-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathmain.cc
165 lines (139 loc) · 4.82 KB
/
main.cc
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
#include "drivers/delay.hh"
#include "drivers/leds.hh"
#include "drivers/pinchange.hh"
#include "drivers/uart.hh"
#include "stm32mp157cxx_ca7.h"
#include <cstdint>
#include "osd32brk_conf.hh"
#include "stm32disco_conf.hh"
// Uncomment one of these to select your board:
namespace Board = OSD32BRK;
// namespace Board = STM32MP1Disco;
namespace BasicIRQ
{
Uart<Board::ConsoleUART> uart;
PinChangeISR<Board::RedLED2::gpio, Board::RedLED2::pin_num> red_led_pinchange;
const auto red_led_irqnum = red_led_pinchange.get_IRQ_num();
PinChangeISR<Board::GreenLED2::gpio, Board::GreenLED2::pin_num> green_led_pinchange;
const auto green_led_irqnum = green_led_pinchange.get_IRQ_num();
uint32_t num_times_red_led_irq_called = 0;
uint32_t num_times_green_led_irq_called = 0;
} // namespace BasicIRQ
void main()
{
using namespace BasicIRQ;
uart.write("\r\n\r\nTesting interrupts\r\n");
Board::RedLED2 red_led;
Board::GreenLED2 green_led;
red_led.off();
green_led.off();
GIC_DisableIRQ(red_led_irqnum);
GIC_SetTarget(red_led_irqnum, 1);
GIC_SetPriority(red_led_irqnum, 0b00000000);
GIC_SetConfiguration(red_led_irqnum, 0b10);
// Toggle the LEDs just to prove the ISR is not getting called
red_led.on();
red_led.off();
red_led.on();
green_led.on();
green_led.off();
green_led.on();
// Enable the ISRs
red_led_pinchange.enable_isr_on_rising_falling_edges(true, false);
red_led_pinchange.enable();
red_led_pinchange.clear_rising_isr_flag();
GIC_ClearPendingIRQ(red_led_irqnum);
GIC_EnableIRQ(red_led_irqnum);
green_led_pinchange.enable_isr_on_rising_falling_edges(true, false);
green_led_pinchange.enable();
green_led_pinchange.clear_rising_isr_flag();
GIC_ClearPendingIRQ(green_led_irqnum);
GIC_EnableIRQ(green_led_irqnum);
// Trigger ISR
uart.write("Triggering ISR: Red LED 1 turning off...\r\n");
Delay::cycles(0x1000000);
uart.write("5 ");
Delay::cycles(0x2000000);
uart.write("\r4 ");
Delay::cycles(0x2000000);
uart.write("\r3 ");
Delay::cycles(0x2000000);
uart.write("\r2 ");
Delay::cycles(0x2000000);
uart.write("\r1 ");
Delay::cycles(0x2000000);
uart.write("\r0 \r");
// Flip the red LED pin, triggering the pin-change interrupt
red_led.off();
Delay::cycles(0x2000000);
uart.write("Triggering ISR: Green LED 1 turning off...\r\n");
Delay::cycles(0x1000000);
uart.write("5 ");
Delay::cycles(0x2000000);
uart.write("\r4 ");
Delay::cycles(0x2000000);
uart.write("\r3 ");
Delay::cycles(0x2000000);
uart.write("\r2 ");
Delay::cycles(0x2000000);
uart.write("\r1 ");
Delay::cycles(0x2000000);
uart.write("\r0 \r");
// Flip the green LED pin, triggering the pin-change interrupt
green_led.off();
int i = 0;
while (1) {
i++;
if (i == 10000) { // plenty of time for ISR to complete
if (num_times_red_led_irq_called == 1)
uart.write("Red LED ISR was called once, hooray!\r\n");
else if (num_times_red_led_irq_called == 0)
uart.write("Red LED ISR was not called, boo.\r\n");
else
uart.write("Red LED ISR was called more than once.. hmmmrr.\r\n");
if (num_times_green_led_irq_called == 1)
uart.write("Green LED ISR was called once, hooray!\r\n");
else if (num_times_green_led_irq_called == 0)
uart.write("Green LED ISR was not called, boo.\r\n");
else
uart.write("Green LED ISR was called more than once.. hmmmrr.\r\n");
while (1)
;
}
};
}
// The vector table says to jump here when the processor receives an IRQ from the GIC.
//
// The interrupt("IRQ") attribute triggers GCC 11 and above to emit a warning about
// clobbering VFP registers. We can safely ignore this (using some #pragmas)
// since we also are using the general_regs_only attribute, and are careful to only
// call functions that do not clobber any VFP registers.
// See: https://github.com/zephyrproject-rtos/zephyr/pull/49704
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wattributes"
extern "C" void __attribute__((general_regs_only, interrupt("IRQ"))) IRQ_Handler()
{
using namespace BasicIRQ;
// Read from the GIC IAR register to get the interrupt number
// IAR means "Interrupt Acknowledge Register".
// By reading this register, we signal to the GIC that we're
// about to handle the interrupt.
auto irqnum = (IRQn_Type)(GICInterface->IAR);
if (irqnum == red_led_irqnum) {
red_led_pinchange.clear_rising_isr_flag();
uart.write(">>> Entering red LED IRQ handler\r\n");
num_times_red_led_irq_called++;
uart.write("<<< Exiting red LED IRQ handler\r\n");
}
if (irqnum == green_led_irqnum) {
green_led_pinchange.clear_rising_isr_flag();
uart.write(">>> Entering green LED IRQ handler\r\n");
num_times_green_led_irq_called++;
uart.write("<<< Exiting green LED IRQ handler\r\n");
}
// Write back the interrupt number into the GIC's EOIR register.
// EOIR means "End of Interrupt Register"
// This tells the GIC we're done handling the interrupt.
GICInterface->EOIR = irqnum;
}
#pragma GCC diagnostic pop