Blame
|
1 | # Handling Interrupts |
||||||
| 2 | ||||||||
|
3 | This actually is very simple. gcc provides the means to mark a function as an interrupt service routine, namely prefixing a function with `__attribute__(interrupt)`. So, something like this: |
||||||
| 4 | ```c |
|||||||
| 5 | __attribute__((interrupt)) duart_interrupt(void) { |
|||||||
| 6 | /* Handle the interrupt */ |
|||||||
|
7 | |||||||
| 8 | } |
|||||||
|
9 | ``` |
||||||
|
10 | But there's a macro in `machine.h` to help, so you could replace the above with: |
||||||
| 11 | ```c |
|||||||
| 12 | #include <machine.h> |
|||||||
| 13 | ||||||||
| 14 | ISR duart_interrupt(void) { |
|||||||
| 15 | /* Handle the interrupt */ |
|||||||
| 16 | ||||||||
| 17 | } |
|||||||
| 18 | ``` |
|||||||
| 19 | gcc knows that functions declared using either of the above methods should end with the `rte` rather than `rts` instruction. |
|||||||
|
20 | |||||||
| 21 | ## Example |
|||||||
| 22 | ```c |
|||||||
| 23 | #include <stdio.h> |
|||||||
| 24 | #include <machine.h> |
|||||||
| 25 | ||||||||
| 26 | static unsigned int ticks = 0; |
|||||||
| 27 | ||||||||
|
28 | ISR isr(void) { |
||||||
|
29 | ticks++; |
||||||
| 30 | ||||||||
| 31 | *pit_tsr = 1; |
|||||||
| 32 | } |
|||||||
| 33 | ||||||||
| 34 | void scan() { |
|||||||
| 35 | static int lednum = 2; |
|||||||
| 36 | static int delta = 1; |
|||||||
| 37 | ||||||||
|
38 | /* create simple visual effect with some of the leds */ |
||||||
|
39 | clear_led(lednum); |
||||||
| 40 | ||||||||
| 41 | lednum += delta; |
|||||||
| 42 | if ((lednum < 2) || (lednum > 7)) { |
|||||||
| 43 | delta = -delta; |
|||||||
| 44 | lednum += delta; |
|||||||
| 45 | lednum += delta; |
|||||||
| 46 | } |
|||||||
| 47 | ||||||||
| 48 | set_led(lednum); |
|||||||
| 49 | } |
|||||||
| 50 | ||||||||
| 51 | int main(void) { |
|||||||
| 52 | unsigned char ivr = *pit_tivr; |
|||||||
| 53 | ||||||||
| 54 | int loop = 0; |
|||||||
| 55 | ||||||||
| 56 | printf("Press any key...\n"); |
|||||||
| 57 | ||||||||
| 58 | _pit_set_counter(1000); |
|||||||
| 59 | *pit_tsr = 1; |
|||||||
| 60 | ||||||||
|
61 | set_isr_handler(ivr, isr); |
||||||
|
62 | |||||||
|
63 | /* Wait for a keypress */ |
||||||
|
64 | while (!_char_available()) { |
||||||
| 65 | printf("%08x\r", ticks); |
|||||||
| 66 | ||||||||
| 67 | loop++; |
|||||||
| 68 | if (loop == 100) { |
|||||||
| 69 | scan(); |
|||||||
| 70 | loop = 0; |
|||||||
| 71 | } |
|||||||
| 72 | } |
|||||||
| 73 | ||||||||
| 74 | _getchar(); |
|||||||
| 75 | } |
|||||||
| 76 | ``` |
|||||||
|
77 | |||||||
| 78 | ## Links |
|||||||
| 79 | - [Article on working with interrupts in C.](https://hackaday.io/project/183861-mackerel-68k-linux-sbcs/log/203533-hardware-timers-vectored-interrupts-exception-handling-in-c) |
|||||||