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.
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @file port_asm.s
|
||||
* @brief ARM Cortex-M0 assembly routines
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.thumb
|
||||
.arch armv6-m
|
||||
|
||||
.section .text
|
||||
|
||||
/* Global symbols */
|
||||
.global current_task_sp
|
||||
.global next_task_sp
|
||||
.global port_context_switch
|
||||
.global port_start_first_task
|
||||
.global port_initialize_task_stack
|
||||
|
||||
/* Variables */
|
||||
.section .bss
|
||||
.align 2
|
||||
current_task_sp: .word 0
|
||||
next_task_sp: .word 0
|
||||
|
||||
.section .text
|
||||
.thumb_func
|
||||
|
||||
/* Start First Task */
|
||||
port_start_first_task:
|
||||
/* Load task stack pointer */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Set PSP */
|
||||
msr PSP, r1
|
||||
|
||||
/* Switch to PSP */
|
||||
movs r0, #2
|
||||
msr CONTROL, r0
|
||||
isb
|
||||
|
||||
/* Restore context */
|
||||
pop {r4-r7}
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
mov r11, r7
|
||||
pop {r4-r7}
|
||||
pop {r0-r3}
|
||||
pop {r12}
|
||||
pop {lr}
|
||||
pop {pc}
|
||||
|
||||
/* PendSV Handler */
|
||||
PendSV_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
subs r0, r0, #32
|
||||
stmia r0!, {r4-r7}
|
||||
mov r4, r8
|
||||
mov r5, r9
|
||||
mov r6, r10
|
||||
mov r7, r11
|
||||
stmia r0!, {r4-r7}
|
||||
subs r0, r0, #32
|
||||
ldr r1, =current_task_sp
|
||||
str r0, [r1]
|
||||
|
||||
/* Load next context */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
ldmia r1!, {r4-r7}
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
mov r11, r7
|
||||
ldmia r1!, {r4-r7}
|
||||
msr PSP, r1
|
||||
bx lr
|
||||
|
||||
/* SVC Handler */
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, MSP
|
||||
mrsne r0, PSP
|
||||
ldr r0, [r0, #24]
|
||||
ldrb r0, [r0, #-2]
|
||||
bx lr
|
||||
|
||||
/* Hard Fault Handler */
|
||||
HardFault_Handler:
|
||||
/* Save registers */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r7}
|
||||
mov r4, r8
|
||||
mov r5, r9
|
||||
mov r6, r10
|
||||
mov r7, r11
|
||||
stmdb r0!, {r4-r7}
|
||||
|
||||
/* Get fault information */
|
||||
mrs r0, BFAR
|
||||
mrs r1, BFSR
|
||||
|
||||
/* Call fault handler */
|
||||
movs r2, #1
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file portmacro.h
|
||||
* @brief ARM Cortex-M0 specific macros
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Data Types */
|
||||
typedef uint32_t port_stack_type_t;
|
||||
typedef uint32_t port_base_type_t;
|
||||
|
||||
/* Architecture Constants */
|
||||
#define PORT_STACK_GROWTH_DIRECTION (-1)
|
||||
#define PORT_BYTE_ALIGNMENT 8
|
||||
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 3
|
||||
|
||||
/* Critical Section Macros */
|
||||
#define portENTER_CRITICAL() __disable_irq()
|
||||
#define portEXIT_CRITICAL() __enable_irq()
|
||||
|
||||
/* Interrupt Control */
|
||||
#define portENABLE_INTERRUPTS() __enable_irq()
|
||||
#define portDISABLE_INTERRUPTS() __disable_irq()
|
||||
|
||||
/* Context Switch */
|
||||
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
|
||||
/* Memory Barriers */
|
||||
#define portMEMORY_BARRIER() __asm volatile("DMB")
|
||||
#define portSYNC_BARRIER() __asm volatile("DSB")
|
||||
#define portINSTRUCTION_BARRIER() __asm volatile("ISB")
|
||||
|
||||
/* NOP */
|
||||
#define portNOP() __asm volatile("NOP")
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* @file port.c
|
||||
* @brief ARM Cortex-M3 architecture specific port
|
||||
* @note Cortex-M3 is widely used in automotive ECUs
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#include "task.h"
|
||||
#include "scheduler.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
/* Context storage */
|
||||
uint32_t* current_task_sp = NULL;
|
||||
uint32_t* next_task_sp = NULL;
|
||||
|
||||
/* Exception priorities */
|
||||
#define SYSTICK_PRIORITY 0xFF
|
||||
#define PENDSV_PRIORITY 0xFF
|
||||
#define SVC_PRIORITY 0x00
|
||||
|
||||
/* Initialize Architecture Port */
|
||||
void port_init(void) {
|
||||
/* Set priority grouping - 4 bits preemption, 0 bits sub-priority */
|
||||
NVIC_SetPriorityGrouping(4);
|
||||
|
||||
/* Configure SysTick */
|
||||
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Set exception priorities */
|
||||
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIORITY);
|
||||
NVIC_SetPriority(PendSV_IRQn, PENDSV_PRIORITY);
|
||||
NVIC_SetPriority(SVCall_IRQn, SVC_PRIORITY);
|
||||
|
||||
/* Enable faults */
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk |
|
||||
SCB_SHCSR_BUSFAULTENA_Msk |
|
||||
SCB_SHCSR_USGFAULTENA_Msk;
|
||||
}
|
||||
|
||||
/* Start First Task */
|
||||
void port_start_first_task(void) {
|
||||
TaskHandle_t first_task = scheduler_get_current_task();
|
||||
|
||||
if (first_task == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set PSP */
|
||||
__set_PSP((uint32_t)first_task->stack_pointer);
|
||||
|
||||
/* Switch to PSP */
|
||||
__set_CONTROL(0x02);
|
||||
__ISB();
|
||||
|
||||
/* Restore context */
|
||||
__asm volatile (
|
||||
"LDMIA R0!, {R4-R11}\n"
|
||||
"MSR PSP, R0\n"
|
||||
"MOV LR, #0xFFFFFFFD\n"
|
||||
"BX LR\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Context Switch */
|
||||
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;
|
||||
|
||||
/* Data synchronization barrier */
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/* Yield */
|
||||
void port_yield(void) {
|
||||
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;
|
||||
|
||||
/* 8-byte alignment */
|
||||
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
|
||||
|
||||
/* Exception frame */
|
||||
*(--stack_ptr) = 0x01000000; /* xPSR */
|
||||
*(--stack_ptr) = (uint32_t)task_function; /* PC */
|
||||
*(--stack_ptr) = 0xFFFFFFFD; /* LR */
|
||||
*(--stack_ptr) = 0x00000000; /* R12 */
|
||||
*(--stack_ptr) = 0x00000003; /* R3 */
|
||||
*(--stack_ptr) = 0x00000002; /* R2 */
|
||||
*(--stack_ptr) = 0x00000001; /* R1 */
|
||||
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
|
||||
|
||||
/* Additional context */
|
||||
*(--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) {
|
||||
extern void kernel_tick_handler(void);
|
||||
kernel_tick_handler();
|
||||
}
|
||||
|
||||
/* PendSV Handler */
|
||||
__attribute__((naked)) void PendSV_Handler(void) {
|
||||
__asm volatile (
|
||||
"MRS R0, PSP\n"
|
||||
"STMDB R0!, {R4-R11}\n"
|
||||
"LDR R1, =current_task_sp\n"
|
||||
"STR R0, [R1]\n"
|
||||
"LDR R0, =next_task_sp\n"
|
||||
"LDR R1, [R0]\n"
|
||||
"LDMIA R1!, {R4-R11}\n"
|
||||
"MSR PSP, R1\n"
|
||||
"BX LR\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* SVC Handler */
|
||||
__attribute__((naked)) void SVC_Handler(void) {
|
||||
__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"
|
||||
"PUSH {LR}\n"
|
||||
"BL svc_handler\n"
|
||||
"POP {LR}\n"
|
||||
"BX LR\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Memory Management Fault Handler */
|
||||
void MemManage_Handler(void) {
|
||||
uint32_t fault_address;
|
||||
uint32_t fault_status;
|
||||
|
||||
fault_address = SCB->MMFAR;
|
||||
fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(2, fault_address, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* Bus Fault Handler */
|
||||
void BusFault_Handler(void) {
|
||||
uint32_t fault_address;
|
||||
uint32_t fault_status;
|
||||
|
||||
fault_address = SCB->BFAR;
|
||||
fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(3, fault_address, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* Usage Fault Handler */
|
||||
void UsageFault_Handler(void) {
|
||||
uint32_t fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(4, 0, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* Hard Fault Handler */
|
||||
void HardFault_Handler(void) {
|
||||
uint32_t fault_address = 0;
|
||||
uint32_t fault_status = SCB->HFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(1, fault_address, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file port_asm.s
|
||||
* @brief ARM Cortex-M3 assembly routines
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.thumb
|
||||
.arch armv7-m
|
||||
|
||||
.section .text
|
||||
|
||||
/* Global symbols */
|
||||
.global current_task_sp
|
||||
.global next_task_sp
|
||||
.global port_context_switch
|
||||
.global port_start_first_task
|
||||
.global port_initialize_task_stack
|
||||
.global port_disable_interrupts
|
||||
.global port_enable_interrupts
|
||||
|
||||
/* Variables */
|
||||
.section .bss
|
||||
.align 2
|
||||
current_task_sp: .word 0
|
||||
next_task_sp: .word 0
|
||||
|
||||
.section .text
|
||||
.thumb_func
|
||||
|
||||
/* Start First Task */
|
||||
port_start_first_task:
|
||||
/* Load task stack pointer */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Set PSP */
|
||||
msr PSP, r1
|
||||
|
||||
/* Switch to PSP */
|
||||
mov r0, #2
|
||||
msr CONTROL, r0
|
||||
isb
|
||||
|
||||
/* Restore context */
|
||||
ldmia r1!, {r4-r11}
|
||||
msr PSP, r1
|
||||
mov lr, #0xFFFFFFFD
|
||||
bx lr
|
||||
|
||||
/* PendSV Handler */
|
||||
PendSV_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
ldr r1, =current_task_sp
|
||||
str r0, [r1]
|
||||
|
||||
/* Load next context */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
ldmia r1!, {r4-r11}
|
||||
msr PSP, r1
|
||||
bx lr
|
||||
|
||||
/* SVC Handler */
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, MSP
|
||||
mrsne r0, PSP
|
||||
ldr r0, [r0, #24]
|
||||
ldrb r0, [r0, #-2]
|
||||
push {lr}
|
||||
bl svc_handler
|
||||
pop {lr}
|
||||
bx lr
|
||||
|
||||
/* Disable Interrupts */
|
||||
port_disable_interrupts:
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/* Enable Interrupts */
|
||||
port_enable_interrupts:
|
||||
cpsie i
|
||||
bx lr
|
||||
|
||||
/* Memory Management Fault */
|
||||
MemManage_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault information */
|
||||
ldr r1, =0xE000ED34 /* MMFAR */
|
||||
ldr r1, [r1]
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #2
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Bus Fault Handler */
|
||||
BusFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault information */
|
||||
ldr r1, =0xE000ED38 /* BFAR */
|
||||
ldr r1, [r1]
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #3
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Usage Fault Handler */
|
||||
UsageFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault status */
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #4
|
||||
movs r1, #0
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Hard Fault Handler */
|
||||
HardFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault status */
|
||||
ldr r2, =0xE000ED2C /* HFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #1
|
||||
movs r1, #0
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file portmacro.h
|
||||
* @brief ARM Cortex-M3 specific macros
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Data Types */
|
||||
typedef uint32_t port_stack_type_t;
|
||||
typedef uint32_t port_base_type_t;
|
||||
|
||||
/* Architecture Constants */
|
||||
#define PORT_STACK_GROWTH_DIRECTION (-1)
|
||||
#define PORT_BYTE_ALIGNMENT 8
|
||||
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 0x50
|
||||
|
||||
/* Critical Section Macros */
|
||||
#define portENTER_CRITICAL() __asm volatile("CPSID I" ::: "memory")
|
||||
#define portEXIT_CRITICAL() __asm volatile("CPSIE I" ::: "memory")
|
||||
|
||||
/* Interrupt Control */
|
||||
#define portENABLE_INTERRUPTS() __asm volatile("CPSIE I" ::: "memory")
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile("CPSID I" ::: "memory")
|
||||
|
||||
/* Context Switch */
|
||||
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
|
||||
/* Memory Barriers */
|
||||
#define portMEMORY_BARRIER() __asm volatile("DMB" ::: "memory")
|
||||
#define portSYNC_BARRIER() __asm volatile("DSB" ::: "memory")
|
||||
#define portINSTRUCTION_BARRIER() __asm volatile("ISB" ::: "memory")
|
||||
|
||||
/* NOP */
|
||||
#define portNOP() __asm volatile("NOP")
|
||||
|
||||
/* Endian Definition */
|
||||
#define portBYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @file port.c
|
||||
* @brief ARM Cortex-M4 architecture specific port with FPU support
|
||||
* @note Cortex-M4 with FPU is common in modern automotive MCUs
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#include "task.h"
|
||||
#include "scheduler.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
/* Context storage */
|
||||
uint32_t* current_task_sp = NULL;
|
||||
uint32_t* next_task_sp = NULL;
|
||||
|
||||
/* FPU context storage */
|
||||
uint32_t current_fpu_context[32];
|
||||
uint32_t next_fpu_context[32];
|
||||
|
||||
/* Exception priorities */
|
||||
#define SYSTICK_PRIORITY 0xFF
|
||||
#define PENDSV_PRIORITY 0xFF
|
||||
#define SVC_PRIORITY 0x00
|
||||
|
||||
/* Initialize Architecture Port */
|
||||
void port_init(void) {
|
||||
/* Set priority grouping - 4 bits preemption, 0 bits sub-priority */
|
||||
NVIC_SetPriorityGrouping(4);
|
||||
|
||||
/* Enable FPU */
|
||||
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));
|
||||
|
||||
/* Configure SysTick */
|
||||
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Set exception priorities */
|
||||
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIORITY);
|
||||
NVIC_SetPriority(PendSV_IRQn, PENDSV_PRIORITY);
|
||||
NVIC_SetPriority(SVCall_IRQn, SVC_PRIORITY);
|
||||
|
||||
/* Enable faults */
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk |
|
||||
SCB_SHCSR_BUSFAULTENA_Msk |
|
||||
SCB_SHCSR_USGFAULTENA_Msk;
|
||||
|
||||
/* Enable divide by zero trap */
|
||||
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
|
||||
|
||||
/* Enable unaligned access trap */
|
||||
SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
|
||||
}
|
||||
|
||||
/* Start First Task */
|
||||
void port_start_first_task(void) {
|
||||
TaskHandle_t first_task = scheduler_get_current_task();
|
||||
|
||||
if (first_task == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restore FPU context if task uses FPU */
|
||||
if (first_task->context[31] & 0x10) {
|
||||
/* FPU was used - restore FPU registers */
|
||||
__asm volatile (
|
||||
"VLDM R0!, {S16-S31}\n"
|
||||
"VLDM R0!, {S0-S15}\n"
|
||||
:
|
||||
: "r" (first_task->context)
|
||||
);
|
||||
}
|
||||
|
||||
/* Set PSP */
|
||||
__set_PSP((uint32_t)first_task->stack_pointer);
|
||||
|
||||
/* Switch to PSP */
|
||||
__set_CONTROL(0x02);
|
||||
__ISB();
|
||||
|
||||
/* Restore context */
|
||||
__asm volatile (
|
||||
"LDMIA R0!, {R4-R11}\n"
|
||||
"MSR PSP, R0\n"
|
||||
"MOV LR, #0xFFFFFFFD\n"
|
||||
"BX LR\n"
|
||||
:
|
||||
: "r" (first_task->stack_pointer)
|
||||
);
|
||||
}
|
||||
|
||||
/* Context Switch */
|
||||
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;
|
||||
|
||||
/* Data synchronization barrier */
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/* Initialize Task Stack with FPU support */
|
||||
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
|
||||
void* parameters,
|
||||
uint32_t* stack_top) {
|
||||
uint32_t* stack_ptr = stack_top;
|
||||
|
||||
/* 8-byte alignment */
|
||||
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
|
||||
|
||||
/* Exception frame with FPU */
|
||||
*(--stack_ptr) = 0x01000000; /* xPSR */
|
||||
*(--stack_ptr) = (uint32_t)task_function; /* PC */
|
||||
*(--stack_ptr) = 0xFFFFFFFD; /* LR */
|
||||
*(--stack_ptr) = 0x00000000; /* R12 */
|
||||
*(--stack_ptr) = 0x00000003; /* R3 */
|
||||
*(--stack_ptr) = 0x00000002; /* R2 */
|
||||
*(--stack_ptr) = 0x00000001; /* R1 */
|
||||
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
|
||||
|
||||
/* Additional context */
|
||||
*(--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 */
|
||||
|
||||
/* FPU context (S0-S31) */
|
||||
for (int i = 0; i < 32; i++) {
|
||||
*(--stack_ptr) = 0;
|
||||
}
|
||||
|
||||
/* FPSCR */
|
||||
*(--stack_ptr) = 0;
|
||||
|
||||
return stack_ptr;
|
||||
}
|
||||
|
||||
/* SysTick Handler */
|
||||
void SysTick_Handler(void) {
|
||||
extern void kernel_tick_handler(void);
|
||||
kernel_tick_handler();
|
||||
}
|
||||
|
||||
/* PendSV Handler with FPU context saving */
|
||||
__attribute__((naked)) void PendSV_Handler(void) {
|
||||
__asm volatile (
|
||||
/* Check if FPU was used */
|
||||
"TST LR, #0x10\n"
|
||||
"IT EQ\n"
|
||||
"BEQ 1f\n"
|
||||
|
||||
/* Save FPU context */
|
||||
"MRS R0, CONTROL\n"
|
||||
"TST R0, #0x04\n"
|
||||
"IT EQ\n"
|
||||
"BEQ 1f\n"
|
||||
|
||||
/* Save FPU registers */
|
||||
"VSTMDB R0!, {S16-S31}\n"
|
||||
"VSTMDB R0!, {S0-S15}\n"
|
||||
|
||||
"1:\n"
|
||||
/* Save core context */
|
||||
"MRS R0, PSP\n"
|
||||
"STMDB R0!, {R4-R11}\n"
|
||||
"LDR R1, =current_task_sp\n"
|
||||
"STR R0, [R1]\n"
|
||||
|
||||
/* Load next context */
|
||||
"LDR R0, =next_task_sp\n"
|
||||
"LDR R1, [R0]\n"
|
||||
"LDMIA R1!, {R4-R11}\n"
|
||||
"MSR PSP, R1\n"
|
||||
|
||||
/* Restore FPU context if needed */
|
||||
"TST LR, #0x10\n"
|
||||
"IT EQ\n"
|
||||
"BEQ 2f\n"
|
||||
|
||||
/* Restore FPU registers */
|
||||
"VLDMIA R0!, {S0-S15}\n"
|
||||
"VLDMIA R0!, {S16-S31}\n"
|
||||
|
||||
"2:\n"
|
||||
"BX LR\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* SVC Handler */
|
||||
__attribute__((naked)) void SVC_Handler(void) {
|
||||
__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"
|
||||
"PUSH {LR}\n"
|
||||
"BL svc_handler\n"
|
||||
"POP {LR}\n"
|
||||
"BX LR\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Fault Handlers */
|
||||
void MemManage_Handler(void) {
|
||||
uint32_t fault_address = SCB->MMFAR;
|
||||
uint32_t fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(2, fault_address, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
void BusFault_Handler(void) {
|
||||
uint32_t fault_address = SCB->BFAR;
|
||||
uint32_t fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(3, fault_address, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
void UsageFault_Handler(void) {
|
||||
uint32_t fault_status = SCB->CFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(4, 0, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
uint32_t fault_status = SCB->HFSR;
|
||||
|
||||
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
|
||||
fault_handler_process(1, 0, fault_status);
|
||||
|
||||
while(1);
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @file port_asm.s
|
||||
* @brief ARM Cortex-M4 assembly routines with FPU support
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.thumb
|
||||
.arch armv7e-m
|
||||
.fpu fpv4-sp-d16
|
||||
|
||||
.section .text
|
||||
|
||||
/* Global symbols */
|
||||
.global current_task_sp
|
||||
.global next_task_sp
|
||||
.global port_context_switch
|
||||
.global port_start_first_task
|
||||
.global port_initialize_task_stack
|
||||
.global port_disable_interrupts
|
||||
.global port_enable_interrupts
|
||||
.global port_enable_fpu
|
||||
.global port_disable_fpu
|
||||
|
||||
/* Variables */
|
||||
.section .bss
|
||||
.align 3
|
||||
current_task_sp: .word 0
|
||||
next_task_sp: .word 0
|
||||
|
||||
.section .text
|
||||
.thumb_func
|
||||
|
||||
/* Start First Task */
|
||||
port_start_first_task:
|
||||
/* Load task stack pointer */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Check if FPU context needs restoring */
|
||||
tst lr, #0x10
|
||||
beq 1f
|
||||
|
||||
/* Restore FPU registers */
|
||||
add r1, r1, #64
|
||||
vldmia r1!, {s16-s31}
|
||||
vldmia r1!, {s0-s15}
|
||||
sub r1, r1, #128
|
||||
|
||||
1:
|
||||
/* Set PSP */
|
||||
msr PSP, r1
|
||||
|
||||
/* Switch to PSP */
|
||||
mov r0, #2
|
||||
msr CONTROL, r0
|
||||
isb
|
||||
|
||||
/* Restore core context */
|
||||
ldmia r1!, {r4-r11}
|
||||
msr PSP, r1
|
||||
mov lr, #0xFFFFFFFD
|
||||
bx lr
|
||||
|
||||
/* PendSV Handler */
|
||||
PendSV_Handler:
|
||||
/* Check if using PSP */
|
||||
mrs r0, CONTROL
|
||||
tst r0, #2
|
||||
beq 1f
|
||||
|
||||
/* Check if FPU was used */
|
||||
tst lr, #0x10
|
||||
beq 1f
|
||||
|
||||
/* Save FPU context */
|
||||
mrs r0, PSP
|
||||
add r0, r0, #64
|
||||
vstmdb r0!, {s16-s31}
|
||||
vstmdb r0!, {s0-s15}
|
||||
|
||||
1:
|
||||
/* Save core context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
ldr r1, =current_task_sp
|
||||
str r0, [r1]
|
||||
|
||||
/* Load next context */
|
||||
ldr r0, =next_task_sp
|
||||
ldr r1, [r0]
|
||||
ldmia r1!, {r4-r11}
|
||||
msr PSP, r1
|
||||
|
||||
/* Restore FPU context if needed */
|
||||
tst lr, #0x10
|
||||
beq 2f
|
||||
|
||||
/* Restore FPU registers */
|
||||
add r1, r1, #64
|
||||
vldmia r1!, {s0-s15}
|
||||
vldmia r1!, {s16-s31}
|
||||
|
||||
2:
|
||||
/* Return from exception */
|
||||
bx lr
|
||||
|
||||
/* SVC Handler */
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, MSP
|
||||
mrsne r0, PSP
|
||||
ldr r0, [r0, #24]
|
||||
ldrb r0, [r0, #-2]
|
||||
push {lr}
|
||||
bl svc_handler
|
||||
pop {lr}
|
||||
bx lr
|
||||
|
||||
/* Enable FPU */
|
||||
port_enable_fpu:
|
||||
/* Enable CP10 and CP11 */
|
||||
ldr r0, =0xE000ED88 /* CPACR */
|
||||
ldr r1, [r0]
|
||||
orr r1, r1, #(0xF << 20)
|
||||
str r1, [r0]
|
||||
dsb
|
||||
isb
|
||||
bx lr
|
||||
|
||||
/* Disable FPU */
|
||||
port_disable_fpu:
|
||||
/* Disable CP10 and CP11 */
|
||||
ldr r0, =0xE000ED88 /* CPACR */
|
||||
ldr r1, [r0]
|
||||
bic r1, r1, #(0xF << 20)
|
||||
str r1, [r0]
|
||||
dsb
|
||||
isb
|
||||
bx lr
|
||||
|
||||
/* Disable Interrupts */
|
||||
port_disable_interrupts:
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/* Enable Interrupts */
|
||||
port_enable_interrupts:
|
||||
cpsie i
|
||||
bx lr
|
||||
|
||||
/* Memory Management Fault */
|
||||
MemManage_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault information */
|
||||
ldr r1, =0xE000ED34 /* MMFAR */
|
||||
ldr r1, [r1]
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #2
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Bus Fault Handler */
|
||||
BusFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault information */
|
||||
ldr r1, =0xE000ED38 /* BFAR */
|
||||
ldr r1, [r1]
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #3
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Usage Fault Handler */
|
||||
UsageFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault status */
|
||||
ldr r2, =0xE000ED28 /* CFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #4
|
||||
movs r1, #0
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
/* Hard Fault Handler */
|
||||
HardFault_Handler:
|
||||
/* Save context */
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
/* Get fault status */
|
||||
ldr r2, =0xE000ED2C /* HFSR */
|
||||
ldr r2, [r2]
|
||||
|
||||
/* Call fault handler */
|
||||
movs r0, #1
|
||||
movs r1, #0
|
||||
bl fault_handler_process
|
||||
|
||||
/* Infinite loop */
|
||||
b .
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file portmacro.h
|
||||
* @brief ARM Cortex-M4 specific macros with FPU support
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stm32f4xx.h" /* Adjust for specific MCU */
|
||||
|
||||
/* Data Types */
|
||||
typedef uint32_t port_stack_type_t;
|
||||
typedef uint32_t port_base_type_t;
|
||||
|
||||
/* Architecture Constants */
|
||||
#define PORT_STACK_GROWTH_DIRECTION (-1)
|
||||
#define PORT_BYTE_ALIGNMENT 8
|
||||
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 0x50
|
||||
|
||||
/* Critical Section Macros */
|
||||
#define portENTER_CRITICAL() __asm volatile("CPSID I" ::: "memory")
|
||||
#define portEXIT_CRITICAL() __asm volatile("CPSIE I" ::: "memory")
|
||||
|
||||
/* Interrupt Control */
|
||||
#define portENABLE_INTERRUPTS() __asm volatile("CPSIE I" ::: "memory")
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile("CPSID I" ::: "memory")
|
||||
|
||||
/* Context Switch */
|
||||
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
|
||||
|
||||
/* Memory Barriers */
|
||||
#define portMEMORY_BARRIER() __asm volatile("DMB" ::: "memory")
|
||||
#define portSYNC_BARRIER() __asm volatile("DSB" ::: "memory")
|
||||
#define portINSTRUCTION_BARRIER() __asm volatile("ISB" ::: "memory")
|
||||
|
||||
/* NOP */
|
||||
#define portNOP() __asm volatile("NOP")
|
||||
|
||||
/* FPU Control */
|
||||
#define portENABLE_FPU() \
|
||||
do { \
|
||||
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
} while(0)
|
||||
|
||||
#define portDISABLE_FPU() \
|
||||
do { \
|
||||
SCB->CPACR &= ~((3UL << 10*2) | (3UL << 11*2)); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
} while(0)
|
||||
|
||||
/* Endian Definition */
|
||||
#define portBYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
/* Optimization */
|
||||
#define portFORCE_INLINE __attribute__((always_inline)) inline
|
||||
|
||||
/* Task Utilities */
|
||||
#define portTASK_RETURN_ADDRESS (0xFFFFFFFD)
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
Reference in New Issue
Block a user