移植到 CH32V10x 既 QingKeV3 系列 MCU 上
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <os_loopdelay.h>
|
||||
|
||||
#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 */
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef INCLUDED_OS_LOOPDELAY_H
|
||||
#define INCLUDED_OS_LOOPDELAY_H
|
||||
|
||||
#ifndef INCLUDED_OS_TYPES_H
|
||||
#include <os_types.h>
|
||||
#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*/
|
||||
@@ -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; i<STACK_FRAME_SIZE/sizeof(os_uintptr_t); i++){
|
||||
((os_uintptr_t*)(p_frame))[i] = 0x5ac0ffee;
|
||||
}
|
||||
|
||||
p_frame->mepc = (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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
#include <qkv3.h>
|
||||
@@ -0,0 +1,226 @@
|
||||
#ifndef INCLUDED_QKV3_H
|
||||
#define INCLUDED_QKV3_H
|
||||
|
||||
|
||||
#ifndef INCLUDED_OS_TYPES_H
|
||||
#include <os_types.h>
|
||||
#endif /*INCLUDED_OS_TYPES_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_COMPILER_H
|
||||
#include <os_compiler.h>
|
||||
#endif /*INCLUDED_OS_COMPILER_H*/
|
||||
|
||||
#ifndef INCLUDED_RISCV_H
|
||||
#include <riscv.h>
|
||||
#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*/
|
||||
@@ -0,0 +1,278 @@
|
||||
#include <riscv.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
#ifndef INCLUDED_RISCV_H
|
||||
#define INCLUDED_RISCV_H
|
||||
|
||||
#ifndef INCLUDED_OS_TYPES_H
|
||||
#include <os_types.h>
|
||||
#endif /*INCLUDED_OS_TYPES_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_COMPILER_H
|
||||
#include <os_compiler.h>
|
||||
#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*/
|
||||
Reference in New Issue
Block a user