Hello everyone! This post introduces stm32f4xx interrupts and their usage from assembly language. The goal is to react on user-button push (a blue one) using external interrupt. To reach this goal without involving the interrupt we would write a loop “listening” the input level on the pin. That’s a really bad idea because our application should be able to do other useful stuff.
A usual application configures all needed interrupts, peripherals etc. at init stage an then just falls into infinite loop that does nothing - or even it may go to a sleep mode, waking up just to process events and after that go to sleep again.
To introduce an external interrupt I configure port’s A zero pin as input with pulldown resistor. Connecting pulldown resistor guarantees low level at the pin when button is not pressed. Then I configure this pin as the source for external interrupt line 0 - stm32f4xx has a rather flexible external interrupt system (please, refer the user manual). After that additionally I need to mask which lines can generate an interrupt request - in our case it is line 0.
The “master” of all interrupts and events inside stm32 is the NVIC core peripheral (please refer to stm32 programming manual - which is a very useful resource). To get things work I should enable the interrupt coming from channel EXT0_IRQn = 6 (this information is summarized in the interrupt vector table, see stm32 reference manual, page 371. Finally I associate some routine to be an interrupt handler by placing it’s address to appropriate offset within interrupt vector table.
Let’s beging coding. Code for startup and init_clock routines I’ve taken from clock control on stm32f4discovery post. So, the clock source is HSE with 8 MHz crystal. No PLL is used.
I’ve decided to share for you two variants of code working with the user button. While I was struggling to make the external interrupt work I wrote a code which works with the user button through a usual loop as a starting point.
Here it is. Now, I’m trying to be modular while writing code. Defined constants are included below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
|
The executable is free to download. Hope you will get that nice flashing on button pushed.
But as I said earlier that is a bad idea of application design. This code idea is narrow and tied up. We need to use a mini operating system approach not to be tied up. What is it about? The system boots, enables and configures some services needed and then just waits for events. The next code example is exactly about that. Note the b .
line which means “jump at current address” - the endless loop. After button is pushed the core will jump to _exti_0 and after execution return back to this loop. Whenever a new functionality is needed - it’s easy enough to attach it.
Here is the code and defined constants.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
Ready executable: download.
Note the stack usage in these examples. The routine preserves registers’ contents by pushing it into the stack at the very start of execution and popping it before leave. I think that is absolutely necessary in interrupt handle routines because of randomity of accesses to them. Though, I may be wrong and there may be better aproaches to that.
Feel free to write for conversations.