Files
root ca13734bf0 Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers,
middleware (CAN stack, diagnostics, safety), applications, board
support, build/test tooling, and documentation.
2026-08-23 03:35:29 -04:00

196 lines
5.2 KiB
C

/**
* @file port.c
* @brief ARM Cortex-M0 architecture specific port
* @note Cortex-M0 is used in low-power automotive applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
/* Global variables for context switching */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* Initialize Architecture Port */
void port_init(void) {
/* Configure SysTick for 1ms interrupts */
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Set lowest priority for SysTick and PendSV */
NVIC_SetPriority(SysTick_IRQn, 3);
NVIC_SetPriority(PendSV_IRQn, 3);
/* Enable interrupts */
__enable_irq();
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Set PSP to task stack pointer */
__set_PSP((uint32_t)first_task->stack_pointer);
/* Switch to using PSP */
__set_CONTROL(0x02);
__ISB();
/* Restore context and start task */
__asm volatile (
"POP {R4-R7}\n"
"MOV R8, R4\n"
"MOV R9, R5\n"
"MOV R10, R6\n"
"MOV R11, R7\n"
"POP {R4-R7}\n"
"POP {R0-R3}\n"
"POP {R12}\n"
"POP {LR}\n"
"POP {PC}\n"
);
}
/* Context Switch Trigger */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger PendSV */
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Yield from ISR */
void port_yield_from_isr(void) {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
__disable_irq();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
__enable_irq();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* Align stack to 8 bytes */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
/* Initial stack frame for Cortex-M0 */
*(--stack_ptr) = 0x01000000; /* xPSR */
*(--stack_ptr) = (uint32_t)task_function; /* PC */
*(--stack_ptr) = 0xFFFFFFFD; /* LR (return to thread mode) */
*(--stack_ptr) = 0x00000000; /* R12 */
*(--stack_ptr) = 0x00000003; /* R3 */
*(--stack_ptr) = 0x00000002; /* R2 */
*(--stack_ptr) = 0x00000001; /* R1 */
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
/* Additional registers */
*(--stack_ptr) = 0x0000000B; /* R11 */
*(--stack_ptr) = 0x0000000A; /* R10 */
*(--stack_ptr) = 0x00000009; /* R9 */
*(--stack_ptr) = 0x00000008; /* R8 */
*(--stack_ptr) = 0x00000007; /* R7 */
*(--stack_ptr) = 0x00000006; /* R6 */
*(--stack_ptr) = 0x00000005; /* R5 */
*(--stack_ptr) = 0x00000004; /* R4 */
return stack_ptr;
}
/* SysTick Handler */
void SysTick_Handler(void) {
/* Increment tick count */
extern void kernel_tick_handler(void);
kernel_tick_handler();
}
/* PendSV Handler */
void PendSV_Handler(void) {
/* Save current context */
__asm volatile (
"MRS R0, PSP\n"
"SUBS R0, R0, #32\n"
"STMIA R0!, {R4-R7}\n"
"MOV R4, R8\n"
"MOV R5, R9\n"
"MOV R6, R10\n"
"MOV R7, R11\n"
"STMIA R0!, {R4-R7}\n"
"SUBS R0, R0, #32\n"
"LDR R1, =current_task_sp\n"
"STR R0, [R1]\n"
);
/* Load next context */
__asm volatile (
"LDR R0, =next_task_sp\n"
"LDR R1, [R0]\n"
"LDMIA R1!, {R4-R7}\n"
"MOV R8, R4\n"
"MOV R9, R5\n"
"MOV R10, R6\n"
"MOV R11, R7\n"
"LDMIA R1!, {R4-R7}\n"
"MSR PSP, R1\n"
"BX LR\n"
);
}
/* SVC Handler */
void SVC_Handler(void) {
/* Handle system calls */
__asm volatile (
"TST LR, #4\n"
"ITE EQ\n"
"MRSEQ R0, MSP\n"
"MRSNE R0, PSP\n"
"LDR R0, [R0, #24]\n"
"LDRB R0, [R0, #-2]\n"
"BX LR\n"
);
}
/* Hard Fault Handler */
void HardFault_Handler(void) {
/* Save fault information */
uint32_t fault_address;
uint32_t fault_status;
__asm volatile (
"MRS %0, BFAR\n"
"MRS %1, BFSR\n"
: "=r" (fault_address), "=r" (fault_status)
);
/* Call fault handler */
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(1, fault_address, fault_status);
/* Infinite loop */
while(1);
}