ICARUS OS (Intelligent Cooperative Architecture for Real-time Unified Systems) 0.1.0
Preemptive Real-Time Operating System for ARM Cortex-M7
Loading...
Searching...
No Matches
stm32h7xx_it.c
Go to the documentation of this file.
1/* USER CODE BEGIN Header */
18/* USER CODE END Header */
19
20/* Includes ------------------------------------------------------------------*/
21#include "bsp/config.h"
22
23#include "stm32h7xx_it.h"
24/* Private includes ----------------------------------------------------------*/
25/* USER CODE BEGIN Includes */
26#include <stdbool.h>
27#include "icarus/config.h"
28#include "icarus/svc.h"
29#ifndef HOST_TEST
30#include "st7735.h"
31#include "lcd.h"
32#endif
33#ifdef HOST_TEST
34// For host testing, include mock header for os_yield_pendsv
35#include "mock_asm.h"
36#endif
37/* USER CODE END Includes */
38
39/* Private typedef -----------------------------------------------------------*/
40/* USER CODE BEGIN TD */
41
42/* USER CODE END TD */
43
44/* Private define ------------------------------------------------------------*/
45/* USER CODE BEGIN PD */
46/* ITCM_FUNC and ITCM_FUNC are defined in icarus/config.h */
47/* USER CODE END PD */
48
49/* Private macro -------------------------------------------------------------*/
50/* USER CODE BEGIN PM */
51
52/* USER CODE END PM */
53
54/* Private variables ---------------------------------------------------------*/
55/* USER CODE BEGIN PV */
56
57/* USER CODE END PV */
58
59/* Private function prototypes -----------------------------------------------*/
60/* USER CODE BEGIN PFP */
61
62/* USER CODE END PFP */
63
64/* Private user code ---------------------------------------------------------*/
65/* USER CODE BEGIN 0 */
66
67/* USER CODE END 0 */
68
69/* External variables --------------------------------------------------------*/
70extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
71/* USER CODE BEGIN EV */
72
73/* USER CODE END EV */
74
75/******************************************************************************/
76/* Cortex Processor Interruption and Exception Handlers */
77/******************************************************************************/
81void NMI_Handler(void)
82{
83 /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
84
85 /* USER CODE END NonMaskableInt_IRQn 0 */
86 /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
87 while (1)
88 {
89 }
90 /* USER CODE END NonMaskableInt_IRQn 1 */
91}
92
96#ifndef HOST_TEST
98{
99 /* Capture fault info from SCB */
100 volatile uint32_t cfsr = SCB->CFSR;
101 volatile uint32_t hfsr = SCB->HFSR;
102 volatile uint32_t mmfar = SCB->MMFAR;
103 volatile uint32_t bfar = SCB->BFAR;
104 (void)cfsr; (void)hfsr; (void)mmfar; (void)bfar;
105
106 /* Extract stacked PC via PSP or MSP */
107 uint32_t *sp;
108 __asm__ volatile ("tst lr, #4\n"
109 "ite eq\n"
110 "mrseq %0, msp\n"
111 "mrsne %0, psp\n"
112 : "=r" (sp));
113 volatile uint32_t stacked_r0 = sp[0];
114 volatile uint32_t stacked_r1 = sp[1];
115 volatile uint32_t stacked_r2 = sp[2];
116 volatile uint32_t stacked_r3 = sp[3];
117 volatile uint32_t stacked_r12 = sp[4];
118 volatile uint32_t stacked_lr = sp[5];
119 volatile uint32_t stacked_pc = sp[6];
120 volatile uint32_t stacked_psr = sp[7];
121 (void)stacked_r0; (void)stacked_r1; (void)stacked_r2; (void)stacked_r3;
122 (void)stacked_r12; (void)stacked_lr; (void)stacked_pc; (void)stacked_psr;
123
124 /* Fast LED blink = HardFault (3 fast blinks, pause, repeat) */
125 while (1)
126 {
127 for (int i = 0; i < 3; i++) {
128 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_SET);
129 for (volatile int d = 0; d < 16000000; d++) {}
130 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_RESET);
131 for (volatile int d = 0; d < 16000000; d++) {}
132 }
133 for (volatile int d = 0; d < 160000000; d++) {}
134 }
135}
136#else
137void HardFault_Handler(void) { while (1) {} }
138#endif
139
140/* Incremented by recoverable MemManage faults */
141volatile uint32_t g_memmanage_fault_count = 0;
142
143/* Debug: capture last fault address */
144volatile uint32_t g_last_fault_addr = 0;
145volatile uint32_t g_last_fault_pc = 0;
146
158#ifndef HOST_TEST
160{
161 uint32_t cfsr = SCB->CFSR;
162
163 /* MemManage fault types:
164 * DACCVIOL (bit 1) = data access violation (read or write)
165 * IACCVIOL (bit 0) = instruction fetch violation — not recoverable here
166 * MMARVALID (bit 7) = MMFAR holds valid fault address */
167 bool is_daccviol = (cfsr & SCB_CFSR_DACCVIOL_Msk) != 0;
168 bool is_iaccviol = (cfsr & SCB_CFSR_IACCVIOL_Msk) != 0;
169
170 /* Check if fault came from thread mode (PSP) vs kernel (MSP) */
171 uint32_t lr_val;
172 __asm__ volatile ("mov %0, lr" : "=r" (lr_val));
173 bool from_psp = (lr_val & 0x4) != 0;
174
175 /* Recover from data access violations (read or write) from unprivileged tasks */
176 if (is_daccviol && !is_iaccviol && from_psp) {
177 /* Recoverable: advance stacked PC past the faulting Thumb instruction */
178 uint32_t *sp;
179 __asm__ volatile ("mrs %0, psp" : "=r" (sp));
180
181 /* Capture fault address for debugging */
182 if (cfsr & SCB_CFSR_MMARVALID_Msk) {
183 g_last_fault_addr = SCB->MMFAR;
184 } else {
185 g_last_fault_addr = 0xFFFFFFFF; /* Invalid */
186 }
187 g_last_fault_pc = sp[6];
188
189 /* Determine instruction length: Thumb-2 (32-bit) vs Thumb (16-bit)
190 * Thumb-2 instructions have bits [15:11] >= 0b11101 (0x1D)
191 * See ARMv7-M Architecture Reference Manual A6.3 */
192 uint16_t *pc_ptr = (uint16_t *)sp[6];
193 uint16_t instr = *pc_ptr;
194 uint8_t instr_len = ((instr & 0xF800) >= 0xE800) ? 4 : 2;
195
196 sp[6] += instr_len; /* stacked PC is at offset 6 in the exception frame */
197
198 /* Clear the fault status bits so we can return cleanly */
199 SCB->CFSR = cfsr;
200
202
203 /* Lower limit for ITCM protection debugging - fail fast after 3 faults */
204 if (g_memmanage_fault_count > 30) {
205 /* Fault info captured in g_last_fault_addr and g_last_fault_pc */
206 /* Fall through to halt with 4 blinks */
207 } else {
208 return;
209 }
210 }
211
212 /* Non-recoverable: 4 fast blinks = MemManage */
213 while (1)
214 {
215 for (int i = 0; i < 4; i++) {
216 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_SET);
217 for (volatile int d = 0; d < 16000000; d++) {}
218 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_RESET);
219 for (volatile int d = 0; d < 16000000; d++) {}
220 }
221 for (volatile int d = 0; d < 160000000; d++) {}
222 }
223}
224#else
225void MemManage_Handler(void) { while (1) {} }
226#endif
227
231#ifndef HOST_TEST
233{
234 volatile uint32_t cfsr = SCB->CFSR;
235 volatile uint32_t bfar = SCB->BFAR;
236 (void)cfsr; (void)bfar;
237
238 /* 5 fast blinks = BusFault */
239 while (1)
240 {
241 for (int i = 0; i < 5; i++) {
242 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_SET);
243 for (volatile int d = 0; d < 16000000; d++) {}
244 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_RESET);
245 for (volatile int d = 0; d < 16000000; d++) {}
246 }
247 for (volatile int d = 0; d < 160000000; d++) {}
248 }
249}
250#else
251void BusFault_Handler(void) { while (1) {} }
252#endif
253
257#ifndef HOST_TEST
259{
260 volatile uint32_t cfsr = SCB->CFSR;
261 (void)cfsr;
262
263 /* 6 fast blinks = UsageFault */
264 while (1)
265 {
266 for (int i = 0; i < 6; i++) {
267 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_SET);
268 for (volatile int d = 0; d < 16000000; d++) {}
269 HAL_GPIO_WritePin(E3_GPIO_Port, E3_Pin, GPIO_PIN_RESET);
270 for (volatile int d = 0; d < 16000000; d++) {}
271 }
272 for (volatile int d = 0; d < 160000000; d++) {}
273 }
274}
275#else
276void UsageFault_Handler(void) { while (1) {} }
277#endif
278
282#ifdef HOST_TEST
283void SVC_Handler(void)
284{
285 /* Empty for host testing */
286}
287#else
288ITCM_FUNC __attribute__((naked)) void SVC_Handler(void)
289{
290 __asm__ volatile (
291 "tst lr, #4\n"
292 "ite eq\n"
293 "mrseq r0, msp\n"
294 "mrsne r0, psp\n"
295 "b SVC_Handler_C\n"
296 );
297}
298#endif
299
304{
305 /* USER CODE BEGIN DebugMonitor_IRQn 0 */
306
307 /* USER CODE END DebugMonitor_IRQn 0 */
308 /* USER CODE BEGIN DebugMonitor_IRQn 1 */
309
310 /* USER CODE END DebugMonitor_IRQn 1 */
311}
312
316#ifdef HOST_TEST
317// For host testing, use regular function (not naked) to call mock
318void PendSV_Handler(void)
319{
320 /* USER CODE BEGIN PendSV_IRQn 0 */
321 os_yield_pendsv();
322 /* USER CODE END PendSV_IRQn 0 */
323 /* USER CODE BEGIN PendSV_IRQn 1 */
324
325 /* USER CODE END PendSV_IRQn 1 */
326}
327#else
328ITCM_FUNC __attribute__ ((naked)) void PendSV_Handler(void)
329{
330 /* USER CODE BEGIN PendSV_IRQn 0 */
331 __asm__ volatile (
332 "b os_yield_pendsv"
333 );
334
335 /* USER CODE END PendSV_IRQn 0 */
336 /* USER CODE BEGIN PendSV_IRQn 1 */
337
338 /* USER CODE END PendSV_IRQn 1 */
339}
340#endif
341
347{
348 /* USER CODE BEGIN SysTick_IRQn 0 */
349 extern volatile uint32_t os_tick_count;
350 extern volatile uint8_t os_running;
351 extern volatile uint32_t current_task_ticks_remaining;
352 extern volatile bool scheduler_enabled;
353
355
356 if ((os_running != 0u) && (--current_task_ticks_remaining == 0u) && (scheduler_enabled)) {
358 SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
359 }
360
361 /* USER CODE END SysTick_IRQn 0 */
362 HAL_IncTick();
363 /* USER CODE BEGIN SysTick_IRQn 1 */
364
365 /* USER CODE END SysTick_IRQn 1 */
366}
367
368/******************************************************************************/
369/* STM32H7xx Peripheral Interrupt Handlers */
370/* Add here the Interrupt Handlers for the used peripherals. */
371/* For the available peripheral interrupt handler names, */
372/* please refer to the startup file (startup_stm32h7xx.s). */
373/******************************************************************************/
374
379{
380 /* USER CODE BEGIN OTG_FS_IRQn 0 */
381
382 /* USER CODE END OTG_FS_IRQn 0 */
383 HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
384 /* USER CODE BEGIN OTG_FS_IRQn 1 */
385
386 /* USER CODE END OTG_FS_IRQn 1 */
387}
388
389/* USER CODE BEGIN 1 */
390
391/* USER CODE END 1 */
#define E3_Pin
Definition config.h:134
#define E3_GPIO_Port
Definition config.h:135
#define ICARUS_TICKS_PER_TASK
Number of SysTick interrupts per task time slice.
Definition config.h:97
ICARUS OS Configuration Header.
#define ITCM_FUNC
Definition config.h:155
volatile uint32_t current_task_ticks_remaining
Ticks remaining in current task's time slice.
Definition kernel.c:66
volatile uint8_t os_running
Flag indicating OS is running.
Definition kernel.c:70
volatile uint32_t os_tick_count
System tick counter.
Definition kernel.c:69
volatile bool scheduler_enabled
Scheduler enable flag.
Definition kernel.c:72
volatile uint32_t g_last_fault_pc
void UsageFault_Handler(void)
This function handles Undefined instruction or illegal state.
void HardFault_Handler(void)
This function handles Hard fault interrupt.
void MemManage_Handler(void)
This function handles Memory management fault.
volatile uint32_t g_last_fault_addr
void SVC_Handler(void)
This function handles System service call via SWI instruction.
PCD_HandleTypeDef hpcd_USB_OTG_FS
void PendSV_Handler(void)
This function handles Pendable request for system service.
void NMI_Handler(void)
This function handles Non maskable interrupt.
void OTG_FS_IRQHandler(void)
This function handles USB On The Go FS global interrupt.
void BusFault_Handler(void)
This function handles Pre-fetch fault, memory access fault.
void SysTick_Handler(void)
This function handles System tick timer.
volatile uint32_t g_memmanage_fault_count
void DebugMon_Handler(void)
This function handles Debug monitor.
This file contains the headers of the interrupt handlers.
ICARUS Supervisor Call (SVC) Definitions.