diff --git a/Base/os_compiler.h b/Base/os_compiler.h index ded8d83..0c6e452 100644 --- a/Base/os_compiler.h +++ b/Base/os_compiler.h @@ -5,6 +5,7 @@ #define OS_STATIC_FORCE_INLINE static inline __attribute__((always_inline)) #define OS_ALIGNED(x) __attribute__((aligned(x))) #define OS_WEAK __attribute__((weak)) + #define OS_USED __attribute__((used)) #define OS_PACKED_STRUCT(x) struct __attribute__((packed)) x #define OS_SECTION(n) __attribute__((section(#n))) #define OS_NORETURN __attribute__((noreturn)) diff --git a/CPU/ARM_Cortex_M3/os_port.c b/CPU/ARM_Cortex_M3/os_port.c index 7796c54..cfa7fea 100644 --- a/CPU/ARM_Cortex_M3/os_port.c +++ b/CPU/ARM_Cortex_M3/os_port.c @@ -213,6 +213,11 @@ void os_sched(void){ } } +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]; @@ -241,7 +246,4 @@ void SVC_Handler_C(os_uintptr_t* svc_args){ } } -void SysTick_Handler(void){ - os_systick_tick(); -} diff --git a/CPU/QingKeV3/os_loopdelay.c b/CPU/QingKeV3/os_loopdelay.c new file mode 100644 index 0000000..84a7d4a --- /dev/null +++ b/CPU/QingKeV3/os_loopdelay.c @@ -0,0 +1,10 @@ +#include + +#if defined (__GNUC__) /*!< GNU Compiler */ +__attribute__((naked)) +void os_loop_delay(unsigned long ulCount){ + __asm(" add a0, a0, -1 \n" + " bne x0, a0, os_loop_delay \n" + " ret "); +} +#endif /* __CC_ARM */ \ No newline at end of file diff --git a/CPU/QingKeV3/os_loopdelay.h b/CPU/QingKeV3/os_loopdelay.h new file mode 100644 index 0000000..ba0bacd --- /dev/null +++ b/CPU/QingKeV3/os_loopdelay.h @@ -0,0 +1,34 @@ +#ifndef INCLUDED_OS_LOOPDELAY_H +#define INCLUDED_OS_LOOPDELAY_H + +#ifndef INCLUDED_OS_TYPES_H +#include +#endif /*INCLUDED_OS_TYPES_H*/ + +#define OS_LOOP_DELAY_US(n) (n * SystemCoreClock/3000000) +#define OS_LOOP_DELAY_MS(n) (n * SystemCoreClock/3000) +#define OS_LOOP_DELAY_S(n) (n * SystemCoreClock/3) + +/* + + 72Mhz时钟时,当ulCount为1时,函数耗时3个时钟,延时=3*1/72us=1/24us + + SystemCoreClock=72000000 + + us级延时,延时n微秒 + LoopDelay(n*(SystemCoreClock/3000000)); + + ms级延时,延时n毫秒 + LoopDelay(n*(SystemCoreClock/3000)); + + m级延时,延时n秒 + LoopDelay(n*(SystemCoreClock/3)); +*/ + +void os_loop_delay(unsigned long ulCount); + +#define OS_LoopDelayUS(n) os_loop_delay(OS_LOOP_DELAY_US(n)) +#define OS_LoopDelayMS(n) os_loop_delay(OS_LOOP_DELAY_MS(n)) +#define OS_LoopDelayS(n) os_loop_delay(OS_LOOP_DELAY_S(n)) + +#endif /*INCLUDED_OS_LOOPDELAY_H*/ diff --git a/CPU/QingKeV3/os_port.c b/CPU/QingKeV3/os_port.c new file mode 100644 index 0000000..869ea3c --- /dev/null +++ b/CPU/QingKeV3/os_port.c @@ -0,0 +1,198 @@ +#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" +#include "qkv3.h" + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +#define SysTick_IRQn 12 +#define Software_IRQn 14 + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +static uint32_t _SysTick_Config(os_tick_t ticks) +{ + QKV3_PFIC->CFGR=0xFA050003; /* 关闭硬件压栈和嵌套 */ + /* + 位段值含义: + Bit [31:16] :0xFA05 - 解锁密钥 (Key)。为了防止误触发,修改中断全局配置通常需要写入固定的“钥匙”值。 + Bit[1] :1(来自0x3) - 硬件压栈使能 (HPE)。开启后,硬件会自动保存寄存器状态,大幅提升中断响应速度。 + Bit[0] :1(来自0x3) - 嵌套中断使能 (NEST)。允许高优先级中断打断低优先级中断。 + */ + + QKV3_NVIC_SetPriority(SysTick_IRQn,0xf0); + QKV3_NVIC_SetPriority(Software_IRQn,0xf0); + QKV3_SysTick->CTLR=0; + QKV3_SysTick->CNTL0=0;QKV3_SysTick->CNTL1=0;QKV3_SysTick->CNTL2=0;QKV3_SysTick->CNTL3=0; + QKV3_SysTick->CNTH0=0;QKV3_SysTick->CNTH1=0;QKV3_SysTick->CNTH2=0;QKV3_SysTick->CNTH3=0; + QKV3_SysTick->CMPLR0=(uint8_t)(ticks-1); + QKV3_SysTick->CMPLR1=(uint8_t)((ticks-1)>>8); + QKV3_SysTick->CMPLR2=(uint8_t)((ticks-1)>>16); + QKV3_SysTick->CMPLR3=(uint8_t)((ticks-1)>>24); + QKV3_SysTick->CMPHR0=0;QKV3_SysTick->CMPHR1=0;QKV3_SysTick->CMPHR2=0;QKV3_SysTick->CMPHR3=0; + QKV3_SysTick->CTLR=0x1; + QKV3_NVIC_EnableIRQ(SysTick_IRQn); + QKV3_NVIC_EnableIRQ(Software_IRQn); + return 0; +} + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +typedef struct { + os_uintptr_t mepc; /* zero, 用于 epc 保存 */ + os_uintptr_t ra; /* 返回地址 */ + os_uintptr_t mstatus; /* 栈指针, 用于mstatus */ + os_uintptr_t gp; /* 全局指针 */ + os_uintptr_t tp; /* 线程指针 */ + os_uintptr_t t0; /* 临时寄存器0 */ + os_uintptr_t t1; /* 临时寄存器1 */ + os_uintptr_t t2; /* 临时寄存器2 */ + os_uintptr_t s0; /* s0/fp */ + os_uintptr_t s1; /* 保存寄存器1 */ + os_uintptr_t a0; /* 函数参数/返回值 */ + os_uintptr_t a1; /* 函数参数 */ + os_uintptr_t a2; /* 函数参数 */ + os_uintptr_t a3; /* 函数参数 */ + os_uintptr_t a4; /* 函数参数 */ + os_uintptr_t a5; /* 函数参数 */ + os_uintptr_t a6; /* 函数参数 */ + os_uintptr_t a7; /* 函数参数 */ + os_uintptr_t s2; /* 保存寄存器 */ + os_uintptr_t s3; /* 保存寄存器 */ + os_uintptr_t s4; /* 保存寄存器 */ + os_uintptr_t s5; /* 保存寄存器 */ + os_uintptr_t s6; /* 保存寄存器 */ + os_uintptr_t s7; /* 保存寄存器 */ + os_uintptr_t s8; /* 保存寄存器 */ + os_uintptr_t s9; /* 保存寄存器 */ + os_uintptr_t s10; /* 保存寄存器 */ + os_uintptr_t s11; /* 保存寄存器 */ + os_uintptr_t t3; /* 临时寄存器 */ + os_uintptr_t t4; /* 临时寄存器 */ + os_uintptr_t t5; /* 临时寄存器 */ + os_uintptr_t t6; /* 临时寄存器 */ +}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); /* 实际栈大小 */ + + os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE); + for(os_size_t i=0; imepc = (os_uintptr_t)entry; + p_frame->a0 = (os_uintptr_t)param; + p_frame->ra = (os_uintptr_t)exit_entry; + + 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_disable_irq(void){ + RISCV_disable_irq(); +} + +void os_port_enable_irq(void){ + RISCV_enable_irq(); +} + +os_uint_t os_port_save_disable_irq(void){ + return os_port_save_disable_irq_in_isr(); +} + +void os_port_restore_irq(os_uint_t level){ + os_port_restore_irq_in_isr(level); +} + +os_uint_t os_port_save_disable_irq_in_isr(void){ + os_uint_t level = RISCV_get_MSTATUS(); + RISCV_set_MSTATUS(0x1800); + return level; +} + +void os_port_restore_irq_in_isr(os_uint_t level){ + RISCV_set_MSTATUS(level); +} + +void os_sched(void){ + os_sched_in_isr(); +} + + +extern volatile os_uint_t SystemCoreClock; + +OS_WEAK +void os_port_init(void){ + +} + +OS_WEAK +void os_port_startup(void){ + _SysTick_Config(SystemCoreClock/8/OS_CFG_TICKS_PER_SECOND); +} + +/* + * 发出上下文切换的请求 + */ +void os_port_send_context_switch_request(void){ + QKV3_NVIC_SetPendingIRQ(Software_IRQn); +} + +/* + * 清除上下文切换的请求 + */ +void os_port_clear_context_switch_request(void){ + QKV3_NVIC_ClearPendingIRQ(Software_IRQn); +} + +extern void os_port_context_restore(os_uintptr_t to); + +OS_USED +void os_port_context_switch(void* from_sp, void* to_sp){ + os_critical_enter_in_isr(); + if(g_os_port_context_switch_flag==OS_TRUE){ + os_critical_leave_in_isr(); + return; + } + g_os_port_context_switch_flag = OS_TRUE; + if(from_sp==0){ + g_os_port_switch_to_sp = to_sp; + os_critical_leave_in_isr(); + os_port_context_restore((os_uintptr_t)to_sp); + }else{ + g_os_port_switch_from_sp = from_sp; + g_os_port_switch_to_sp = to_sp; + os_critical_leave_in_isr(); + os_port_send_context_switch_request(); + } +} + + +void SysTick_Handler(void) __attribute__((interrupt())); +void SysTick_Handler(void){ + QKV3_SysTick->CTLR=0; + QKV3_SysTick->CNTL0=0;QKV3_SysTick->CNTL1=0;QKV3_SysTick->CNTL2=0;QKV3_SysTick->CNTL3=0; + QKV3_SysTick->CNTH0=0;QKV3_SysTick->CNTH1=0;QKV3_SysTick->CNTH2=0;QKV3_SysTick->CNTH3=0; + QKV3_SysTick->CTLR=0x1; + + // 调用系统心跳处理 + os_systick_tick(); +} + diff --git a/CPU/QingKeV3/os_port_gnu.S b/CPU/QingKeV3/os_port_gnu.S new file mode 100644 index 0000000..760cfd3 --- /dev/null +++ b/CPU/QingKeV3/os_port_gnu.S @@ -0,0 +1,173 @@ + .section .text.SW_Handler,"ax",@progbits + .global SW_Handler + .p2align 2 /* 4 bytes align */ + .func +SW_Handler: + /* save all from thread context */ + addi sp, sp, -32 * 4 + sw x5, 5 * 4(sp) /* 保存 t0, 后面要使用这个寄存器 */ + + csrr t0, mstatus /* 读取 mstatus */ + sw t0, 2 * 4(sp) /* 保存到 x2 位置 */ + + li t0,0x1800 /* 关闭中断,并进入 M-Mode 模式 */ + csrw mstatus, t0 + + csrr t0, mepc /* 额外保存 mepc 到 x0 位置 */ + sw t0, 0 * 4(sp) + + sw x1, 1 * 4(sp) /* return address */ + sw x4, 4 * 4(sp) /* tp */ + sw x6, 6 * 4(sp) + sw x7, 7 * 4(sp) + sw x8, 8 * 4(sp) + sw x9, 9 * 4(sp) + sw x10, 10 * 4(sp) + sw x11, 11 * 4(sp) + sw x12, 12 * 4(sp) + sw x13, 13 * 4(sp) + sw x14, 14 * 4(sp) + sw x15, 15 * 4(sp) + sw x16, 16 * 4(sp) + sw x17, 17 * 4(sp) + sw x18, 18 * 4(sp) + sw x19, 19 * 4(sp) + sw x20, 20 * 4(sp) + sw x21, 21 * 4(sp) + sw x22, 22 * 4(sp) + sw x23, 23 * 4(sp) + sw x24, 24 * 4(sp) + sw x25, 25 * 4(sp) + sw x26, 26 * 4(sp) + sw x27, 27 * 4(sp) + sw x28, 28 * 4(sp) + sw x29, 29 * 4(sp) + sw x30, 30 * 4(sp) + sw x31, 31 * 4(sp) + + la s0, g_os_port_switch_from_sp /* 更新旧任务栈指针 */ + lw s1, 0(s0) + sw sp, 0(s1) + + /* ---------- 收尾工作 ---------- */ + jal os_port_on_switch_success + + /* ---------- 切换到新任务 ---------- */ + + la s0, g_os_port_switch_to_sp /* 加载新任务栈指针 */ + lw s1, 0(s0) + lw sp, 0(s1) + + lw t0, 0 * 4(sp) /* 恢复 mepc 指针 */ + csrw mepc, t0 /* 将 t0 值写入 mepc */ + + lw x1, 1 * 4(sp) /* 加载 return address */ + + lw t0, 2*4(sp) /* 将栈里面的 mstatus 恢复 */ + csrs mstatus, t0 /* 设置 MPIE = 1 */ + + lw x4, 4 * 4(sp) /* 恢复其它寄存器 */ + lw x5, 5 * 4(sp) + lw x6, 6 * 4(sp) + lw x7, 7 * 4(sp) + lw x8, 8 * 4(sp) + lw x9, 9 * 4(sp) + lw x10, 10 * 4(sp) + lw x11, 11 * 4(sp) + lw x12, 12 * 4(sp) + lw x13, 13 * 4(sp) + lw x14, 14 * 4(sp) + lw x15, 15 * 4(sp) + lw x16, 16 * 4(sp) + lw x17, 17 * 4(sp) + lw x18, 18 * 4(sp) + lw x19, 19 * 4(sp) + lw x20, 20 * 4(sp) + lw x21, 21 * 4(sp) + lw x22, 22 * 4(sp) + lw x23, 23 * 4(sp) + lw x24, 24 * 4(sp) + lw x25, 25 * 4(sp) + lw x26, 26 * 4(sp) + lw x27, 27 * 4(sp) + lw x28, 28 * 4(sp) + lw x29, 29 * 4(sp) + lw x30, 30 * 4(sp) + lw x31, 31 * 4(sp) + addi sp, sp, 32 * 4 /* 出栈 */ + + mret + .endfunc + + + /* + * void os_port_context_restore(os_uintptr_t to); + * a0 --> to + * a1 --> to_thread + */ + .section .text.os_port_context_restore,"ax",@progbits + .globl os_port_context_restore + .func + .p2align 2 /* 4 bytes align */ +os_port_context_restore: + /* first save interrupt stack */ + la t0, _eusrstack + addi t0, t0, -512 + csrw mscratch,t0 + + /* keep machine mode */ + li t0, 0x1800 + csrw mstatus, t0 + + /* ---------- 收尾工作 ---------- */ + jal os_port_on_switch_success + + + /* ---- Load target sp ---- */ + + lw sp, (a0) /* 将 to 的指针加载到 sp */ + + /* resw ra to mepc */ + lw a0, 0 * 4(sp) + csrw mepc, a0 + + lw x1, 1 * 4(sp) /* 返回地址 */ + lw x4, 4 * 4(sp) + lw x5, 5 * 4(sp) + lw x6, 6 * 4(sp) + lw x7, 7 * 4(sp) + lw x8, 8 * 4(sp) + lw x9, 9 * 4(sp) + lw x10, 10 * 4(sp) + lw x11, 11 * 4(sp) + lw x12, 12 * 4(sp) + lw x13, 13 * 4(sp) + lw x14, 14 * 4(sp) + lw x15, 15 * 4(sp) + lw x16, 16 * 4(sp) + lw x17, 17 * 4(sp) + lw x18, 18 * 4(sp) + lw x19, 19 * 4(sp) + lw x20, 20 * 4(sp) + lw x21, 21 * 4(sp) + lw x22, 22 * 4(sp) + lw x23, 23 * 4(sp) + lw x24, 24 * 4(sp) + lw x25, 25 * 4(sp) + lw x26, 26 * 4(sp) + lw x27, 27 * 4(sp) + lw x28, 28 * 4(sp) + lw x29, 29 * 4(sp) + lw x30, 30 * 4(sp) + lw x31, 31 * 4(sp) + + lw t0, 2*4(sp) + csrs mstatus, t0 + + addi sp, sp, 32 * 4 + + mret + .endfunc + + + .end \ No newline at end of file diff --git a/CPU/QingKeV3/qkv3.c b/CPU/QingKeV3/qkv3.c new file mode 100644 index 0000000..c598600 --- /dev/null +++ b/CPU/QingKeV3/qkv3.c @@ -0,0 +1 @@ +#include diff --git a/CPU/QingKeV3/qkv3.h b/CPU/QingKeV3/qkv3.h new file mode 100644 index 0000000..a676fcd --- /dev/null +++ b/CPU/QingKeV3/qkv3.h @@ -0,0 +1,226 @@ +#ifndef INCLUDED_QKV3_H +#define INCLUDED_QKV3_H + + +#ifndef INCLUDED_OS_TYPES_H +#include +#endif /*INCLUDED_OS_TYPES_H*/ + +#ifndef INCLUDED_OS_COMPILER_H +#include +#endif /*INCLUDED_OS_COMPILER_H*/ + +#ifndef INCLUDED_RISCV_H +#include +#endif /*INCLUDED_RISCV_H*/ + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +#ifdef __cplusplus +#define __I volatile /* defines 'read only' permissions */ +#else +#define __I volatile const /* defines 'read only' permissions */ +#endif +#define __O volatile /* defines 'write only' permissions */ +#define __IO volatile /* defines 'read / write' permissions */ + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +#define QKV3_PFIC ((QKV3_PFIC_Type *) 0xE000E000 ) +#define QKV3_NVIC QKV3_PFIC +#define QKV3_NVIC_KEY1 ((uint32_t)0xFA050000) +#define QKV3_NVIC_KEY2 ((uint32_t)0xBCAF0000) +#define QKV3_NVIC_KEY3 ((uint32_t)0xBEEF0000) + +#define QKV3_SysTick ((QKV3_SysTick_Type *) 0xE000F000) + + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +typedef enum {QKV3_NoREADY = 0, QKV3_READY = !QKV3_NoREADY} QKV3_ErrorStatus; + +typedef enum {QKV3_DISABLE = 0, QKV3_ENABLE = !QKV3_DISABLE} QKV3_FunctionalState; + +typedef enum {QKV3_RESET = 0, QKV3_SET = !QKV3_RESET} QKV3_FlagStatus, QKV3_ITStatus; + +/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ +typedef struct{ + __I uint32_t ISR[8]; + __I uint32_t IPR[8]; + __IO uint32_t ITHRESDR; + __IO uint32_t VTFBADDRR; + __IO uint32_t CFGR; + __I uint32_t GISR; + uint8_t RESERVED0[0x10]; + __IO uint32_t VTFADDRR[4]; + uint8_t RESERVED1[0x90]; + __O uint32_t IENR[8]; + uint8_t RESERVED2[0x60]; + __O uint32_t IRER[8]; + uint8_t RESERVED3[0x60]; + __O uint32_t IPSR[8]; + uint8_t RESERVED4[0x60]; + __O uint32_t IPRR[8]; + uint8_t RESERVED5[0x60]; + __IO uint32_t IACTR[8]; + uint8_t RESERVED6[0xE0]; + __IO uint8_t IPRIOR[256]; + uint8_t RESERVED7[0x810]; + __IO uint32_t SCTLR; +}QKV3_PFIC_Type; + +/* memory mapped structure for SysTick */ +typedef struct +{ + __IO uint32_t CTLR; + __IO uint8_t CNTL0; + __IO uint8_t CNTL1; + __IO uint8_t CNTL2; + __IO uint8_t CNTL3; + __IO uint8_t CNTH0; + __IO uint8_t CNTH1; + __IO uint8_t CNTH2; + __IO uint8_t CNTH3; + __IO uint8_t CMPLR0; + __IO uint8_t CMPLR1; + __IO uint8_t CMPLR2; + __IO uint8_t CMPLR3; + __IO uint8_t CMPHR0; + __IO uint8_t CMPHR1; + __IO uint8_t CMPHR2; + __IO uint8_t CMPHR3; +}QKV3_SysTick_Type; + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_EnableIRQ(uint32_t IRQn) +{ + QKV3_NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_DisableIRQ(uint32_t IRQn) +{ + uint32_t t; + + t = QKV3_NVIC->ITHRESDR; + QKV3_NVIC->ITHRESDR = 0x10; + QKV3_NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); + QKV3_NVIC->ITHRESDR = t; +} + +OS_STATIC_FORCE_INLINE +uint32_t QKV3_NVIC_GetStatusIRQ(uint32_t IRQn) +{ + return((uint32_t) ((QKV3_NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +OS_STATIC_FORCE_INLINE +uint32_t QKV3_NVIC_GetPendingIRQ(uint32_t IRQn) +{ + return((uint32_t) ((QKV3_NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_SetPendingIRQ(uint32_t IRQn) +{ + QKV3_NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_ClearPendingIRQ(uint32_t IRQn) +{ + QKV3_NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +OS_STATIC_FORCE_INLINE +uint32_t QKV3_NVIC_GetActive(uint32_t IRQn) +{ + return((uint32_t)((QKV3_NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_SetPriority(uint32_t IRQn, uint8_t priority) +{ + QKV3_NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; +} + +OS_STATIC_FORCE_INLINE +void QKV3_WFI(void) +{ + QKV3_NVIC->SCTLR &= ~(1<<3); // wfi + asm volatile ("wfi"); +} + +OS_STATIC_FORCE_INLINE +void QKV3_SEV(void) +{ + QKV3_NVIC->SCTLR |= (1<<3)|(1<<5); +} + +OS_STATIC_FORCE_INLINE +void QKV3_WFE(void) +{ + QKV3_NVIC->SCTLR |= (1<<3); + asm volatile ("wfi"); +} + +OS_STATIC_FORCE_INLINE +void QKV3__WFE(void) +{ + QKV3_SEV(); + QKV3_WFE(); + QKV3_WFE(); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_SetFastIRQ(uint32_t addr, uint32_t IRQn, uint8_t num) +{ + if(num > 3) return ; + QKV3_NVIC->VTFBADDRR = addr; + QKV3_NVIC->VTFADDRR[num] = ((uint32_t)IRQn<<24)|(addr&0xfffff); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_SystemReset(void) +{ + QKV3_NVIC->CFGR = QKV3_NVIC_KEY3|(1<<7); +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_HaltPushCfg(QKV3_FunctionalState NewState) +{ + if (NewState != QKV3_DISABLE) + { + QKV3_NVIC->CFGR = QKV3_NVIC_KEY1; + } + else + { + QKV3_NVIC->CFGR = QKV3_NVIC_KEY1|(1<<0); + } +} + +OS_STATIC_FORCE_INLINE +void QKV3_NVIC_INTNestCfg(QKV3_FunctionalState NewState) +{ + if (NewState != QKV3_DISABLE) + { + QKV3_NVIC->CFGR = QKV3_NVIC_KEY1; + } + else + { + QKV3_NVIC->CFGR = QKV3_NVIC_KEY1|(1<<1); + } +} + + + +#endif /*INCLUDED_QKV3_H*/ diff --git a/CPU/QingKeV3/riscv.c b/CPU/QingKeV3/riscv.c new file mode 100644 index 0000000..d084634 --- /dev/null +++ b/CPU/QingKeV3/riscv.c @@ -0,0 +1,278 @@ +#include + +#define __ASM __asm /* asm keyword for GNU Compiler */ +#define __INLINE inline /* inline keyword for GNU Compiler */ + + + +/********************************************************************* + * @fn RISCV_get_MSTATUS + * + * @brief Return the Machine Status Register + * + * @return mstatus value + */ +uint32_t RISCV_get_MSTATUS(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mstatus": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MSTATUS + * + * @brief Set the Machine Status Register + * + * @param value - set mstatus value + * + * @return none + */ +void RISCV_set_MSTATUS(uint32_t value) +{ + __ASM volatile("csrw mstatus, %0" : : "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MISA + * + * @brief Return the Machine ISA Register + * + * @return misa value + */ +uint32_t RISCV_get_MISA(void) +{ + uint32_t result; + + __ASM volatile("csrr %0,""misa" : "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MISA + * + * @brief Set the Machine ISA Register + * + * @param value - set misa value + * + * @return none + */ +void RISCV_set_MISA(uint32_t value) +{ + __ASM volatile("csrw misa, %0" : : "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MTVEC + * + * @brief Return the Machine Trap-Vector Base-Address Register + * + * @return mtvec value + */ +uint32_t RISCV_get_MTVEC(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mtvec": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MTVEC + * + * @brief Set the Machine Trap-Vector Base-Address Register + * + * @param value - set mtvec value + * + * @return none + */ +void RISCV_set_MTVEC(uint32_t value) +{ + __ASM volatile("csrw mtvec, %0":: "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MSCRATCH + * + * @brief Return the Machine Seratch Register + * + * @return mscratch value + */ +uint32_t RISCV_get_MSCRATCH(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mscratch" : "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MSCRATCH + * + * @brief Set the Machine Seratch Register + * + * @param value - set mscratch value + * + * @return none + */ +void RISCV_set_MSCRATCH(uint32_t value) +{ + __ASM volatile("csrw mscratch, %0" : : "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MEPC + * + * @brief Return the Machine Exception Program Register + * + * @return mepc value + */ +uint32_t RISCV_get_MEPC(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mepc" : "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MEPC + * + * @brief Set the Machine Exception Program Register + * + * @return mepc value + */ +void RISCV_set_MEPC(uint32_t value) +{ + __ASM volatile("csrw mepc, %0" : : "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MCAUSE + * + * @brief Return the Machine Cause Register + * + * @return mcause value + */ +uint32_t RISCV_get_MCAUSE(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mcause": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MEPC + * + * @brief Set the Machine Cause Register + * + * @return mcause value + */ +void RISCV_set_MCAUSE(uint32_t value) +{ + __ASM volatile("csrw mcause, %0":: "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MTVAL + * + * @brief Return the Machine Trap Value Register + * + * @return mtval value + */ +uint32_t RISCV_get_MTVAL(void) +{ + uint32_t result; + + __ASM volatile("csrr %0," "mtval" : "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_set_MTVAL + * + * @brief Set the Machine Trap Value Register + * + * @return mtval value + */ +void RISCV_set_MTVAL(uint32_t value) +{ + __ASM volatile("csrw mtval, %0":: "r"(value)); +} + +/********************************************************************* + * @fn RISCV_get_MVENDORID + * + * @brief Return Vendor ID Register + * + * @return mvendorid value + */ +uint32_t RISCV_get_MVENDORID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0,""mvendorid": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_get_MARCHID + * + * @brief Return Machine Architecture ID Register + * + * @return marchid value + */ +uint32_t RISCV_get_MARCHID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0,""marchid": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_get_MIMPID + * + * @brief Return Machine Implementation ID Register + * + * @return mimpid value + */ +uint32_t RISCV_get_MIMPID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0,""mimpid": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_get_MHARTID + * + * @brief Return Hart ID Register + * + * @return mhartid value + */ +uint32_t RISCV_get_MHARTID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0,""mhartid": "=r"(result)); + return (result); +} + +/********************************************************************* + * @fn RISCV_get_SP + * + * @brief Return SP Register + * + * @return SP value + */ +uint32_t RISCV_get_SP(void) +{ + uint32_t result; + + __ASM volatile("mv %0,""sp": "=r"(result):); + return (result); +} diff --git a/CPU/QingKeV3/riscv.h b/CPU/QingKeV3/riscv.h new file mode 100644 index 0000000..55b0c9d --- /dev/null +++ b/CPU/QingKeV3/riscv.h @@ -0,0 +1,239 @@ +#ifndef INCLUDED_RISCV_H +#define INCLUDED_RISCV_H + +#ifndef INCLUDED_OS_TYPES_H +#include +#endif /*INCLUDED_OS_TYPES_H*/ + +#ifndef INCLUDED_OS_COMPILER_H +#include +#endif /*INCLUDED_OS_COMPILER_H*/ + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +OS_STATIC_FORCE_INLINE +void RISCV_enable_irq() +{ + __asm volatile ("csrs mstatus, %0" : : "r" (0x88) ); +} + +OS_STATIC_FORCE_INLINE +void RISCV_disable_irq() +{ + __asm volatile ("csrc mstatus, %0" : : "r" (0x88) ); +} + +OS_STATIC_FORCE_INLINE +void RISCV_NOP() +{ + __asm volatile ("nop"); +} + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +/********************************************************************* + * @fn __AMOADD_W + * + * @brief Atomic Add with 32bit value + * Atomically ADD 32bit value with value in memory using amoadd.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ADDed + * + * @return return memory value + add value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOADD_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoadd.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + + +/********************************************************************* + * @fn __AMOAND_W + * + * @brief Atomic And with 32bit value + * Atomically AND 32bit value with value in memory using amoand.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ANDed + * + * @return return memory value & and value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOAND_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoand.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + + +/********************************************************************* + * @fn __AMOMAX_W + * + * @brief Atomic signed MAX with 32bit value + * Atomically signed max compare 32bit value with value in memory using amomax.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return return the bigger value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOMAX_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomax.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +OS_STATIC_FORCE_INLINE +uint32_t RISCV_AMOMAXU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amomaxu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMIN_W + * + * @brief Atomic signed MIN with 32bit value + * Atomically signed min compare 32bit value with value in memory using amomin.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return return the smaller value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOMIN_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomin.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMINU_W + * + * @brief Atomic unsigned MIN with 32bit value + * Atomically unsigned min compare 32bit value with value in memory using amominu.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return return the smaller value + */ +OS_STATIC_FORCE_INLINE +uint32_t RISCV_AMOMINU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amominu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOOR_W + * + * @brief Atomic OR with 32bit value + * Atomically OR 32bit value with value in memory using amoor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ORed + * + * @return return memory value | and value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOSWAP_W + * + * @brief Atomically swap new 32bit value into memory using amoswap.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * newval - New value to be stored into the address + * + * @return return the original value in memory + */ +OS_STATIC_FORCE_INLINE +uint32_t RISCV_AMOSWAP_W(volatile uint32_t *addr, uint32_t newval) +{ + uint32_t result; + + __asm volatile ("amoswap.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(newval) : "memory"); + return result; +} + +/********************************************************************* + * @fn __AMOXOR_W + * + * @brief Atomic XOR with 32bit value + * Atomically XOR 32bit value with value in memory using amoxor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be XORed + * + * @return return memory value ^ and value + */ +OS_STATIC_FORCE_INLINE +int32_t RISCV_AMOXOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoxor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* */ + +extern uint32_t RISCV_get_MSTATUS(void); +extern void RISCV_set_MSTATUS(uint32_t value); +extern uint32_t RISCV_get_MISA(void); +extern void RISCV_set_MISA(uint32_t value); +extern uint32_t RISCV_get_MTVEC(void); +extern void RISCV_set_MTVEC(uint32_t value); +extern uint32_t RISCV_get_MSCRATCH(void); +extern void RISCV_set_MSCRATCH(uint32_t value); +extern uint32_t RISCV_get_MEPC(void); +extern void RISCV_set_MEPC(uint32_t value); +extern uint32_t RISCV_get_MCAUSE(void); +extern void RISCV_set_MCAUSE(uint32_t value); +extern uint32_t RISCV_get_MTVAL(void); +extern void RISCV_set_MTVAL(uint32_t value); +extern uint32_t RISCV_get_MVENDORID(void); +extern uint32_t RISCV_get_MARCHID(void); +extern uint32_t RISCV_get_MIMPID(void); +extern uint32_t RISCV_get_MHARTID(void); +extern uint32_t RISCV_get_SP(void); + +#endif /*INCLUDED_RISCV_H*/ diff --git a/Kernel/SingleCore/os.h b/Kernel/SingleCore/os.h index 632df85..35eb21f 100644 --- a/Kernel/SingleCore/os.h +++ b/Kernel/SingleCore/os.h @@ -5,6 +5,10 @@ #include "os_types.h" #endif /* INCLUDED_OS_TYPES_H */ +#ifndef INCLUDED_OS_ALIGN_H +#include +#endif /*INCLUDED_OS_ALIGN_H*/ + #ifndef INCLUDED_OS_COMPILER_H #include "os_compiler.h" #endif /* INCLUDED_OS_COMPILER_H */ @@ -13,6 +17,10 @@ #include "os_macros.h" #endif /* INCLUDED_OS_MACROS_H */ +#ifndef INCLUDED_OS_ENDIAN_H +#include +#endif /*INCLUDED_OS_ENDIAN_H*/ + #ifndef INCLUDED_OS_SCHED_H #include #endif /*INCLUDED_OS_SCHED_H*/ @@ -57,6 +65,10 @@ #include #endif /*INCLUDED_OS_FAIRLOCK_H*/ +#ifndef INCLUDED_OS_IDLE_H +#include +#endif /*INCLUDED_OS_IDLE_H*/ + /* ==================================================================================================== */ diff --git a/Kernel/SingleCore/os_config.h.in b/Kernel/SingleCore/os_config.h.in index 54c8815..92d72d8 100644 --- a/Kernel/SingleCore/os_config.h.in +++ b/Kernel/SingleCore/os_config.h.in @@ -44,4 +44,16 @@ #define OS_CFG_DEVICE_MAX 10 #endif /* OS_CFG_DEVICE_MAX */ +#ifndef OS_CFG_IDLE_TASK_TICKS +#define OS_CFG_IDLE_TASK_TICKS 5 +#endif /*OS_CFG_IDLE_TASK_TICKS*/ + +#ifndef OS_CFG_IDLE_TASK_STACK_SIZE +#define OS_CFG_IDLE_TASK_STACK_SIZE 1024 +#endif /*OS_CFG_IDLE_TASK_STACK_SIZE*/ + +#ifndef OS_CFG_IDLE_TASK_PRIORITY +#define OS_CFG_IDLE_TASK_PRIORITY OS_PRIORITY_IDLE +#endif /*OS_CFG_IDLE_TASK_PRIORITY*/ + #endif /*INCLUDED_OS_CONFIG_H*/ diff --git a/Kernel/SingleCore/os_port.c b/Kernel/SingleCore/os_port.c index e6cbec4..c3a1070 100644 --- a/Kernel/SingleCore/os_port.c +++ b/Kernel/SingleCore/os_port.c @@ -12,13 +12,14 @@ volatile os_bool_t g_os_port_context_switch_flag; void os_port_on_switch_success(void){ - os_critical_enter_in_isr(); +// os_critical_enter_in_isr(); g_os_sched_current_task_p = g_os_port_switch_to_sp; g_os_sched_current_task_p->state = kOsTaskState_Running; g_os_port_context_switch_flag = OS_FALSE; - os_critical_leave_in_isr(); +// os_critical_leave_in_isr(); } +OS_WEAK void os_port_context_switch(void* from_sp, void* to_sp){ os_critical_enter_in_isr(); if(g_os_port_context_switch_flag==OS_TRUE){ diff --git a/Kernel/SingleCore/os_port.h b/Kernel/SingleCore/os_port.h index dba36cb..7a0d3ad 100644 --- a/Kernel/SingleCore/os_port.h +++ b/Kernel/SingleCore/os_port.h @@ -33,8 +33,8 @@ os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param /* * 请求上下文切换 - * @param from_sp - 切换的源头任务栈 - * @param to_sp - 切换的目标任务栈 + * @param from_sp - 切换的源头任务栈指针 + * @param to_sp - 切换的目标任务栈指针 */ void os_port_context_switch(void* from_sp, void* to_sp);