148 lines
4.2 KiB
C
148 lines
4.2 KiB
C
#include "os_port.h"
|
|||
|
|
#include "os_stack.h"
|
||
|
|
#include "os_macros.h"
|
||
|
|
#include "os_align.h"
|
||
|
|
#include "os_compiler.h"
|
||
|
|
#include "os_systick.h"
|
||
|
|
#include "os_sched.h"
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
volatile os_uint_t svc_exc_return;
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
#if(OS_CFG_CPU_FPU_PRESENT)
|
||
|
|
os_uintptr_t s16;
|
||
|
|
os_uintptr_t s17;
|
||
|
|
os_uintptr_t s18;
|
||
|
|
os_uintptr_t s19;
|
||
|
|
os_uintptr_t s20;
|
||
|
|
os_uintptr_t s21;
|
||
|
|
os_uintptr_t s22;
|
||
|
|
os_uintptr_t s23;
|
||
|
|
os_uintptr_t s24;
|
||
|
|
os_uintptr_t s25;
|
||
|
|
os_uintptr_t s26;
|
||
|
|
os_uintptr_t s27;
|
||
|
|
os_uintptr_t s28;
|
||
|
|
os_uintptr_t s29;
|
||
|
|
os_uintptr_t s30;
|
||
|
|
os_uintptr_t s31;
|
||
|
|
#endif
|
||
|
|
/* ==== 以下为手动压栈部分 ==== */
|
||
|
|
os_uintptr_t exc_return; /* r2 - LR */ /* 这是地址最小的位置 */
|
||
|
|
os_uintptr_t control; /* r3 */
|
||
|
|
os_uintptr_t r4;
|
||
|
|
os_uintptr_t r5;
|
||
|
|
os_uintptr_t r6;
|
||
|
|
os_uintptr_t r7;
|
||
|
|
os_uintptr_t r8;
|
||
|
|
os_uintptr_t r9;
|
||
|
|
os_uintptr_t r10;
|
||
|
|
os_uintptr_t r11;
|
||
|
|
/* ==== 以下为自动压栈部分 ==== */
|
||
|
|
os_uintptr_t r0;
|
||
|
|
os_uintptr_t r1;
|
||
|
|
os_uintptr_t r2;
|
||
|
|
os_uintptr_t r3;
|
||
|
|
os_uintptr_t r12;
|
||
|
|
os_uintptr_t lr;
|
||
|
|
os_uintptr_t pc;
|
||
|
|
os_uintptr_t xPSR;
|
||
|
|
}os_stack_frame_t;
|
||
|
|
|
||
|
|
#define STACK_FRAME_SIZE sizeof(os_stack_frame_t)
|
||
|
|
|
||
|
|
os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param
|
||
|
|
, void* stack_base, os_size_t stack_size, void(*exit_entry)(void)){
|
||
|
|
os_uintptr_t stack_max = (os_uintptr_t)((uint8_t *) stack_base + stack_size);
|
||
|
|
os_uintptr_t real_max = OS_ALIGN_DOWN(stack_max, OS_ALIGN_SIZE); /* 实际栈顶的位置,对齐后的位置 */
|
||
|
|
stack_size -= (stack_max - real_max); /* 实际栈大小 */
|
||
|
|
|
||
|
|
uint8_t flag = 0x01;
|
||
|
|
os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE);
|
||
|
|
for(os_size_t i=0; i<STACK_FRAME_SIZE/sizeof(os_uintptr_t); i++){
|
||
|
|
((os_uintptr_t*)(p_frame))[i] = ((os_uintptr_t)flag<<24)|((os_uintptr_t)flag<<16)|((os_uintptr_t)flag<<8)|flag;
|
||
|
|
flag++;
|
||
|
|
}
|
||
|
|
|
||
|
|
p_frame->r0 = (os_uintptr_t)param; /* 任务参数 */
|
||
|
|
p_frame->pc = (os_uintptr_t)entry; /* 任务入口 */
|
||
|
|
p_frame->lr = (os_uintptr_t)exit_entry; /* 退出地址 */
|
||
|
|
|
||
|
|
p_frame->xPSR = (1u << 24); /* THUMB */
|
||
|
|
p_frame->control = 0x03; /* 任务使用用户权限,栈使用 PSP */
|
||
|
|
p_frame->exc_return = 0xFFFFFFFDul; /* 任务在中断中切换,这里是退出中断的设置 */
|
||
|
|
|
||
|
|
os_stack_t stack;
|
||
|
|
stack.min = (os_uintptr_t)stack_base;
|
||
|
|
stack.max = (os_uintptr_t)real_max;
|
||
|
|
stack.type = kOsStackType_MaxToMin;
|
||
|
|
stack.sp = p_frame;
|
||
|
|
return stack;
|
||
|
|
}
|
||
|
|
|
||
|
|
void os_port_init(void){
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void os_port_startup(void){
|
||
|
|
NVIC_SetPriority(PendSV_IRQn, 0xff);
|
||
|
|
NVIC_SetPriority(SVCall_IRQn, OS_CFG_SYSCALL_PRIORITY);
|
||
|
|
SysTick_Config(SystemCoreClock/OS_CFG_TICKS_PER_SECOND);
|
||
|
|
}
|
||
|
|
|
||
|
|
void os_port_send_context_switch_request(void){
|
||
|
|
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
||
|
|
}
|
||
|
|
|
||
|
|
void os_port_clear_context_switch_request(void){
|
||
|
|
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
|
||
|
|
}
|
||
|
|
|
||
|
|
void os_sched(void){
|
||
|
|
if(is_cpu_in_privilege()){
|
||
|
|
os_sched_in_isr();
|
||
|
|
}else{
|
||
|
|
cpu_sched_in_svc();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void SysTick_Handler(void){
|
||
|
|
os_systick_tick();
|
||
|
|
}
|
||
|
|
|
||
|
|
void SVC_Handler_C(os_uintptr_t* svc_args){
|
||
|
|
// 读取系统调用号:它存储在原本的 PC 指令前两个字节
|
||
|
|
uint8_t svc_number = ((uint8_t *)svc_args[6])[-2];
|
||
|
|
switch (svc_number) {
|
||
|
|
case CPU_SYSCALL_ID:{
|
||
|
|
os_uint_t op = svc_args[0];
|
||
|
|
switch (op) {
|
||
|
|
case CPU_SYSCALL_OP_SAVE_DISABLE_IRQ:{
|
||
|
|
svc_args[0] = os_port_save_disable_irq_in_isr();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case CPU_SYSCALL_OP_RESTORE_IRQ:{
|
||
|
|
os_port_restore_irq_in_isr(svc_args[1]);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case CPU_SYSCALL_OP_SCHED:{
|
||
|
|
os_sched_in_isr();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default: break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|