未验证 提交 b9e4fcfc 编写于 作者: Y Yaochenger 提交者: GitHub

[libcpu][riscv]整合libcpu/riscv中的移植文件 提供一份公共代码于common (#6941)

整合libcpu/riscv中的移植文件 提供一份公共代码于common

在提交本pr时,除hpmicro的内核,rv32内核bsp已完成去除大部分的冗余,大部分代码采用common中的实现。本pr的作用是进一步统一common中的文件,从而提供一份公用代码,新移植的RV32内核的BSP可以全部使用common代码。

- 在common中提供一份公用文件:interrupt_gcc.S
- 修改原有的文件,将原有的中断中上下文切换代码替换为interrupt_gcc.S
- 基于上述修改,修改仓库中risc-v内核的BSP与移植相关的部分 (主要包含中断入口函数 中断栈等)
- 在common中提供一份公用文件:trap_common.c;提供统一中断入口函数,中断入口函数初始化,中断入口注册等函数,并完善异常时的信息输出

- 在common中提供一份公用文件:rt_hw_stack_frame.h;将栈帧结构体剥离,供用户使用

- 在上述工作完成后,在上述工作的基础上测试仓库中risc-v内核的BSP

- 完善函数中的命名,完善中断栈的获取

- 提供一份详细的基于现有common文件的移植指南

  #### 在什么测试环境下测试通过 

- 1.CH32V307V-R1-R0
- 2.CH32V208W-R0-1V4
- 3.HPM6750EVKMINI
- 4.GD32VF103V-EVAL
- 5.qemu(CORE-V-MCU )

> 与上述开发板使用同样芯片的BSP均测试通过

在CH32V307V-R1-R0与HPM6750EVKMINI上基于现有移植文件进行多线程复杂场景下的长时间测试,测试过程系统运行正常。
上级 4021b821
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- core-v-mcu.c
- crt0.S
- vectors.S
......@@ -43,7 +43,7 @@
FLASH_DEVICE_OBJECT gFlashDeviceObject[N_QSPIM];
uint8_t gQSPIFlashPresentFlg[N_QSPIM] = {0};
uint8_t gMicronFlashDetectedFlg[N_QSPIM] = {0};
#endif
#endif
#define HEAP_SIZE (( unsigned int) (64 * 1024 ))
......@@ -53,20 +53,20 @@ uint8_t gMicronFlashDetectedFlg[N_QSPIM] = {0};
typedef struct
{
volatile uint32_t *rx_saddr; // 0x00
volatile uint32_t rx_size; // 0x04
volatile uint32_t rx_cfg; // 0x08
volatile uint32_t rx_initcfg; // 0x0C
volatile uint32_t *tx_saddr; // 0x10
volatile uint32_t tx_size; // 0x14
volatile uint32_t tx_cfg; // 0x18
volatile uint32_t tx_initcfg; // 0x1C
volatile uint32_t cfg_glob; // 0x20
volatile uint32_t cfg_ll; // 0x24
volatile uint32_t cfg_ur; // 0x28
volatile uint32_t cfg_size; // 0x2C
volatile uint32_t cfg_filter; // 0x30
volatile uint32_t vsync_pol; // 0x34
volatile uint32_t *rx_saddr; // 0x00
volatile uint32_t rx_size; // 0x04
volatile uint32_t rx_cfg; // 0x08
volatile uint32_t rx_initcfg; // 0x0C
volatile uint32_t *tx_saddr; // 0x10
volatile uint32_t tx_size; // 0x14
volatile uint32_t tx_cfg; // 0x18
volatile uint32_t tx_initcfg; // 0x1C
volatile uint32_t cfg_glob; // 0x20
volatile uint32_t cfg_ll; // 0x24
volatile uint32_t cfg_ur; // 0x28
volatile uint32_t cfg_size; // 0x2C
volatile uint32_t cfg_filter; // 0x30
volatile uint32_t vsync_pol; // 0x34
} camera_struct_t;
......@@ -75,7 +75,7 @@ void forSimulationTesting(void);
/* test some assumptions we make about compiler settings */
static_assert(sizeof(uintptr_t) == 4,
"uintptr_t is not 4 bytes. Make sure you are using -mabi=ilp32*");
"uintptr_t is not 4 bytes. Make sure you are using -mabi=ilp32*");
/* Allocate heap to special section. Note that we have no references in the
* whole program to this variable (since its just here to allocate space in the
......@@ -105,95 +105,95 @@ void flash_readid(const struct cli_cmd_entry *pEntry);
uint8_t setFLLFrequencyInIntegerMode(uint8_t aFLLNum, uint8_t aRefFreqInMHz, uint16_t aMultiplier, uint8_t aDivideRatio_R_Prescale, uint8_t aPS0_L1, uint8_t aPS0_L2)
{
uint8_t lSts = 0;
volatile uint32_t *lPLLStartAddress = (uint32_t *)NULL;
uint32_t lCounter = 0;
uint32_t lCfgVal = 0;
uint8_t lPS0_L1 = aPS0_L1 & 0x03;
uint8_t lPS0_L2 = aPS0_L2 & 0xFF;
if (aFLLNum == 0)
lPLLStartAddress = (uint32_t *)FLL1_START_ADDR;
else if (aFLLNum == 1)
lPLLStartAddress = (uint32_t *)FLL2_START_ADDR;
else if (aFLLNum == 2)
lPLLStartAddress = (uint32_t *)FLL3_START_ADDR;
else
lPLLStartAddress = (uint32_t *)NULL;
if (lPLLStartAddress != NULL)
{
if ((aRefFreqInMHz >= 5) && (aRefFreqInMHz <= 500))
{
if ((aMultiplier > 0) && (aMultiplier < 2048))
{
if (aDivideRatio_R_Prescale < 16)
{
*lPLLStartAddress |= (1 << 19); // Bypass on;
*lPLLStartAddress |= (1 << 2); // Reset high
*lPLLStartAddress &= ~(1 << 2); // Reset low;
*lPLLStartAddress &= ~(1 << 18); // PS0_EN is set to low
*lPLLStartAddress |= (lPS0_L1 << 0); // PS0_L1 0 which gives L01 = 1
*lPLLStartAddress |= (lPS0_L2 << 4); // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
*lPLLStartAddress |= (0 << 12); // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
// FLL1 Config 1 register not configuring PS1
*(lPLLStartAddress + 1) = 0;
// FLL1 Config 2 register
lCfgVal = 0;
lCfgVal |= (aMultiplier << 4); // MULT_INT 0x28 = 40 (40*10 = 400MHz) Multiplier cannot hold 0
lCfgVal |= (1 << 27); // INTEGER_MODE is enabled
lCfgVal |= (aDivideRatio_R_Prescale << 28); // PRESCALE value (Divide Ratio R = 1)
*(lPLLStartAddress + 2) = lCfgVal;
// FLL1 Config 3 register not configuring SSC
*(lPLLStartAddress + 3) = 0;
// FLL1 Config 4 register
*(lPLLStartAddress + 4) = 0x64;
// FLL1 Config 5 register
*(lPLLStartAddress + 5) = 0x269;
*lPLLStartAddress |= (1 << 2); // Reset high
*lPLLStartAddress |= (1 << 18); // PS0_EN;
// lCounter = 0;
while ((*(lPLLStartAddress + 4) & 0x80000000) == 0) // Wait for lock detect to go high
{
lCounter++;
if (lCounter >= 0x00010000)
{
lSts = 5; // Unable to achieve lock
lCounter = 0;
break;
}
}
if (lSts == 0)
*(lPLLStartAddress) &= ~(1 << 19); // Bypass off;
}
else
{
lSts = 1; // aDivideRatio_R_Prescale
}
}
else
{
lSts = 2; // Invalid aMultiplier
}
}
else
{
lSts = 3; // Invalid reference freq
}
}
else
{
lSts = 4; // Invalid PLL number
}
return lSts;
uint8_t lSts = 0;
volatile uint32_t *lPLLStartAddress = (uint32_t *)NULL;
uint32_t lCounter = 0;
uint32_t lCfgVal = 0;
uint8_t lPS0_L1 = aPS0_L1 & 0x03;
uint8_t lPS0_L2 = aPS0_L2 & 0xFF;
if (aFLLNum == 0)
lPLLStartAddress = (uint32_t *)FLL1_START_ADDR;
else if (aFLLNum == 1)
lPLLStartAddress = (uint32_t *)FLL2_START_ADDR;
else if (aFLLNum == 2)
lPLLStartAddress = (uint32_t *)FLL3_START_ADDR;
else
lPLLStartAddress = (uint32_t *)NULL;
if (lPLLStartAddress != NULL)
{
if ((aRefFreqInMHz >= 5) && (aRefFreqInMHz <= 500))
{
if ((aMultiplier > 0) && (aMultiplier < 2048))
{
if (aDivideRatio_R_Prescale < 16)
{
*lPLLStartAddress |= (1 << 19); // Bypass on;
*lPLLStartAddress |= (1 << 2); // Reset high
*lPLLStartAddress &= ~(1 << 2); // Reset low;
*lPLLStartAddress &= ~(1 << 18); // PS0_EN is set to low
*lPLLStartAddress |= (lPS0_L1 << 0); // PS0_L1 0 which gives L01 = 1
*lPLLStartAddress |= (lPS0_L2 << 4); // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
*lPLLStartAddress |= (0 << 12); // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
// FLL1 Config 1 register not configuring PS1
*(lPLLStartAddress + 1) = 0;
// FLL1 Config 2 register
lCfgVal = 0;
lCfgVal |= (aMultiplier << 4); // MULT_INT 0x28 = 40 (40*10 = 400MHz) Multiplier cannot hold 0
lCfgVal |= (1 << 27); // INTEGER_MODE is enabled
lCfgVal |= (aDivideRatio_R_Prescale << 28); // PRESCALE value (Divide Ratio R = 1)
*(lPLLStartAddress + 2) = lCfgVal;
// FLL1 Config 3 register not configuring SSC
*(lPLLStartAddress + 3) = 0;
// FLL1 Config 4 register
*(lPLLStartAddress + 4) = 0x64;
// FLL1 Config 5 register
*(lPLLStartAddress + 5) = 0x269;
*lPLLStartAddress |= (1 << 2); // Reset high
*lPLLStartAddress |= (1 << 18); // PS0_EN;
// lCounter = 0;
while ((*(lPLLStartAddress + 4) & 0x80000000) == 0) // Wait for lock detect to go high
{
lCounter++;
if (lCounter >= 0x00010000)
{
lSts = 5; // Unable to achieve lock
lCounter = 0;
break;
}
}
if (lSts == 0)
*(lPLLStartAddress) &= ~(1 << 19); // Bypass off;
}
else
{
lSts = 1; // aDivideRatio_R_Prescale
}
}
else
{
lSts = 2; // Invalid aMultiplier
}
}
else
{
lSts = 3; // Invalid reference freq
}
}
else
{
lSts = 4; // Invalid PLL number
}
return lSts;
}
int handler_count[32];
......@@ -202,118 +202,121 @@ uint8_t gQSPIIdNum = 0;
void system_init(void)
{
uint32_t lFlashID = 0;
SocCtrl_t *soc = APB_SOC_CTRL_ADDR;
soc->soft_reset = 1;
uint32_t val = 0;
uint8_t i = 0;
timer_irq_disable();
uint32_t lFlashID = 0;
SocCtrl_t *soc = APB_SOC_CTRL_ADDR;
soc->soft_reset = 1;
uint32_t val = 0;
uint8_t i = 0;
timer_irq_disable();
uint32_t *lFFL1StartAddress = (uint32_t *)FLL1_START_ADDR;
uint32_t *lFFL2StartAddress = (uint32_t *)FLL2_START_ADDR;
uint32_t *lFFL3StartAddress = (uint32_t *)FLL3_START_ADDR;
uint32_t *lFFL1StartAddress = (uint32_t *)FLL1_START_ADDR;
uint32_t *lFFL2StartAddress = (uint32_t *)FLL2_START_ADDR;
uint32_t *lFFL3StartAddress = (uint32_t *)FLL3_START_ADDR;
setFLLFrequencyInIntegerMode(0, 10, 40, 1, 0, 1); // 400
setFLLFrequencyInIntegerMode(0, 10, 40, 1, 0, 1); // 400
setFLLFrequencyInIntegerMode(1, 10, 40, 1, 0, 2); // 200
setFLLFrequencyInIntegerMode(1, 10, 40, 1, 0, 2); // 200
setFLLFrequencyInIntegerMode(2, 10, 40, 1, 0, 4); // 100
setFLLFrequencyInIntegerMode(2, 10, 40, 1, 0, 4); // 100
/* Hook up isr table. This table is temporary until we figure out how to do proper vectored interrupts. */
for (int i = 0; i < 32; i++)
{
isr_table[i] = undefined_handler;
handler_count[i] = 0;
}
isr_table[0x7] = timer_irq_handler;
isr_table[0xb] = (void (*)(uint32_t))fc_soc_event_handler1; // 11 for cv32
/* Hook up isr table. This table is temporary until we figure out how to do proper vectored interrupts. */
for (int i = 0; i < 32; i++)
{
isr_table[i] = undefined_handler;
handler_count[i] = 0;
}
isr_table[0x7] = timer_irq_handler;
isr_table[0xb] = (void (*)(uint32_t))fc_soc_event_handler1; // 11 for cv32
/* mtvec is set in crt0.S */
rt_hw_interrupt_init();
rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");
rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");
/* mtvec is set in crt0.S */
/* deactivate all soc events as they are enabled by default */
pulp_soc_eu_event_init();
/* deactivate all soc events as they are enabled by default */
pulp_soc_eu_event_init();
/* Setup soc events handler. */
pi_fc_event_handler_init(11);
/* Setup soc events handler. */
pi_fc_event_handler_init(11);
val = csr_read(CSR_MIE);
val = csr_read(CSR_MIE);
/* TODO: enable uart */
for (uint8_t id = 0; id != N_UART; id++)
{
udma_uart_open(id, 115200);
}
/* TODO: enable uart */
for (uint8_t id = 0; id != N_UART; id++)
{
udma_uart_open(id, 115200);
}
#if (FOR_SIMULATION_TESTING == 1)
forSimulationTesting();
forSimulationTesting();
#endif
}
void system_core_clock_update(void)
{
system_core_clock = pi_fll_get_frequency(FLL_SOC, 0);
system_core_clock = pi_fll_get_frequency(FLL_SOC, 0);
}
void system_core_clock_get(void)
{
system_core_clock_update();
return;
system_core_clock_update();
return;
}
uint16_t Writeraw(uint8_t uart_id, uint16_t write_len, uint8_t* write_buffer) {
UdmaUart_t* puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
UdmaUart_t* puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
while (puart->status_b.tx_busy) { // ToDo: Why is this necessary? Thought the semaphore should have protected
}
while (puart->status_b.tx_busy) { // ToDo: Why is this necessary? Thought the semaphore should have protected
}
puart->tx_saddr = (uint32_t)write_buffer;
puart->tx_size = write_len;
puart->tx_cfg_b.en = 1; //enable the transfer
puart->tx_saddr = (uint32_t)write_buffer;
puart->tx_size = write_len;
puart->tx_cfg_b.en = 1; //enable the transfer
return 0;
return 0;
}
void timer_irq_handler(uint32_t mcause)
{
#warning requires critical section if interrupt nesting is used.
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
void vSystemIrqHandler(uint32_t mcause)
{
isr_table[mcause & 0x1f](mcause & 0x1f);
isr_table[mcause & 0x1f](mcause & 0x1f);
}
void undefined_handler(uint32_t mcause)
{
uint32_t RegReadVal = 0;
uint32_t RegReadVal = 0;
#ifdef __PULP_USE_LIBC
abort();
abort();
#else
if ((mcause == 18) || (mcause == 19) || (mcause == 31))
{
gSpecialHandlingIRQCnt++;
if (gSpecialHandlingIRQCnt >= 20)
{
RegReadVal = csr_read(CSR_MIE);
if ((RegReadVal & BIT(mcause)) != 0) // Check if the event interrupt mask is open.
{
// close the event interrupt mask.
csr_read_clear(CSR_MIE, BIT(mcause));
}
}
}
else
{
handler_count[mcause]++;
}
if ((mcause == 18) || (mcause == 19) || (mcause == 31))
{
gSpecialHandlingIRQCnt++;
if (gSpecialHandlingIRQCnt >= 20)
{
RegReadVal = csr_read(CSR_MIE);
if ((RegReadVal & BIT(mcause)) != 0) // Check if the event interrupt mask is open.
{
// close the event interrupt mask.
csr_read_clear(CSR_MIE, BIT(mcause));
}
}
}
else
{
handler_count[mcause]++;
}
#endif
}
void rt_systick_config(void)
{
extern int timer_irq_init(uint32_t ticks);
timer_irq_init(ARCHI_FPGA_FREQUENCY / RT_TICK_PER_SECOND);
extern int timer_irq_init(uint32_t ticks);
timer_irq_init(ARCHI_FPGA_FREQUENCY / RT_TICK_PER_SECOND);
}
......@@ -19,7 +19,7 @@
* Date Author Notes
* 2022-12-08 WangShun Remove FreeRTOS related code and add RT-Thread code
*/
.extern IRQ_Handler
.extern SW_handler
#ifdef PULP_FREERTOS_VECTORED_CONTEXT_SWITCH
.extern freertos_risc_v_ctxt_handler
#endif
......@@ -30,38 +30,38 @@
.section .vectors, "ax"
.option norvc
vector_table:
j IRQ_Handler // irq0
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler // irq3
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler //ctxt_handler // irq 7 mtime or timer
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler // IRQ_Handler
j IRQ_Handler // irq 11 Machine (event Fifo)
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler
j IRQ_Handler // IRQ16
j IRQ_Handler // IRQ17
j IRQ_Handler // IRQ18
j IRQ_Handler // IRQ19
j IRQ_Handler // IRQ20
j IRQ_Handler // IRQ21
j IRQ_Handler // IRQ22
j IRQ_Handler // IRQ23
j IRQ_Handler // IRQ24
j IRQ_Handler // IRQ25
j IRQ_Handler // IRQ26
j IRQ_Handler // IRQ27
j IRQ_Handler // IRQ28
j IRQ_Handler // IRQ29
j IRQ_Handler // IRQ30
j IRQ_Handler // IRQ30
j SW_handler // irq0
j SW_handler
j SW_handler
j SW_handler // irq3
j SW_handler
j SW_handler
j SW_handler
j SW_handler //ctxt_handler // irq 7 mtime or timer
j SW_handler
j SW_handler
j SW_handler // SW_handler
j SW_handler // irq 11 Machine (event Fifo)
j SW_handler
j SW_handler
j SW_handler
j SW_handler
j SW_handler // IRQ16
j SW_handler // IRQ17
j SW_handler // IRQ18
j SW_handler // IRQ19
j SW_handler // IRQ20
j SW_handler // IRQ21
j SW_handler // IRQ22
j SW_handler // IRQ23
j SW_handler // IRQ24
j SW_handler // IRQ25
j SW_handler // IRQ26
j SW_handler // IRQ27
j SW_handler // IRQ28
j SW_handler // IRQ29
j SW_handler // IRQ30
j SW_handler // IRQ30
/* this is fixed to 0x8000, used for PULP_SECURE=0. We redirect this entry to the
new vector table (which is at mtvec) */
......
......@@ -342,6 +342,7 @@ SECTIONS
__stack_bottom = .;
. += __stack_size;
__stack_top = .;
PROVIDE( __rt_rvstack = . );
__freertos_irq_stack_top = .; /* sytem stack */
stack = .;
} > L2
......
......@@ -17,8 +17,8 @@ else:
print('Please make sure your toolchains is GNU GCC!')
exit(0)
#if os.getenv('RTT_EXEC_PATH'):
# EXEC_PATH = os.getenv('RTT_EXEC_PATH')
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
BUILD = 'debug'
#BUILD = 'release'
......
......@@ -22,8 +22,8 @@ else:
print('Please make sure your toolchains is GNU GCC!')
exit(0)
#if os.getenv('RTT_EXEC_PATH'):
# EXEC_PATH = os.getenv('RTT_EXEC_PATH')
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
CORE = 'risc-v'
BUILD = 'debug'
......
......@@ -195,5 +195,6 @@ SECTIONS
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
PROVIDE( __rt_rvstack = .);
} >ram AT>ram
}
......@@ -187,7 +187,7 @@ _start0800:
csrw CSR_MTVT, t0
/* Intial the mtvt2 and enable it*/
la t0, irq_entry
la t0, SW_handler
csrw CSR_MTVT2, t0
csrs CSR_MTVT2, 0x1
......@@ -236,7 +236,6 @@ _start0800:
call atexit
call __libc_init_array
/* argc = argv = 0 */
li a0, 0
li a1, 0
......
......@@ -195,5 +195,6 @@ SECTIONS
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
PROVIDE( __rt_rvstack = .);
} >ram AT>ram
}
......@@ -51,7 +51,7 @@ void rt_hw_interrupt_init(void)
/* config interrupt vector*/
asm volatile(
"la t0, trap_entry\n"
"la t0, SW_handler\n"
"csrw mtvec, t0"
);
......
......@@ -181,5 +181,6 @@ SECTIONS
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
PROVIDE( __rt_rvstack = .);
} >ram AT>ram :ram
}
......@@ -6,7 +6,7 @@
#include "encoding.h"
extern int main(int argc, char** argv);
extern void trap_entry();
extern void SW_handler();
static unsigned long mtime_lo(void)
{
......@@ -223,7 +223,7 @@ void _init()
rt_kprintf("core freq at %ld Hz\n", get_cpu_freq());
write_csr(mtvec, &trap_entry);
write_csr(mtvec, &SW_handler);
if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present
write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping
write_csr(fcsr, 0); // initialize rounding mode, undefined at reset
......
......@@ -87,7 +87,7 @@ _start:
#if defined(ENABLE_SMP)
2:
la t0, trap_entry
la t0, SW_handler
csrw mtvec, t0
csrr a0, mhartid
......
......@@ -247,6 +247,7 @@ SECTIONS
. += STACK_SIZE;
. = ALIGN(8);
PROVIDE (_stack = .);
PROVIDE( __rt_rvstack = . );
PROVIDE (_stack_in_dlm = .);
} > AXI_SRAM
......
......@@ -46,7 +46,7 @@ _start:
csrci CSR_MMISC_CTL, 2
/* Initialize trap_entry base */
la t0, irq_handler_trap
la t0, SW_handler
csrw mtvec, t0
......
......@@ -11,7 +11,7 @@
__vector_table:
.weak default_isr_trap
.set default_isr_trap, irq_handler_trap
.set default_isr_trap, SW_handler
.long default_isr_trap
IRQ_HANDLER 1 /* GPIO0_A IRQ handler */
IRQ_HANDLER 2 /* GPIO0_B IRQ handler */
......
......@@ -7,7 +7,7 @@
#include "hpm_common.h"
#include "hpm_soc.h"
#include <rtthread.h>
#include "riscv-stackframe.h"
#include "rt_hw_stack_frame.h"
#define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
#define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
......
......@@ -45,10 +45,9 @@ _start:
/* Disable Vector mode */
csrci CSR_MMISC_CTL, 2
/* Initialize trap_entry base */
la t0, irq_handler_trap
la t0, SW_handler
csrw mtvec, t0
/* System reset handler */
call reset_handler
......
......@@ -9,7 +9,7 @@
.align 9
__vector_table:
.weak default_isr_trap
.set default_isr_trap, irq_handler_trap
.set default_isr_trap, SW_handler
.long default_isr_trap
IRQ_HANDLER 1 /* GPIO0_A IRQ handler */
IRQ_HANDLER 2 /* GPIO0_B IRQ handler */
......
......@@ -7,7 +7,7 @@
#include "hpm_common.h"
#include "hpm_soc.h"
#include <rtthread.h>
#include "riscv-stackframe.h"
#include "rt_hw_stack_frame.h"
#define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
#define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
......
......@@ -247,6 +247,7 @@ SECTIONS
. += STACK_SIZE;
. = ALIGN(8);
PROVIDE (_stack = .);
PROVIDE( __rt_rvstack = . );
PROVIDE (_stack_in_dlm = .);
} > AXI_SRAM
......
......@@ -46,7 +46,7 @@ _start:
csrci CSR_MMISC_CTL, 2
/* Initialize trap_entry base */
la t0, irq_handler_trap
la t0, SW_handler
csrw mtvec, t0
......
......@@ -11,7 +11,7 @@
__vector_table:
.weak default_isr_trap
.set default_isr_trap, irq_handler_trap
.set default_isr_trap, SW_handler
.long default_isr_trap
IRQ_HANDLER 1 /* GPIO0_A IRQ handler */
IRQ_HANDLER 2 /* GPIO0_B IRQ handler */
......
......@@ -7,7 +7,7 @@
#include "hpm_common.h"
#include "hpm_soc.h"
#include <rtthread.h>
#include "riscv-stackframe.h"
#include "rt_hw_stack_frame.h"
#define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
#define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
......
......@@ -45,10 +45,9 @@ _start:
/* Disable Vector mode */
csrci CSR_MMISC_CTL, 2
/* Initialize trap_entry base */
la t0, irq_handler_trap
la t0, SW_handler
csrw mtvec, t0
/* System reset handler */
call reset_handler
......
......@@ -9,7 +9,7 @@
.align 9
__vector_table:
.weak default_isr_trap
.set default_isr_trap, irq_handler_trap
.set default_isr_trap, SW_handler
.long default_isr_trap
IRQ_HANDLER 1 /* GPIO0_A IRQ handler */
IRQ_HANDLER 2 /* GPIO0_B IRQ handler */
......
......@@ -7,7 +7,7 @@
#include "hpm_common.h"
#include "hpm_soc.h"
#include <rtthread.h>
#include "riscv-stackframe.h"
#include "rt_hw_stack_frame.h"
#define MCAUSE_INSTR_ADDR_MISALIGNED (0U) //!< Instruction Address misaligned
#define MCAUSE_INSTR_ACCESS_FAULT (1U) //!< Instruction access fault
......
......@@ -52,7 +52,7 @@ _start:
#endif
#ifndef CONFIG_FREERTOS
#define HANDLER_TRAP irq_handler_trap
#define HANDLER_TRAP SW_handler
#define HANDLER_S_TRAP irq_handler_s_trap
#else
#define HANDLER_TRAP freertos_risc_v_trap_handler
......
......@@ -224,7 +224,7 @@ MARK_FUNC __SEGGER_init_done
#endif
#ifndef CONFIG_FREERTOS
#define HANDLER_TRAP irq_handler_trap
#define HANDLER_TRAP SW_handler
#define HANDLER_S_TRAP irq_handler_s_trap
#else
#define HANDLER_TRAP freertos_risc_v_trap_handler
......
......@@ -100,11 +100,11 @@ __attribute__((weak)) void mchtmr_s_isr(void)
}
#ifndef CONFIG_FREERTOS
void irq_handler_trap(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
void SW_handler(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
#else
void irq_handler_trap(void) __attribute__ ((section(".isr_vector")));
void SW_handler(void) __attribute__ ((section(".isr_vector")));
#endif
void irq_handler_trap(void)
void SW_handler(void)
{
long mcause = read_csr(CSR_MCAUSE);
long mepc = read_csr(CSR_MEPC);
......
......@@ -22,7 +22,7 @@ default_irq_handler:
__vector_table:
.weak default_isr_trap
.set default_isr_trap, irq_handler_trap
.set default_isr_trap, SW_handler
.long default_isr_trap
IRQ_HANDLER 1 /* GPIO0_A IRQ handler */
IRQ_HANDLER 2 /* GPIO0_B IRQ handler */
......
......@@ -52,7 +52,7 @@ _start:
#endif
#ifndef CONFIG_FREERTOS
#define HANDLER_TRAP irq_handler_trap
#define HANDLER_TRAP SW_handler
#else
#define HANDLER_TRAP freertos_risc_v_trap_handler
#endif
......
......@@ -224,7 +224,7 @@ MARK_FUNC __SEGGER_init_done
#endif
#ifndef CONFIG_FREERTOS
#define HANDLER_TRAP irq_handler_trap
#define HANDLER_TRAP SW_handler
#else
#define HANDLER_TRAP freertos_risc_v_trap_handler
#endif
......
......@@ -89,11 +89,11 @@ __attribute__((weak)) long exception_handler(long cause, long epc)
}
#ifndef CONFIG_FREERTOS
void irq_handler_trap(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
void SW_handler(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
#else
void irq_handler_trap(void) __attribute__ ((section(".isr_vector")));
void SW_handler(void) __attribute__ ((section(".isr_vector")));
#endif
void irq_handler_trap(void)
void SW_handler(void)
{
long mcause = read_csr(CSR_MCAUSE);
long mepc = read_csr(CSR_MEPC);
......
......@@ -128,6 +128,7 @@ SECTIONS
. += __STACKSIZE__;
__stack_cpu0 = .;
PROVIDE( __rt_rvstack = .);
. += __STACKSIZE__;
__stack_cpu1 = .;
......
......@@ -32,19 +32,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
# CONFIG_RT_USING_TINY_FFS is not set
# CONFIG_RT_KPRINTF_USING_LONGLONG is not set
CONFIG_RT_DEBUG=y
CONFIG_RT_DEBUG_COLOR=y
CONFIG_RT_DEBUG_INIT_CONFIG=y
CONFIG_RT_DEBUG_INIT=1
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
# CONFIG_RT_DEBUG is not set
#
# Inter-Thread communication
......@@ -59,6 +47,7 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
#
# Memory Management
#
CONFIG_RT_PAGE_MAX_ORDER=11
CONFIG_RT_USING_MEMPOOL=y
CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
......@@ -77,15 +66,18 @@ CONFIG_RT_USING_HEAP=y
#
CONFIG_RT_USING_DEVICE=y
# CONFIG_RT_USING_DEVICE_OPS is not set
# CONFIG_RT_USING_DM is not set
# CONFIG_RT_USING_INTERRUPT_INFO is not set
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart4"
CONFIG_RT_VER_NUM=0x40101
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
CONFIG_RT_VER_NUM=0x50000
# CONFIG_RT_USING_CACHE is not set
# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_RISCV32=y
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
#
# RT-Thread Components
......@@ -117,6 +109,7 @@ CONFIG_FINSH_ARG_MAX=10
# Device Drivers
#
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_UNAMED_PIPE_NUMBER=64
CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048
CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
......@@ -133,10 +126,14 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_ADC is not set
# CONFIG_RT_USING_DAC is not set
# CONFIG_RT_USING_NULL is not set
# CONFIG_RT_USING_ZERO is not set
# CONFIG_RT_USING_RANDOM is not set
# CONFIG_RT_USING_PWM is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
# CONFIG_RT_USING_FDT is not set
# CONFIG_RT_USING_RTC is not set
# CONFIG_RT_USING_SDIO is not set
# CONFIG_RT_USING_SPI is not set
......@@ -144,10 +141,13 @@ CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_AUDIO is not set
# CONFIG_RT_USING_SENSOR is not set
# CONFIG_RT_USING_TOUCH is not set
# CONFIG_RT_USING_LCD is not set
# CONFIG_RT_USING_HWCRYPTO is not set
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
# CONFIG_RT_USING_DEV_BUS is not set
# CONFIG_RT_USING_WIFI is not set
# CONFIG_RT_USING_VIRTIO is not set
#
# Using USB
......@@ -292,6 +292,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_AGILE_FTP is not set
# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
# CONFIG_PKG_USING_RT_LINK_HW is not set
# CONFIG_PKG_USING_RYANMQTT is not set
# CONFIG_PKG_USING_LORA_PKT_FWD is not set
# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
......@@ -299,6 +300,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_SMALL_MODBUS is not set
# CONFIG_PKG_USING_NET_SERVER is not set
# CONFIG_PKG_USING_ZFTP is not set
# CONFIG_PKG_USING_WOL is not set
#
# security packages
......@@ -389,7 +391,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_SEGGER_RTT is not set
# CONFIG_PKG_USING_RDB is not set
# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
# CONFIG_PKG_USING_ULOG_FILE is not set
# CONFIG_PKG_USING_LOGMGR is not set
# CONFIG_PKG_USING_ADBD is not set
# CONFIG_PKG_USING_COREMARK is not set
......@@ -423,8 +424,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_CBOX is not set
# CONFIG_PKG_USING_SNOWFLAKE is not set
# CONFIG_PKG_USING_HASH_MATCH is not set
# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set
# CONFIG_PKG_USING_VOFA_PLUS is not set
#
# system packages
......@@ -460,7 +461,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_UC_CLK is not set
# CONFIG_PKG_USING_UC_COMMON is not set
# CONFIG_PKG_USING_UC_MODBUS is not set
# CONFIG_PKG_USING_RTDUINO is not set
# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
......@@ -495,15 +495,88 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_KMULTI_RTIMER is not set
# CONFIG_PKG_USING_TFDB is not set
# CONFIG_PKG_USING_QPC is not set
# CONFIG_PKG_USING_AGILE_UPGRADE is not set
#
# peripheral libraries and drivers
#
# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
#
# sensors drivers
#
# CONFIG_PKG_USING_FINGERPRINT is not set
# CONFIG_PKG_USING_LSM6DSM is not set
# CONFIG_PKG_USING_LSM6DSL is not set
# CONFIG_PKG_USING_LPS22HB is not set
# CONFIG_PKG_USING_HTS221 is not set
# CONFIG_PKG_USING_LSM303AGR is not set
# CONFIG_PKG_USING_BME280 is not set
# CONFIG_PKG_USING_BME680 is not set
# CONFIG_PKG_USING_BMA400 is not set
# CONFIG_PKG_USING_BMI160_BMX160 is not set
# CONFIG_PKG_USING_SPL0601 is not set
# CONFIG_PKG_USING_MS5805 is not set
# CONFIG_PKG_USING_DA270 is not set
# CONFIG_PKG_USING_DF220 is not set
# CONFIG_PKG_USING_HSHCAL001 is not set
# CONFIG_PKG_USING_BH1750 is not set
# CONFIG_PKG_USING_MPU6XXX is not set
# CONFIG_PKG_USING_AHT10 is not set
# CONFIG_PKG_USING_AP3216C is not set
# CONFIG_PKG_USING_TSL4531 is not set
# CONFIG_PKG_USING_DS18B20 is not set
# CONFIG_PKG_USING_DHT11 is not set
# CONFIG_PKG_USING_DHTXX is not set
# CONFIG_PKG_USING_GY271 is not set
# CONFIG_PKG_USING_GP2Y10 is not set
# CONFIG_PKG_USING_SGP30 is not set
# CONFIG_PKG_USING_HDC1000 is not set
# CONFIG_PKG_USING_BMP180 is not set
# CONFIG_PKG_USING_BMP280 is not set
# CONFIG_PKG_USING_SHTC1 is not set
# CONFIG_PKG_USING_BMI088 is not set
# CONFIG_PKG_USING_HMC5883 is not set
# CONFIG_PKG_USING_MAX6675 is not set
# CONFIG_PKG_USING_TMP1075 is not set
# CONFIG_PKG_USING_SR04 is not set
# CONFIG_PKG_USING_CCS811 is not set
# CONFIG_PKG_USING_PMSXX is not set
# CONFIG_PKG_USING_RT3020 is not set
# CONFIG_PKG_USING_MLX90632 is not set
# CONFIG_PKG_USING_MLX90393 is not set
# CONFIG_PKG_USING_MLX90392 is not set
# CONFIG_PKG_USING_MLX90397 is not set
# CONFIG_PKG_USING_MS5611 is not set
# CONFIG_PKG_USING_MAX31865 is not set
# CONFIG_PKG_USING_VL53L0X is not set
# CONFIG_PKG_USING_INA260 is not set
# CONFIG_PKG_USING_MAX30102 is not set
# CONFIG_PKG_USING_INA226 is not set
# CONFIG_PKG_USING_LIS2DH12 is not set
# CONFIG_PKG_USING_HS300X is not set
# CONFIG_PKG_USING_ZMOD4410 is not set
# CONFIG_PKG_USING_ISL29035 is not set
# CONFIG_PKG_USING_MMC3680KJ is not set
# CONFIG_PKG_USING_QMP6989 is not set
# CONFIG_PKG_USING_BALANCE is not set
# CONFIG_PKG_USING_SHT2X is not set
# CONFIG_PKG_USING_SHT3X is not set
# CONFIG_PKG_USING_AD7746 is not set
# CONFIG_PKG_USING_ADT74XX is not set
# CONFIG_PKG_USING_MAX17048 is not set
#
# touch drivers
#
# CONFIG_PKG_USING_GT9147 is not set
# CONFIG_PKG_USING_GT1151 is not set
# CONFIG_PKG_USING_GT917S is not set
# CONFIG_PKG_USING_GT911 is not set
# CONFIG_PKG_USING_FT6206 is not set
# CONFIG_PKG_USING_FT5426 is not set
# CONFIG_PKG_USING_FT6236 is not set
# CONFIG_PKG_USING_XPT2046_TOUCH is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_AS7341 is not set
# CONFIG_PKG_USING_STM32_SDIO is not set
# CONFIG_PKG_USING_ESP_IDF is not set
......@@ -530,12 +603,9 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_AGILE_LED is not set
# CONFIG_PKG_USING_AT24CXX is not set
# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
# CONFIG_PKG_USING_AD7746 is not set
# CONFIG_PKG_USING_PCA9685 is not set
# CONFIG_PKG_USING_I2C_TOOLS is not set
# CONFIG_PKG_USING_NRF24L01 is not set
# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
# CONFIG_PKG_USING_MAX17048 is not set
# CONFIG_PKG_USING_RPLIDAR is not set
# CONFIG_PKG_USING_AS608 is not set
# CONFIG_PKG_USING_RC522 is not set
......@@ -596,6 +666,7 @@ CONFIG_PKG_NUCLEI_SDK_VER="latest"
# CONFIG_PKG_USING_RFM300 is not set
# CONFIG_PKG_USING_IO_INPUT_FILTER is not set
# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set
# CONFIG_PKG_USING_LRF_NV7LIDAR is not set
#
# AI packages
......@@ -610,6 +681,12 @@ CONFIG_PKG_NUCLEI_SDK_VER="latest"
# CONFIG_PKG_USING_QUEST is not set
# CONFIG_PKG_USING_NAXOS is not set
#
# Signal Processing and Control Algorithm Packages
#
# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
# CONFIG_PKG_USING_UKAL is not set
#
# miscellaneous packages
#
......@@ -661,7 +738,6 @@ CONFIG_PKG_NUCLEI_SDK_VER="latest"
# CONFIG_PKG_USING_VI is not set
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_UKAL is not set
# CONFIG_PKG_USING_CRCLIB is not set
# CONFIG_PKG_USING_LWGPS is not set
# CONFIG_PKG_USING_STATE_MACHINE is not set
......@@ -672,63 +748,212 @@ CONFIG_PKG_NUCLEI_SDK_VER="latest"
# CONFIG_PKG_USING_SLCAN2RTT is not set
# CONFIG_PKG_USING_SOEM is not set
# CONFIG_PKG_USING_QPARAM is not set
# CONFIG_PKG_USING_CorevMCU_CLI is not set
#
# Arduino libraries
#
# CONFIG_PKG_USING_RTDUINO is not set
#
# Projects
#
# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set
# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set
# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set
#
# Sensors
#
# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set
# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set
# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set
# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set
# CONFIG_PKG_USING_SEEED_ITG3200 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set
# CONFIG_PKG_USING_SEEED_MP503 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set
#
# Display
#
# CONFIG_PKG_USING_ARDUINO_U8G2 is not set
# CONFIG_PKG_USING_SEEED_TM1637 is not set
#
# Timing
#
# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set
#
# Data Processing
#
# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set
# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set
#
# Data Storage
#
#
# Communication
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set
#
# Device Control
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set
#
# Other
#
#
# Privated Packages of RealThread
#
# CONFIG_PKG_USING_CODEC is not set
# CONFIG_PKG_USING_PLAYER is not set
# CONFIG_PKG_USING_MPLAYER is not set
# CONFIG_PKG_USING_PERSIMMON_SRC is not set
# CONFIG_PKG_USING_JS_PERSIMMON is not set
# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set
#
# Network Utilities
#
# CONFIG_PKG_USING_WICED is not set
# CONFIG_PKG_USING_CLOUDSDK is not set
# CONFIG_PKG_USING_POWER_MANAGER is not set
# CONFIG_PKG_USING_RT_OTA is not set
# CONFIG_PKG_USING_RTINSIGHT is not set
# CONFIG_PKG_USING_SMARTCONFIG is not set
# CONFIG_PKG_USING_RTX is not set
# CONFIG_RT_USING_TESTCASE is not set
# CONFIG_PKG_USING_NGHTTP2 is not set
# CONFIG_PKG_USING_AVS is not set
# CONFIG_PKG_USING_ALI_LINKKIT is not set
# CONFIG_PKG_USING_STS is not set
# CONFIG_PKG_USING_DLMS is not set
# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set
# CONFIG_PKG_USING_ZBAR is not set
# CONFIG_PKG_USING_MCF is not set
# CONFIG_PKG_USING_URPC is not set
# CONFIG_PKG_USING_DCM is not set
# CONFIG_PKG_USING_EMQ is not set
# CONFIG_PKG_USING_CFGM is not set
# CONFIG_PKG_USING_RT_CMSIS_DAP is not set
# CONFIG_PKG_USING_SMODULE is not set
# CONFIG_PKG_USING_SNFD is not set
# CONFIG_PKG_USING_UDBD is not set
# CONFIG_PKG_USING_BENCHMARK is not set
# CONFIG_PKG_USING_UBJSON is not set
# CONFIG_PKG_USING_DATATYPE is not set
# CONFIG_PKG_USING_FASTFS is not set
# CONFIG_PKG_USING_RIL is not set
# CONFIG_PKG_USING_WATCH_DCM_SVC is not set
# CONFIG_PKG_USING_WATCH_APP_FWK is not set
# CONFIG_PKG_USING_GUI_TEST is not set
# CONFIG_PKG_USING_PMEM is not set
# CONFIG_PKG_USING_LWRDP is not set
# CONFIG_PKG_USING_MASAN is not set
# CONFIG_PKG_USING_BSDIFF_LIB is not set
# CONFIG_PKG_USING_PRC_DIFF is not set
#
# RT-Thread Smart
#
# CONFIG_PKG_USING_UKERNEL is not set
# CONFIG_PKG_USING_TRACE_AGENT is not set
# Signal IO
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set
#
# Uncategorized
#
#
# Hardware Drivers Config
......@@ -744,7 +969,7 @@ CONFIG_BSP_USING_UART_CONSOLE=y
# On-chip Peripheral Drivers
#
CONFIG_BSP_USING_UART=y
# CONFIG_BSP_USING_UART0 is not set
CONFIG_BSP_USING_UART0=y
# CONFIG_BSP_USING_UART1 is not set
# CONFIG_BSP_USING_UART2 is not set
# CONFIG_BSP_USING_UART3 is not set
......
......@@ -64,9 +64,21 @@ export PATH=~/Software/Nuclei/gcc/bin:~/Software/Nuclei/openocd/bin:$PATH
**注意**: 请确保Nuclei GCC和Nuclei OpenOCD的路径设置正确无误。
1. 运行 ``pkgs --update``来下载最新的依赖的**Nuclei SDK**开发包
1. 运行 ``pkgs --update``来下载最新的依赖的**Nuclei SDK**开发包,修改链接脚本。
```c
.stack ORIGIN(RAM) + LENGTH(RAM) - __TOT_STACK_SIZE (NOLOAD) :
{
...
PROVIDE( _sp = . );
PROVIDE( __rt_rvstack = . );//在链接脚本中补充该条语句
} >RAM AT>RAM
```
2. **可选**: 运行 ``menuconfig``来进行内核配置
3. 运行 ``scons -c``清理之前的编译结果
4. 运行 ``scons``来进行代码的编译
### 下载程序
......
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
......@@ -16,4 +16,4 @@ int main(int argc, char *argv[])
return RT_EOK;
}
/******************** end of file *******************/
\ No newline at end of file
/******************** end of file *******************/
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
......@@ -12,7 +12,9 @@
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "cpuport.h"
#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND)
#define RT_KERNEL_INTERRUPT_LEVEL 1
#ifdef RT_USING_SERIAL
#include <drv_usart.h>
......@@ -122,6 +124,45 @@ void rt_hw_drivers_init(void)
#endif
}
rt_weak void rt_hw_ticksetup(void)
{
uint64_t ticks = SYSTICK_TICK_CONST;
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
}
#define SysTick_Handler eclic_mtip_handler
/**
* @brief This is the timer interrupt service routine.
*
*/
void SysTick_Handler(void)
{
/* Reload systimer */
SysTick_Reload(SYSTICK_TICK_CONST);
/* enter interrupt */
rt_interrupt_enter();
/* tick increase */
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
/**
* @brief Setup hardware board for rt-thread
*
......@@ -158,4 +199,3 @@ void rt_hw_board_init(void)
}
/******************** end of file *******************/
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
......
......@@ -23,10 +23,6 @@
/* kservice optimization */
#define RT_DEBUG
#define RT_DEBUG_COLOR
#define RT_DEBUG_INIT_CONFIG
#define RT_DEBUG_INIT 1
/* Inter-Thread communication */
......@@ -38,6 +34,7 @@
/* Memory Management */
#define RT_PAGE_MAX_ORDER 11
#define RT_USING_MEMPOOL
#define RT_USING_SMALL_MEM
#define RT_USING_SMALL_MEM_AS_HEAP
......@@ -49,7 +46,7 @@
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart4"
#define RT_VER_NUM 0x40101
#define RT_VER_NUM 0x50000
#define ARCH_RISCV
#define ARCH_RISCV32
......@@ -76,6 +73,7 @@
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SYSTEM_WORKQUEUE
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
......@@ -166,6 +164,11 @@
/* peripheral libraries and drivers */
/* sensors drivers */
/* touch drivers */
/* Kendryte SDK */
......@@ -178,6 +181,9 @@
/* AI packages */
/* Signal Processing and Control Algorithm Packages */
/* miscellaneous packages */
/* project laboratory */
......@@ -188,14 +194,38 @@
/* entertainment: terminal games and other interesting software packages */
/* Privated Packages of RealThread */
/* Arduino libraries */
/* Projects */
/* Sensors */
/* Display */
/* Timing */
/* Data Processing */
/* Data Storage */
/* Communication */
/* Device Control */
/* Network Utilities */
/* Other */
/* Signal IO */
/* RT-Thread Smart */
/* Uncategorized */
/* Hardware Drivers Config */
......@@ -208,6 +238,7 @@
/* On-chip Peripheral Drivers */
#define BSP_USING_UART
#define BSP_USING_UART0
#define BSP_USING_UART4
/* Board extended module Drivers */
......
......@@ -13,7 +13,7 @@ if os.getenv('RTT_CC'):
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = 'D:/Software/Nuclei/gcc/bin'
EXEC_PATH = r'D:/Software/Nuclei/gcc/bin'
else:
print("CROSS_TOOL = {} not yet supported" % CROSS_TOOL)
......@@ -50,6 +50,7 @@ if PLATFORM == 'gcc':
CPATH = ''
LPATH = ''
LIBS = ['stdc++']
AFLAGS += ' -I. '+ ' -D"irq_entry=SW_handler" '
if BUILD == 'debug':
CFLAGS += ' -O2 -Os -ggdb'
......
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-07-23 tyustli first version
* 2020-04-02 hqfang modified for Nuclei
*/
#include <drv_usart.h>
......@@ -14,344 +13,228 @@
#ifdef RT_USING_SERIAL
#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) \
&& !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4)
&& !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5)
#error "Please define at least one BSP_USING_UARTx"
/* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable UART */
#endif
/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
#endif
struct gd32_usart {
char *name;
rt_uint32_t usart_base;
rt_uint32_t usart_clk;
rt_uint32_t gpio_clk;
rt_uint32_t gpio_port;
rt_uint32_t tx_pin;
rt_uint32_t rx_pin;
IRQn_Type irqn;
struct rt_serial_device serial;
};
enum
{
enum {
#ifdef BSP_USING_UART0
GDUART0_INDEX,
#endif
#ifdef BSP_USING_UART1
GDUART1_INDEX,
#endif
#ifdef BSP_USING_UART2
GDUART2_INDEX,
#endif
#ifdef BSP_USING_UART3
GDUART3_INDEX,
#endif
#ifdef BSP_USING_UART4
GDUART4_INDEX,
GDUSART0_INDEX,
#endif
};
static struct gd32_uart_config uart_config[] =
{
static struct gd32_usart usart_config[] = {
#ifdef BSP_USING_UART0
{
"uart0",
{ "uart0",
USART0,
USART0_IRQn,
},
#endif
#ifdef BSP_USING_UART1
{
"uart1",
USART1,
USART1_IRQn,
},
#endif
#ifdef BSP_USING_UART2
{
"uart2",
USART2,
USART2_IRQn,
},
#endif
#ifdef BSP_USING_UART3
{
"uart3",
UART3,
UART3_IRQn,
},
#endif
#ifdef BSP_USING_UART4
{
"uart4",
UART4,
UART4_IRQn,
},
RCU_USART0,
RCU_GPIOA,
GPIOA,
GPIO_PIN_9,
GPIO_PIN_10,
USART0_IRQn, },
#endif
};
static struct gd32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
static rt_err_t gd32_configure(struct rt_serial_device *serial,
struct serial_configure *cfg)
{
struct gd32_uart *usart_obj;
struct gd32_uart_config *usart;
struct serial_configure *cfg) {
struct gd32_usart *usart;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
usart_obj = (struct gd32_uart *) serial->parent.user_data;
usart = usart_obj->config;
usart = (struct gd32_usart *) serial->parent.user_data;
RT_ASSERT(usart != RT_NULL);
usart_deinit(usart->uart_base);
usart_baudrate_set(usart->uart_base, cfg->baud_rate);
switch (cfg->data_bits)
{
/* enable GPIO clock */
rcu_periph_clock_enable(usart->gpio_clk);
/* enable USART clock */
rcu_periph_clock_enable(usart->usart_clk);
/* connect port to USARTx_Tx */
gpio_init(usart->gpio_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
usart->tx_pin);
/* connect port to USARTx_Rx */
gpio_init(usart->gpio_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,
usart->rx_pin);
usart_deinit(usart->usart_base);
usart_baudrate_set(usart->usart_base, cfg->baud_rate);
switch (cfg->data_bits) {
case DATA_BITS_8:
usart_word_length_set(usart->uart_base, USART_WL_8BIT);
usart_word_length_set(usart->usart_base, USART_WL_8BIT);
break;
case DATA_BITS_9:
usart_word_length_set(usart->uart_base, USART_WL_9BIT);
usart_word_length_set(usart->usart_base, USART_WL_9BIT);
break;
default:
usart_word_length_set(usart->uart_base, USART_WL_8BIT);
usart_word_length_set(usart->usart_base, USART_WL_8BIT);
break;
}
switch (cfg->stop_bits)
{
switch (cfg->stop_bits) {
case STOP_BITS_1:
usart_stop_bit_set(usart->uart_base, USART_STB_1BIT);
usart_stop_bit_set(usart->usart_base, USART_STB_1BIT);
break;
case STOP_BITS_2:
usart_stop_bit_set(usart->uart_base, USART_STB_2BIT);
usart_stop_bit_set(usart->usart_base, USART_STB_2BIT);
break;
default:
usart_stop_bit_set(usart->uart_base, USART_STB_1BIT);
usart_stop_bit_set(usart->usart_base, USART_STB_1BIT);
break;
}
switch (cfg->parity)
{
switch (cfg->parity) {
case PARITY_NONE:
usart_parity_config(usart->uart_base, USART_PM_NONE);
usart_parity_config(usart->usart_base, USART_PM_NONE);
break;
case PARITY_ODD:
usart_parity_config(usart->uart_base, USART_PM_ODD);
usart_parity_config(usart->usart_base, USART_PM_ODD);
break;
case PARITY_EVEN:
usart_parity_config(usart->uart_base, USART_PM_EVEN);
usart_parity_config(usart->usart_base, USART_PM_EVEN);
break;
default:
usart_parity_config(usart->uart_base, USART_PM_NONE);
usart_parity_config(usart->usart_base, USART_PM_NONE);
break;
}
usart_hardware_flow_rts_config(usart->uart_base, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(usart->uart_base, USART_CTS_DISABLE);
usart_receive_config(usart->uart_base, USART_RECEIVE_ENABLE);
usart_transmit_config(usart->uart_base, USART_TRANSMIT_ENABLE);
usart_enable(usart->uart_base);
usart_hardware_flow_rts_config(usart->usart_base, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(usart->usart_base, USART_RTS_DISABLE);
usart_receive_config(usart->usart_base, USART_RECEIVE_ENABLE);
usart_transmit_config(usart->usart_base, USART_TRANSMIT_ENABLE);
usart_enable(usart->usart_base);
return RT_EOK;
}
static rt_err_t gd32_control(struct rt_serial_device *serial, int cmd,
void *arg)
{
struct gd32_uart *usart_obj;
struct gd32_uart_config *usart;
void *arg) {
struct gd32_usart *usart;
RT_ASSERT(serial != RT_NULL);
usart_obj = (struct gd32_uart *) serial->parent.user_data;
usart = usart_obj->config;
usart = (struct gd32_usart *) serial->parent.user_data;
RT_ASSERT(usart != RT_NULL);
switch (cmd)
{
switch (cmd) {
case RT_DEVICE_CTRL_CLR_INT:
ECLIC_DisableIRQ(usart->irqn);
usart_interrupt_disable(usart->uart_base, USART_INT_RBNE);
eclic_irq_disable(usart->usart_base);
usart_interrupt_disable(usart->usart_base, USART_INT_RBNE);
break;
case RT_DEVICE_CTRL_SET_INT:
ECLIC_EnableIRQ(usart->irqn);
// eclic_set_nlbits(3);
eclic_irq_enable(usart->irqn, 1, 0);
/* enable USART0 receive interrupt */
usart_interrupt_enable(usart->uart_base, USART_INT_RBNE);
usart_interrupt_enable(usart->usart_base, USART_INT_RBNE);
break;
}
return RT_EOK;
}
static int gd32_putc(struct rt_serial_device *serial, char ch)
{
struct gd32_uart *usart_obj;
struct gd32_uart_config *usart;
static int gd32_putc(struct rt_serial_device *serial, char ch) {
struct gd32_usart *usart;
RT_ASSERT(serial != RT_NULL);
usart_obj = (struct gd32_uart *) serial->parent.user_data;
usart = usart_obj->config;
usart = (struct gd32_usart *) serial->parent.user_data;
RT_ASSERT(usart != RT_NULL);
usart_data_transmit(usart->uart_base, (uint8_t) ch);
while (usart_flag_get(usart->uart_base, USART_FLAG_TBE) == RESET);
usart_data_transmit(usart->usart_base, (uint8_t) ch);
while (usart_flag_get(usart->usart_base, USART_FLAG_TBE) == RESET)
;
return 1;
}
static int gd32_getc(struct rt_serial_device *serial)
{
static int gd32_getc(struct rt_serial_device *serial) {
int ch;
struct gd32_uart *usart_obj;
struct gd32_uart_config *usart;
struct gd32_usart *usart;
RT_ASSERT(serial != RT_NULL);
usart_obj = (struct gd32_uart *) serial->parent.user_data;
usart = usart_obj->config;
usart = (struct gd32_usart *) serial->parent.user_data;
RT_ASSERT(usart != RT_NULL);
ch = -1;
if (RESET != usart_flag_get(usart->uart_base, USART_FLAG_RBNE))
{
ch = usart_data_receive(usart->uart_base) & 0xff;
if (RESET != usart_flag_get(usart->usart_base, USART_FLAG_RBNE)) {
ch = usart_data_receive(usart->usart_base) & 0xff;
}
return ch;
}
static const struct rt_uart_ops gd32_uart_ops = { gd32_configure, gd32_control,
gd32_putc, gd32_getc,
RT_NULL
};
static const struct rt_uart_ops gd32_usart_ops = { gd32_configure, gd32_control,
gd32_putc, gd32_getc,
RT_NULL };
static void usart_isr(struct rt_serial_device *serial)
{
struct gd32_uart *usart_obj;
struct gd32_uart_config *usart;
static void usart_isr(struct rt_serial_device *serial) {
struct gd32_usart *usart;
RT_ASSERT(serial != RT_NULL);
usart_obj = (struct gd32_uart *) serial->parent.user_data;
usart = usart_obj->config;
usart = (struct gd32_usart *) serial->parent.user_data;
RT_ASSERT(usart != RT_NULL);
if ((usart_interrupt_flag_get(usart->uart_base, USART_INT_FLAG_RBNE)
if ((usart_interrupt_flag_get(usart->usart_base, USART_INT_FLAG_RBNE)
!= RESET)
&& (RESET != usart_flag_get(usart->uart_base, USART_FLAG_RBNE)))
{
&& (RESET != usart_flag_get(usart->usart_base, USART_FLAG_RBNE))) {
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
usart_interrupt_flag_clear(usart->uart_base, USART_INT_FLAG_RBNE);
usart_flag_clear(usart->uart_base, USART_FLAG_RBNE);
}
else
{
if (usart_flag_get(usart->uart_base, USART_FLAG_CTSF) != RESET)
{
usart_flag_clear(usart->uart_base, USART_FLAG_CTSF);
usart_interrupt_flag_clear(usart->usart_base, USART_INT_FLAG_RBNE);
usart_flag_clear(usart->usart_base, USART_FLAG_RBNE);
} else {
if (usart_flag_get(usart->usart_base, USART_FLAG_CTSF) != RESET) {
usart_flag_clear(usart->usart_base, USART_FLAG_CTSF);
}
if (usart_flag_get(usart->uart_base, USART_FLAG_LBDF) != RESET)
{
usart_flag_clear(usart->uart_base, USART_FLAG_LBDF);
if (usart_flag_get(usart->usart_base, USART_FLAG_LBDF) != RESET) {
usart_flag_clear(usart->usart_base, USART_FLAG_LBDF);
}
if (usart_flag_get(usart->uart_base, USART_FLAG_TC) != RESET)
{
usart_flag_clear(usart->uart_base, USART_FLAG_TC);
if (usart_flag_get(usart->usart_base, USART_FLAG_TC) != RESET) {
usart_flag_clear(usart->usart_base, USART_FLAG_TC);
}
}
}
#ifdef BSP_USING_UART0
void USART0_IRQHandler(void)
{
void USART0_IRQHandler(void) {
rt_interrupt_enter();
usart_isr(&uart_obj[GDUART0_INDEX].serial);
usart_isr(&usart_config[GDUSART0_INDEX].serial);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_UART1
void USART1_IRQHandler(void)
{
rt_interrupt_enter();
usart_isr(&uart_obj[GDUART1_INDEX].serial);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_UART2
void USART2_IRQHandler(void)
{
rt_interrupt_enter();
usart_isr(&uart_obj[GDUART2_INDEX].serial);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_UART3
void UART3_IRQHandler(void)
{
rt_interrupt_enter();
usart_isr(&uart_obj[GDUART3_INDEX].serial);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_UART4
void UART4_IRQHandler(void)
{
rt_interrupt_enter();
usart_isr(&uart_obj[GDUART4_INDEX].serial);
rt_interrupt_leave();
}
#endif
int rt_hw_usart_init(void)
{
int rt_hw_usart_init(void) {
rt_size_t obj_num;
int index;
#ifdef BSP_USING_UART0
rcu_periph_clock_enable(RCU_USART0);
#endif
#ifdef BSP_USING_UART1
rcu_periph_clock_enable(RCU_USART1);
#endif
#ifdef BSP_USING_UART2
rcu_periph_clock_enable(RCU_USART2);
#endif
#ifdef BSP_USING_UART3
rcu_periph_clock_enable(RCU_UART3);
#endif
#ifdef BSP_USING_UART4
rcu_periph_clock_enable(RCU_UART4);
#endif
obj_num = sizeof(uart_obj) / sizeof(struct gd32_uart);
obj_num = sizeof(usart_config) / sizeof(struct gd32_usart);
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t result = 0;
for (index = 0; index < obj_num; index++)
{
/* init UART object */
uart_obj[index].config = &uart_config[index];
uart_obj[index].serial.ops = &gd32_uart_ops;
uart_obj[index].serial.config = config;
for (index = 0; index < obj_num; index++) {
usart_config[index].serial.ops = &gd32_usart_ops;
usart_config[index].serial.config = config;
/* register UART device */
result = rt_hw_serial_register(&uart_obj[index].serial,
uart_obj[index].config->name,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX, &uart_obj[index]);
result = rt_hw_serial_register(&usart_config[index].serial,
usart_config[index].name,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX, &usart_config[index]);
RT_ASSERT(result == RT_EOK);
}
......
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-04-15 hqfang first version
*/
#ifndef __DRV_UART_H__
#define __DRV_UART_H__
#include <rtthread.h>
#include <rtdevice.h>
#include <drv_config.h>
/* gd32 config class */
struct gd32_uart_config
{
const char *name;
uint32_t uart_base;
IRQn_Type irqn;
};
/* gd32 uart dirver class */
struct gd32_uart
{
struct rt_serial_device serial;
struct gd32_uart_config *config;
};
#include "board.h"
int rt_hw_usart_init(void);
......
......@@ -73,14 +73,27 @@ export PATH=~/NucleiStudio/toolchain/gcc/bin:~/NucleiStudio/toolchain/openocd/bi
**注意**: 请确保Nuclei GCC和Nuclei OpenOCD的路径设置正确无误。
1. 运行 ``pkgs --update``来下载最新的依赖的**Nuclei SDK**开发包
1. 运行 ``pkgs --update``来下载最新的依赖的**Nuclei SDK**开发包,修改链接脚本。
```c
.stack ORIGIN(RAM) + LENGTH(RAM) - __TOT_STACK_SIZE (NOLOAD) :
{
...
PROVIDE( _sp = . );
PROVIDE( __rt_rvstack = . );//在链接脚本中补充该条语句
} >RAM AT>RAM
```
2. **可选**: 运行 ``menuconfig``来进行内核配置
3. 运行 ``scons -c``清理之前的编译结果
4. 根据你当前评估的Nuclei RISC-V内核情况,修改 ``rtconfig.py``中的``NUCLEI_SDK_CORE````NUCLEI_SDK_DOWNLOAD``参数。
- ``NUCLEI_SDK_CORE``可选的参数为[Supported Nuclei Cores](https://doc.nucleisys.com/nuclei_sdk/develop/buildsystem.html#core)
- ``NUCLEI_SDK_DOWNLOAD``可选的参数为``ilm``,``flash``或者``flashxip``, 关于该选项的说明参见[Supported Download Modes](https://doc.nucleisys.com/nuclei_sdk/develop/buildsystem.html#download)
- 假设你手头拿到的Nuclei评估处理器内核为N307(rv32imafc), 想程序运行模式为``flash``,
则修改``NUCLEI_SDK_CORE````n307``, ``NUCLEI_SDK_DOWNLOAD````flash``.
5. 修改完对应的``rtconfig.py``参数配置并保存后,运行 ``scons``来进行代码的编译
### 下载程序
......
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
......@@ -14,6 +14,9 @@
#include "board.h"
#include "cpuport.h"
#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND)
#define RT_KERNEL_INTERRUPT_LEVEL 1
#ifdef RT_USING_SERIAL
#include <drv_uart.h>
#endif
......@@ -32,6 +35,45 @@ extern void *_heap_end;
*/
extern void _init(void);
rt_weak void rt_hw_ticksetup(void)
{
uint64_t ticks = SYSTICK_TICK_CONST;
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
}
#define SysTick_Handler eclic_mtip_handler
/**
* @brief This is the timer interrupt service routine.
*
*/
void SysTick_Handler(void)
{
/* Reload systimer */
SysTick_Reload(SYSTICK_TICK_CONST);
/* enter interrupt */
rt_interrupt_enter();
/* tick increase */
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
/**
* @brief Setup hardware board for rt-thread
*
......
......@@ -12,9 +12,9 @@ if os.getenv('RTT_CC'):
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
if platform.system().lower() == "windows":
EXEC_PATH = 'D:/NucleiStudio/toolchain/gcc/bin'
EXEC_PATH = r'/NucleiStudio/toolchain/gcc/bin'
else:
EXEC_PATH = '~/NucleiStudio/toolchain/gcc/bin'
EXEC_PATH = r'~/NucleiStudio/toolchain/gcc/bin'
if os.path.exists(EXEC_PATH) == False:
print("Warning: Toolchain path %s doesn't exist, assume it is already in PATH" % EXEC_PATH)
EXEC_PATH = '' # Don't set path if not exist
......@@ -56,6 +56,7 @@ if PLATFORM == 'gcc':
CPATH = ''
LPATH = ''
LIBS = ['stdc++']
AFLAGS += ' -D"irq_entry=SW_handler" '
if BUILD == 'debug':
CFLAGS += ' -O2 -ggdb'
......
......@@ -30,38 +30,38 @@
.section .vectors, "ax"
.option norvc;
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
// reset vector
jal x0, Reset_Handler
......@@ -97,6 +97,8 @@ Reset_Handler:
# Enable global interrupt. */
# csrsi mstatus, 8
la t0, __stack
csrw mscratch,t0
jal entry
ebreak
......@@ -182,16 +184,16 @@ end_except:
addi x2, x2, EXCEPTION_STACK_SIZE
mret
.weak IRQ_Handler
.type IRQ_Handler, %function
IRQ_Handler:
.weak SW_handler
.type SW_handler, %function
SW_handler:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
csrr a0, mcause
jal x0, SystemIrqHandler
.size IRQ_Handler, . - IRQ_Handler
.size SW_handler, . - SW_handler
.macro define_exception_entry entry_name handler_name
.weak \entry_name
......
......@@ -29,38 +29,38 @@
.section .vectors, "ax"
.option norvc;
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
jal x0, SW_handler
// reset vector
jal x0, Reset_Handler
......@@ -181,16 +181,16 @@ end_except:
addi x2, x2, EXCEPTION_STACK_SIZE
mret
.weak IRQ_Handler
.type IRQ_Handler, %function
IRQ_Handler:
.weak SW_handler
.type SW_handler, %function
SW_handler:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
csrr a0, mcause
jal x0, SystemIrqHandler
.size IRQ_Handler, . - IRQ_Handler
.size SW_handler, . - SW_handler
.macro define_exception_entry entry_name handler_name
.weak \entry_name
......
......@@ -379,13 +379,7 @@ handle_reset:
ori t0, t0, 3
csrw mtvec, t0
la t0, _eusrstack
addi t0, t0, -512
csrw mscratch,t0
jal SystemInit
la t0, entry
csrw mepc, t0
mret
......@@ -186,6 +186,7 @@ SECTIONS
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
PROVIDE( __rt_rvstack = .);
} >RAM
}
......
......@@ -15,8 +15,8 @@ else:
print('Please make sure your toolchains is GNU GCC!')
exit(0)
# if os.getenv('RTT_EXEC_PATH'):
# EXEC_PATH = os.getenv('RTT_EXEC_PATH')
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
BUILD = 'debug'
#BUILD = 'release'
......
......@@ -194,6 +194,7 @@ SECTIONS
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
PROVIDE( __rt_rvstack = . );
} >RAM
}
......
......@@ -10,6 +10,7 @@
#include <rtthread.h>
#include <rtdevice.h>
#include "ch32v30x.h"
/* defined the LED0 pin: PB5 */
#define LED0_PIN rt_pin_get("PB.5")
......
......@@ -202,6 +202,7 @@ SECTIONS
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
PROVIDE( __rt_rvstack = . );
} >RAM
}
......@@ -10,14 +10,10 @@ group = []
list = os.listdir(cwd)
# add common code files
if rtconfig.CPU == "nuclei" :
group = group
elif rtconfig.CPU == "virt64" :
if rtconfig.CPU == "virt64" :
group = group
elif rtconfig.CPU == "c906" :
group = group
elif rtconfig.CPU == "hpmicro":
group = group
else :
group = group + SConscript(os.path.join('common', 'SConscript'))
......
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "cpuport.h"
.section .text.entry
.align 6 /* In ECLIC mode, the trap entry must be 64bytes aligned */
.global irq_entry
irq_entry:
/* save all from thread context */
addi sp, sp, -32 * REGBYTES
STORE x1, 1 * REGBYTES(sp)
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
move s0, sp
/* switch to interrupt stack */
la sp, _sp
/* interrupt handle */
call rt_interrupt_enter
csrr a0, mcause
csrr a1, mepc
mv a2, sp
csrrw ra, 0x07ED, ra
call rt_interrupt_leave
/* switch to from thread stack */
move sp, s0
/* need to switch new thread */
la s0, rt_thread_switch_interrupt_flag
lw s2, 0(s0)
beqz s2, spurious_interrupt
/* clear switch interrupt flag */
sw zero, 0(s0)
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
la s0, rt_interrupt_from_thread
LOAD s1, 0(s0)
STORE sp, 0(s1)
la s0, rt_interrupt_to_thread
LOAD s1, 0(s0)
LOAD sp, 0(s1)
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
spurious_interrupt:
LOAD x1, 1 * REGBYTES(sp)
/* Remain in M-mode after mret */
li t0, 0x00001800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
mret
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
csrrw ra, 0x07ED, ra
li t0, 0x08
csrc mstatus, t0
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
......@@ -2,16 +2,11 @@
from building import *
Import('rtconfig')
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
CPPPATH = [cwd]
ASFLAGS = ' -I ' + cwd
if rtconfig.PLATFORM == 'gcc':
src += Glob('*_gcc.S')
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
Return('group')
......@@ -8,6 +8,7 @@
* 2021-09-09 WCH the first version
* 2023-01-04 WangShun Remove redundant files
*/
#include "rtconfig.h"
#if defined (SOC_RISCV_SERIES_CH32V1)
#include "ch32v10x.h"
#elif defined (SOC_RISCV_SERIES_CH32V2)
......@@ -17,11 +18,7 @@
#else
#error "CH32 architecture doesn't support!"
#endif
/*
* trigger soft interrupt
*/
void sw_setpend(void)
void rt_trigger_software_interrupt(void)
{
/*CH32V103 does not support systick software interrupt*/
#if defined(SOC_RISCV_SERIES_CH32V1)
......@@ -31,39 +28,14 @@ void sw_setpend(void)
#endif
}
/*
* clear soft interrupt
*/
void sw_clearpend(void)
void rt_hw_do_after_save_above(void)
{
__asm volatile ("li t0,0x20" );
__asm volatile ("csrs 0x804, t0");
/*CH32V103 does not support systick software interrupt*/
#if defined(SOC_RISCV_SERIES_CH32V1)
NVIC_ClearPendingIRQ(Software_IRQn);
#else
SysTick->CTLR &= ~(1 << 31);
#endif
}
/*
* disable interrupt and save mstatus
*/
rt_weak rt_base_t rt_hw_interrupt_disable(void)
{
rt_base_t value=0;
#if defined(SOC_RISCV_SERIES_CH32V3)
asm("csrrw %0, mstatus, %1":"=r"(value):"r"(0x7800));
#else
asm("csrrw %0, mstatus, %1":"=r"(value):"r"(0x1800));
#endif
return value;
}
/*
* enable interrupt and resume mstatus
*/
rt_weak void rt_hw_interrupt_enable(rt_base_t level)
{
asm("csrw mstatus, %0": :"r"(level));
}
}
\ No newline at end of file
......@@ -46,6 +46,9 @@ rt_hw_interrupt_enable:
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
la t0, __rt_rvstack
csrw mscratch,t0
LOAD sp, (a0)
#ifdef RT_USING_SMP
......@@ -214,9 +217,9 @@ rt_hw_context_switch_exit:
LOAD x1, 1 * REGBYTES(sp)
#ifdef ARCH_RISCV_FPU
li t0, 0x00007800
li t0, 0x7800
#else
li t0, 0x00001800
li t0, 0x1800
#endif
csrw mstatus, t0
LOAD a0, 2 * REGBYTES(sp)
......
......@@ -14,6 +14,7 @@
#include <rtthread.h>
#include "cpuport.h"
#include "rt_hw_stack_frame.h"
#ifndef RT_USING_SMP
volatile rt_ubase_t rt_interrupt_from_thread = 0;
......@@ -21,76 +22,6 @@ volatile rt_ubase_t rt_interrupt_to_thread = 0;
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
#endif
struct rt_hw_stack_frame
{
rt_ubase_t epc; /* epc - epc - program counter */
rt_ubase_t ra; /* x1 - ra - return address for jumps */
rt_ubase_t mstatus; /* - machine status register */
rt_ubase_t gp; /* x3 - gp - global pointer */
rt_ubase_t tp; /* x4 - tp - thread pointer */
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
rt_ubase_t a7; /* x17 - s7 - function argument 7 */
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
#ifdef ARCH_RISCV_FPU
rv_floatreg_t f0; /* f0 */
rv_floatreg_t f1; /* f1 */
rv_floatreg_t f2; /* f2 */
rv_floatreg_t f3; /* f3 */
rv_floatreg_t f4; /* f4 */
rv_floatreg_t f5; /* f5 */
rv_floatreg_t f6; /* f6 */
rv_floatreg_t f7; /* f7 */
rv_floatreg_t f8; /* f8 */
rv_floatreg_t f9; /* f9 */
rv_floatreg_t f10; /* f10 */
rv_floatreg_t f11; /* f11 */
rv_floatreg_t f12; /* f12 */
rv_floatreg_t f13; /* f13 */
rv_floatreg_t f14; /* f14 */
rv_floatreg_t f15; /* f15 */
rv_floatreg_t f16; /* f16 */
rv_floatreg_t f17; /* f17 */
rv_floatreg_t f18; /* f18 */
rv_floatreg_t f19; /* f19 */
rv_floatreg_t f20; /* f20 */
rv_floatreg_t f21; /* f21 */
rv_floatreg_t f22; /* f22 */
rv_floatreg_t f23; /* f23 */
rv_floatreg_t f24; /* f24 */
rv_floatreg_t f25; /* f25 */
rv_floatreg_t f26; /* f26 */
rv_floatreg_t f27; /* f27 */
rv_floatreg_t f28; /* f28 */
rv_floatreg_t f29; /* f29 */
rv_floatreg_t f30; /* f30 */
rv_floatreg_t f31; /* f31 */
#endif
};
/**
* This function will initialize thread stack
*
......@@ -127,14 +58,24 @@ rt_uint8_t *rt_hw_stack_init(void *tentry,
/* force to machine mode(MPP=11) and set MPIE to 1 */
#ifdef ARCH_RISCV_FPU
frame->mstatus = 0x00007880;
frame->mstatus = 0x7880;
#else
frame->mstatus = 0x00001880;
frame->mstatus = 0x1880;
#endif
return stk;
}
rt_weak void rt_trigger_software_interrupt(void)
{
while (0);
}
rt_weak void rt_hw_do_after_save_above(void)
{
while (1);
}
/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
......@@ -150,9 +91,9 @@ rt_weak void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_t
rt_interrupt_to_thread = to;
rt_thread_switch_interrupt_flag = 1;
#if defined(SOC_RISCV_FAMILY_CH32)
sw_setpend();
#endif
rt_trigger_software_interrupt();
return ;
}
#endif /* end of RT_USING_SMP */
......
......@@ -14,11 +14,6 @@
#define CPUPORT_H__
#include <rtconfig.h>
#if !defined(__ASSEMBLY__)
#if defined(SOC_RISCV_FAMILY_CH32)
#include "interrupt.h"
#endif
#endif
#ifndef __ASSEMBLY__
#ifdef RT_USING_SMP
......@@ -32,6 +27,15 @@ typedef union {
#endif
#endif
/* Preprocessor Definition */
#if __riscv_flen == 32
#define ARCH_RISCV_FPU_S
#endif
#if __riscv_flen == 64
#define ARCH_RISCV_FPU_D
#endif
/* bytes of register width */
#ifdef ARCH_CPU_64BIT
#define STORE sd
......@@ -43,6 +47,7 @@ typedef union {
#define REGBYTES 4
#endif
/* Preprocessor Definition */
#ifdef ARCH_RISCV_FPU
#ifdef ARCH_RISCV_FPU_D
#define FSTORE fsd
......
......@@ -5,17 +5,23 @@
*
* Change Logs:
* Date Author Notes
* 2021-09-09 WCH the first version
* 2022-12-27 WangShun Merge WCH series mcu port files
* 2023/01/17 WangShun The first version
*/
#define __ASSEMBLY__
#include "cpuport.h"
.global SW_handler
.align 2
.section .text.entry, "ax"
#if defined(SOC_SERIES_GD32VF103V)
.align 6
#else
.align 2
#endif
.global SW_handler
SW_handler:
/* save all from thread context */
li t0, 0x08
csrc mstatus, t0
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES
FSTORE f0, 0 * FREGBYTES(sp)
......@@ -51,21 +57,13 @@ SW_handler:
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
/* save all from thread context */
addi sp, sp, -32 * REGBYTES
STORE x5, 5 * REGBYTES(sp)
/* saved MPIE */
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
/* Temporarily disable HPE */
#if defined (SOC_RISCV_SERIES_CH32V3)
li t0, 0x20
csrs 0x804, t0
#endif
STORE x1, 1 * REGBYTES(sp)
/* Mandatory set the MPIE of mstatus */
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
......@@ -95,20 +93,23 @@ SW_handler:
STORE x31, 31 * REGBYTES(sp)
/* switch to interrupt stack */
csrrw sp,mscratch,sp
csrrw sp,mscratch,sp
/* interrupt handle */
call rt_interrupt_enter
/* clear interrupt */
jal sw_clearpend
/* Do the work after saving the above */
jal rt_hw_do_after_save_above
call rt_interrupt_leave
/* switch to from thread stack */
csrrw sp,mscratch,sp
csrrw sp,mscratch,sp
/* if rt_thread_switch_interrupt_flag=1,then clear it */
/* Determine whether to trigger scheduling at the interrupt function */
la s0, rt_thread_switch_interrupt_flag
lw s2, 0(s0)
beqz s2, 1f
/* clear the flag of rt_thread_switch_interrupt_flag */
sw zero, 0(s0)
#1:
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
......@@ -123,16 +124,14 @@ SW_handler:
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
1: LOAD x1, 1 * REGBYTES(sp)
#if defined (SOC_RISCV_SERIES_CH32V3)
li t0,0x7800
csrs mstatus, t0
#else
li t0,0x1800
csrs mstatus, t0
#endif
LOAD t0, 2*REGBYTES(sp)
csrs mstatus, t0
1:
LOAD x1, 1 * REGBYTES(sp)
/* Set the mode after MRET */
li t0, 0x1800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
......@@ -162,9 +161,8 @@ SW_handler:
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
/* load float reg */
addi sp, sp, 32 * REGBYTES
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp)
FLOAD f1, 1 * FREGBYTES(sp)
......@@ -198,6 +196,7 @@ SW_handler:
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret
......@@ -83,5 +83,4 @@ typedef struct rt_hw_stack_frame
#endif
}rt_hw_stack_frame_t;
#endif /* RISCV_STACKFRAME_H */
#include <rthw.h>
#include <rtthread.h>
#include "riscv-ops.h"
#include "rt_hw_stack_frame.h"
#define ISR_NUMBER 32
static volatile rt_hw_stack_frame_t *s_stack_frame;
static struct rt_irq_desc rv32irq_table[ISR_NUMBER];
void rt_show_stack_frame(void);
/**
* Temporary interrupt entry function
*
* @param mcause Machine Cause Register
* @return RT_NULL
*/
rt_weak rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t mcause)
{
rt_kprintf("UN-handled interrupt %d occurred!!!\n", mcause);
return RT_NULL;
}
/**
* Interrupt entry function initialization
*/
rt_weak void rt_hw_interrupt_init(void)
{
int idx = 0;
for (idx = 0; idx < ISR_NUMBER; idx++)
{
rv32irq_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
rv32irq_table[idx].param = RT_NULL;
}
}
/**
* Break Entry Function Binding
*
* @param vector interrupt number
* @param handler Break-in function requiring binding
* @param param NULL
* @param name NULL
* @return NULL
*/
rt_weak rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
void *user_param = param;
char *user_name = name;
if(vector < ISR_NUMBER)
{
if (handler != RT_NULL)
{
rv32irq_table[vector].handler = (rt_isr_handler_t)handler;
rv32irq_table[vector].param = param;
}
}
}
/**
* Query and Distribution Entry for Exception and Interrupt Sources
*
* @param mcause Machine Cause Register
*/
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
{
rt_uint32_t mscratch = read_csr(0x340);
rt_uint32_t irq_id = (mcause & 0x1F);
rt_uint32_t exception = !(mcause & 0x80000000);
if(exception)
{
s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
rt_show_stack_frame();
}
else
{
rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param);
}
}
/**
* Register Print on Exception
*/
rt_weak void rt_show_stack_frame(void)
{
rt_kprintf("Stack frame:\r\n----------------------------------------\r\n");
rt_kprintf("ra : 0x%08x\r\n", s_stack_frame->ra);
rt_kprintf("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus
rt_kprintf("t0 : 0x%08x\r\n", s_stack_frame->t0);
rt_kprintf("t1 : 0x%08x\r\n", s_stack_frame->t1);
rt_kprintf("t2 : 0x%08x\r\n", s_stack_frame->t2);
rt_kprintf("a0 : 0x%08x\r\n", s_stack_frame->a0);
rt_kprintf("a1 : 0x%08x\r\n", s_stack_frame->a1);
rt_kprintf("a2 : 0x%08x\r\n", s_stack_frame->a2);
rt_kprintf("a3 : 0x%08x\r\n", s_stack_frame->a3);
rt_kprintf("a4 : 0x%08x\r\n", s_stack_frame->a4);
rt_kprintf("a5 : 0x%08x\r\n", s_stack_frame->a5);
rt_kprintf("a6 : 0x%08x\r\n", s_stack_frame->a6);
rt_kprintf("a7 : 0x%08x\r\n", s_stack_frame->a7);
rt_kprintf("t3 : 0x%08x\r\n", s_stack_frame->t3);
rt_kprintf("t4 : 0x%08x\r\n", s_stack_frame->t4);
rt_kprintf("t5 : 0x%08x\r\n", s_stack_frame->t5);
rt_kprintf("t6 : 0x%08x\r\n", s_stack_frame->t6);
}
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/01 Bernard The first version
*/
#include <rthw.h>
#include <stdint.h>
#include <rtthread.h>
typedef void (*irq_handler_t)(void);
extern const irq_handler_t isr_table[];
extern void vSystemIrqHandler(uint32_t mcause);
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/02 Bernard The first version
*/
#include "cpuport.h"
.section .text.entry
.align 2
.global IRQ_Handler
IRQ_Handler:
/* save all from thread context */
addi sp, sp, -32 * REGBYTES
STORE x1, 1 * REGBYTES(sp)
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
move s0, sp
/* switch to interrupt stack */
la sp, __freertos_irq_stack_top
/* interrupt handle */
call rt_interrupt_enter
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call vSystemIrqHandler
call rt_interrupt_leave
/* switch to from thread stack */
move sp, s0
/* need to switch new thread */
la s0, rt_thread_switch_interrupt_flag
lw s2, 0(s0)
beqz s2, spurious_interrupt
/* clear switch interrupt flag */
sw zero, 0(s0)
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
la s0, rt_interrupt_from_thread
LOAD s1, 0(s0)
STORE sp, 0(s1)
la s0, rt_interrupt_to_thread
LOAD s1, 0(s0)
LOAD sp, 0(s1)
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
spurious_interrupt:
LOAD x1, 1 * REGBYTES(sp)
/* Remain in M-mode after mret */
li t0, 0x00001800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
mret
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call rt_rv32_system_irq_handler
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/02 Bernard The first version
*/
#include "cpuport.h"
.section .text.entry
.align 2
.global trap_entry
trap_entry:
/* save all from thread context */
addi sp, sp, -32 * REGBYTES
STORE x1, 1 * REGBYTES(sp)
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
/* save break thread stack to s0 */
move s0, sp
/* switch to interrupt stack */
la sp, _sp
/* interrupt handle */
call rt_interrupt_enter
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call handle_trap
call rt_interrupt_leave
/* switch to from_thread stack */
move sp, s0
/* need to switch new thread */
la s0, rt_thread_switch_interrupt_flag
lw s2, 0(s0)
beqz s2, spurious_interrupt
sw zero, 0(s0)
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
la s0, rt_interrupt_from_thread
LOAD s1, 0(s0)
STORE sp, 0(s1)
la s0, rt_interrupt_to_thread
LOAD s1, 0(s0)
LOAD sp, 0(s1)
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
spurious_interrupt:
LOAD x1, 1 * REGBYTES(sp)
/* Remain in M-mode after mret */
li t0, 0x00001800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
mret
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call handle_trap
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
\ No newline at end of file
......@@ -11,7 +11,7 @@ if rtconfig.PLATFORM == 'gcc':
src += Glob('*_gcc.S')
CPPPATH = [cwd]
ASFLAGS = ''
ASFLAGS = ' -I ' + cwd
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
......
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/28 Bernard The unify RISC-V porting implementation
* 2018/12/27 Jesven Add SMP support
* 2020/11/20 BalanceTWK Add FPU support
*/
#include "cpuport.h"
#ifdef RT_USING_SMP
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
#endif
/*
* rt_base_t rt_hw_interrupt_disable(void);
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
csrrci a0, mstatus, 8
ret
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
csrw mstatus, a0
ret
/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
* #else
* void rt_hw_context_switch_to(rt_ubase_t to);
* #endif
* a0 --> to
* a1 --> to_thread
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
LOAD sp, (a0)
#ifdef RT_USING_SMP
mv a0, a1
call rt_cpus_lock_status_restore
#endif
LOAD a0, 2 * REGBYTES(sp)
csrw mstatus, a0
j rt_hw_context_switch_exit
/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
* #else
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
* #endif
*
* a0 --> from
* a1 --> to
* a2 --> to_thread
*/
.globl rt_hw_context_switch
rt_hw_context_switch:
/* saved from thread context
* x1/ra -> sp(0)
* x1/ra -> sp(1)
* mstatus.mie -> sp(2)
* x(i) -> sp(i-4)
*/
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES
FSTORE f0, 0 * FREGBYTES(sp)
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
addi sp, sp, -32 * REGBYTES
STORE sp, (a0)
STORE x1, 0 * REGBYTES(sp)
STORE x1, 1 * REGBYTES(sp)
csrr a0, mstatus
andi a0, a0, 8
beqz a0, save_mpie
li a0, 0x80
save_mpie:
STORE a0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
/* restore to thread context
* sp(0) -> epc;
* sp(1) -> ra;
* sp(i) -> x(i+2)
*/
LOAD sp, (a1)
#ifdef RT_USING_SMP
mv a0, a2
call rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
j rt_hw_context_switch_exit
#ifdef RT_USING_SMP
/*
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
*
* a0 --> context
* a1 --> from
* a2 --> to
* a3 --> to_thread
*/
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
STORE a0, 0(a1)
LOAD sp, 0(a2)
move a0, a3
call rt_cpus_lock_status_restore
j rt_hw_context_switch_exit
#endif
.global rt_hw_context_switch_exit
rt_hw_context_switch_exit:
#ifdef RT_USING_SMP
#ifdef RT_USING_SIGNALS
mv a0, sp
csrr t0, mhartid
/* switch interrupt stack of current cpu */
la sp, __stack_start__
addi t1, t0, 1
li t2, __STACKSIZE__
mul t1, t1, t2
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
call rt_signal_check
mv sp, a0
#endif
#endif
/* resw ra to mepc */
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
LOAD x1, 1 * REGBYTES(sp)
li t0, 0x00007800
csrw mstatus, t0
LOAD a0, 2 * REGBYTES(sp)
csrs mstatus, a0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp)
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret
/*
#include <rt-thread/libcpu/risc-v/hpmicro/cpuport.h>
#include <rt-thread/libcpu/risc-v/hpmicro/riscv-stackframe.h>
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/28 Bernard The unify RISC-V porting code.
* 2020/11/20 BalanceTWK Add FPU support
*/
#include <rthw.h>
#include <rtthread.h>
#include "riscv-stackframe.h"
volatile rt_ubase_t rt_interrupt_from_thread = 0;
volatile rt_ubase_t rt_interrupt_to_thread = 0;
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry,
void *parameter,
rt_uint8_t *stack_addr,
void *texit)
{
struct rt_hw_stack_frame *frame;
rt_uint8_t *stk;
int i;
stk = stack_addr + sizeof(rt_ubase_t);
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
stk -= sizeof(struct rt_hw_stack_frame);
frame = (struct rt_hw_stack_frame *)stk;
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
{
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
}
frame->ra = (rt_ubase_t)texit;
frame->a0 = (rt_ubase_t)parameter;
frame->epc = (rt_ubase_t)tentry;
/* force to machine mode(MPP=11) and set MPIE to 1 */
frame->mstatus = 0x00007880;
return stk;
}
/*
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
*/
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
{
if (rt_thread_switch_interrupt_flag == 0)
rt_interrupt_from_thread = from;
rt_interrupt_to_thread = to;
rt_thread_switch_interrupt_flag = 1;
return ;
}
/** shutdown CPU */
rt_weak void rt_hw_cpu_shutdown()
{
rt_uint32_t level;
rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
}
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-10-03 Bernard The first version
* 2020/11/20 BalanceTWK Add FPU support
*/
#ifndef CPUPORT_H__
#define CPUPORT_H__
#include <rtconfig.h>
/* bytes of register width */
#define STORE sw
#define LOAD lw
#define REGBYTES 4
#ifdef __riscv_flen
#define ARCH_RISCV_FPU
#if __riscv_flen == 32
#define ARCH_RISCV_FPU_S
#endif
#if __riscv_flen == 64
#define ARCH_RISCV_FPU_D
#endif
#endif
#ifdef ARCH_RISCV_FPU
#ifdef ARCH_RISCV_FPU_D
#define FSTORE fsd
#define FLOAD fld
#define FREGBYTES 8
#define rv_floatreg_t rt_int64_t
#endif
#ifdef ARCH_RISCV_FPU_S
#define FSTORE fsw
#define FLOAD flw
#define FREGBYTES 4
#define rv_floatreg_t rt_int32_t
#endif
#endif
#endif
/*
* Copyright (c) 2021 - 2022 hpmicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Change Logs:
* Date Author Notes
* 2022/01/16 HPMicro The first version
* 2020/04/27 HPMicro Bugfix for interrupt management
*/
#include "cpuport.h"
.section .isr_vector, "ax"
.global irq_handler_trap
.align 2
irq_handler_trap:
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES
FSTORE f0, 0 * FREGBYTES(sp)
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
/* save all from thread context */
addi sp, sp, -32 * REGBYTES
STORE x1, 1 * REGBYTES(sp) // ra
li t0, 0x80
STORE t0, 2 * REGBYTES(sp) // mstatus
STORE x4, 4 * REGBYTES(sp) // tp - thread pointer
STORE x5, 5 * REGBYTES(sp) // t0
STORE x6, 6 * REGBYTES(sp) // t1
STORE x7, 7 * REGBYTES(sp) // t2
STORE x8, 8 * REGBYTES(sp) // s0/fp
STORE x9, 9 * REGBYTES(sp) // s1
STORE x10, 10 * REGBYTES(sp) // a0
STORE x11, 11 * REGBYTES(sp) // a1
STORE x12, 12 * REGBYTES(sp) // a2
STORE x13, 13 * REGBYTES(sp) // a3
STORE x14, 14 * REGBYTES(sp) // a4
STORE x15, 15 * REGBYTES(sp) // a5
STORE x16, 16 * REGBYTES(sp) // a6
STORE x17, 17 * REGBYTES(sp) // a7
STORE x18, 18 * REGBYTES(sp) // s2
STORE x19, 19 * REGBYTES(sp) // s3
STORE x20, 20 * REGBYTES(sp) // s4
STORE x21, 21 * REGBYTES(sp) // s5
STORE x22, 22 * REGBYTES(sp) // s6
STORE x23, 23 * REGBYTES(sp) // s7
STORE x24, 24 * REGBYTES(sp) // s8
STORE x25, 25 * REGBYTES(sp) // s9
STORE x26, 26 * REGBYTES(sp) // s10
STORE x27, 27 * REGBYTES(sp) // s11
STORE x28, 28 * REGBYTES(sp) // t3
STORE x29, 29 * REGBYTES(sp) // t4
STORE x30, 30 * REGBYTES(sp) // t5
STORE x31, 31 * REGBYTES(sp) // t6
/* Save the thread stack frame base to mscratch */
csrw mscratch, sp
/* switch to interrupt stack */
la sp, _stack
/* interrupt handle */
call rt_interrupt_enter
/* Get the thread stack frame base from mscratch */
csrr a0, mscratch
call trap_entry
call rt_interrupt_leave
/* switch to thread stack */
csrr sp, mscratch
/* need to switch new thread */
la s0, rt_thread_switch_interrupt_flag
lw s2, 0(s0)
beqz s2, spurious_interrupt
/* clear switch interrupt flag */
sw zero, 0(s0)
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
la s0, rt_interrupt_from_thread
LOAD s1, 0(s0)
STORE sp, 0(s1)
la s0, rt_interrupt_to_thread
LOAD s1, 0(s0)
LOAD sp, 0(s1)
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
spurious_interrupt:
LOAD x1, 1 * REGBYTES(sp) // ra
/* Remain in M-mode after mret */
li t0, 0x00001800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0 // mstatus.mpie
LOAD x4, 4 * REGBYTES(sp) // tp
LOAD x5, 5 * REGBYTES(sp) // t0
LOAD x6, 6 * REGBYTES(sp) // t1
LOAD x7, 7 * REGBYTES(sp) // t2
LOAD x8, 8 * REGBYTES(sp) // s0/fp
LOAD x9, 9 * REGBYTES(sp) // s1
LOAD x10, 10 * REGBYTES(sp) // a0
LOAD x11, 11 * REGBYTES(sp) // a1
LOAD x12, 12 * REGBYTES(sp) // a2
LOAD x13, 13 * REGBYTES(sp) // a3
LOAD x14, 14 * REGBYTES(sp) // a4
LOAD x15, 15 * REGBYTES(sp) // a5
LOAD x16, 16 * REGBYTES(sp) // a6
LOAD x17, 17 * REGBYTES(sp) // a7
LOAD x18, 18 * REGBYTES(sp) // s2
LOAD x19, 19 * REGBYTES(sp) // s3
LOAD x20, 20 * REGBYTES(sp) // s4
LOAD x21, 21 * REGBYTES(sp) // s5
LOAD x22, 22 * REGBYTES(sp) // s6
LOAD x23, 23 * REGBYTES(sp) // s7
LOAD x24, 24 * REGBYTES(sp) // s8
LOAD x25, 25 * REGBYTES(sp) // s9
LOAD x26, 26 * REGBYTES(sp) // s10
LOAD x27, 27 * REGBYTES(sp) // s11
LOAD x28, 28 * REGBYTES(sp) // t3
LOAD x29, 29 * REGBYTES(sp) // t4
LOAD x30, 30 * REGBYTES(sp) // t5
LOAD x31, 31 * REGBYTES(sp) // t6
addi sp, sp, 32 * REGBYTES
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp)
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mscratch
call trap_entry
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
\ No newline at end of file
......@@ -7,7 +7,7 @@ Import('rtconfig')
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
CPPPATH = [cwd]
ASFLAGS = ''
ASFLAGS = ' -I ' + cwd
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
......
/*
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/03/26 Huaqi First Nuclei RISC-V porting implementation
*/
#include "riscv_encoding.h"
#ifndef __riscv_32e
#define RT_SAVED_REGNUM 30
#else
#define RT_SAVED_REGNUM 14
#endif
#define RT_CONTEXT_SIZE (RT_SAVED_REGNUM * REGBYTES)
.extern rt_interrupt_from_thread
.extern rt_interrupt_to_thread
.section .text
/*
* void rt_hw_context_switch_to(rt_ubase_t to);
* a0 --> to_thread
*/
.globl rt_hw_context_switch_to
/* Start the first task. This also clears the bit that indicates the FPU is
in use in case the FPU was used before the scheduler was started - which
would otherwise result in the unnecessary leaving of space in the stack
for lazy saving of FPU registers. */
.align 3
rt_hw_context_switch_to:
/* Setup Interrupt Stack using
The stack that was used by main()
before the scheduler is started is
no longer required after the scheduler is started.
Interrupt stack pointer is stored in CSR_MSCRATCH */
la t0, _sp
csrw CSR_MSCRATCH, t0
LOAD sp, 0x0(a0) /* Read sp from first TCB member(a0) */
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp)
csrw CSR_MEPC, t0
/* Pop mstatus from stack and set it */
LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
#endif
addi sp, sp, RT_CONTEXT_SIZE
mret
.align 2
.global eclic_msip_handler
eclic_msip_handler:
addi sp, sp, -RT_CONTEXT_SIZE
STORE x1, 1 * REGBYTES(sp) /* RA */
STORE x5, 2 * REGBYTES(sp)
STORE x6, 3 * REGBYTES(sp)
STORE x7, 4 * REGBYTES(sp)
STORE x8, 5 * REGBYTES(sp)
STORE x9, 6 * REGBYTES(sp)
STORE x10, 7 * REGBYTES(sp)
STORE x11, 8 * REGBYTES(sp)
STORE x12, 9 * REGBYTES(sp)
STORE x13, 10 * REGBYTES(sp)
STORE x14, 11 * REGBYTES(sp)
STORE x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 13 * REGBYTES(sp)
STORE x17, 14 * REGBYTES(sp)
STORE x18, 15 * REGBYTES(sp)
STORE x19, 16 * REGBYTES(sp)
STORE x20, 17 * REGBYTES(sp)
STORE x21, 18 * REGBYTES(sp)
STORE x22, 19 * REGBYTES(sp)
STORE x23, 20 * REGBYTES(sp)
STORE x24, 21 * REGBYTES(sp)
STORE x25, 22 * REGBYTES(sp)
STORE x26, 23 * REGBYTES(sp)
STORE x27, 24 * REGBYTES(sp)
STORE x28, 25 * REGBYTES(sp)
STORE x29, 26 * REGBYTES(sp)
STORE x30, 27 * REGBYTES(sp)
STORE x31, 28 * REGBYTES(sp)
#endif
/* Push mstatus to stack */
csrr t0, CSR_MSTATUS
STORE t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
/* Push additional registers */
/* Store sp to task stack */
LOAD t0, rt_interrupt_from_thread
STORE sp, 0(t0)
csrr t0, CSR_MEPC
STORE t0, 0(sp)
jal rt_hw_taskswitch
/* Switch task context */
LOAD t0, rt_interrupt_to_thread
LOAD sp, 0x0(t0)
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp)
csrw CSR_MEPC, t0
/* Pop additional registers */
/* Pop mstatus from stack and set it */
LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
#endif
addi sp, sp, RT_CONTEXT_SIZE
mret
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/03/26 Huaqi Nuclei RISC-V Core porting code.
*/
#include <rthw.h>
#include <rtthread.h>
#include <sys/types.h>
#include <unistd.h>
#include "cpuport.h"
#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND)
/* Interrupt level for kernel systimer interrupt and software timer interrupt */
#define RT_KERNEL_INTERRUPT_LEVEL 0
/* Initial CSR MSTATUS value when thread created */
#define RT_INITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
/**
* @brief from thread used interrupt context switch
*
*/
volatile rt_ubase_t rt_interrupt_from_thread = 0;
/**
* @brief to thread used interrupt context switch
*
*/
volatile rt_ubase_t rt_interrupt_to_thread = 0;
/**
* @brief flag to indicate context switch in interrupt or not
*
*/
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
/**
* @brief thread stack frame of saved context
*
*/
struct rt_hw_stack_frame
{
rt_ubase_t epc; /*!< epc - epc - program counter */
rt_ubase_t ra; /*!< x1 - ra - return address for jumps */
rt_ubase_t t0; /*!< x5 - t0 - temporary register 0 */
rt_ubase_t t1; /*!< x6 - t1 - temporary register 1 */
rt_ubase_t t2; /*!< x7 - t2 - temporary register 2 */
rt_ubase_t s0_fp; /*!< x8 - s0/fp - saved register 0 or frame pointer */
rt_ubase_t s1; /*!< x9 - s1 - saved register 1 */
rt_ubase_t a0; /*!< x10 - a0 - return value or function argument 0 */
rt_ubase_t a1; /*!< x11 - a1 - return value or function argument 1 */
rt_ubase_t a2; /*!< x12 - a2 - function argument 2 */
rt_ubase_t a3; /*!< x13 - a3 - function argument 3 */
rt_ubase_t a4; /*!< x14 - a4 - function argument 4 */
rt_ubase_t a5; /*!< x15 - a5 - function argument 5 */
#ifndef __riscv_32e
rt_ubase_t a6; /*!< x16 - a6 - function argument 6 */
rt_ubase_t a7; /*!< x17 - s7 - function argument 7 */
rt_ubase_t s2; /*!< x18 - s2 - saved register 2 */
rt_ubase_t s3; /*!< x19 - s3 - saved register 3 */
rt_ubase_t s4; /*!< x20 - s4 - saved register 4 */
rt_ubase_t s5; /*!< x21 - s5 - saved register 5 */
rt_ubase_t s6; /*!< x22 - s6 - saved register 6 */
rt_ubase_t s7; /*!< x23 - s7 - saved register 7 */
rt_ubase_t s8; /*!< x24 - s8 - saved register 8 */
rt_ubase_t s9; /*!< x25 - s9 - saved register 9 */
rt_ubase_t s10; /*!< x26 - s10 - saved register 10 */
rt_ubase_t s11; /*!< x27 - s11 - saved register 11 */
rt_ubase_t t3; /*!< x28 - t3 - temporary register 3 */
rt_ubase_t t4; /*!< x29 - t4 - temporary register 4 */
rt_ubase_t t5; /*!< x30 - t5 - temporary register 5 */
rt_ubase_t t6; /*!< x31 - t6 - temporary register 6 */
#endif
rt_ubase_t mstatus; /*!< - machine status register */
};
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry,
void *parameter,
rt_uint8_t *stack_addr,
void *texit)
{
struct rt_hw_stack_frame *frame;
rt_uint8_t *stk;
int i;
stk = stack_addr + sizeof(rt_ubase_t);
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
stk -= sizeof(struct rt_hw_stack_frame);
frame = (struct rt_hw_stack_frame *)stk;
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
{
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
}
frame->ra = (rt_ubase_t)texit;
frame->a0 = (rt_ubase_t)parameter;
frame->epc = (rt_ubase_t)tentry;
frame->mstatus = RT_INITIAL_MSTATUS;
return stk;
}
/**
* @brief Do rt-thread context switch in interrupt context
*
* @param from thread sp of from thread
* @param to thread sp of to thread
*/
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
{
if (rt_thread_switch_interrupt_flag == 0)
rt_interrupt_from_thread = from;
rt_interrupt_to_thread = to;
rt_thread_switch_interrupt_flag = 1;
RT_YIELD();
}
/**
* @brief Do rt-thread context switch in task context
*
* @param from thread sp of from thread
* @param to thread sp of to thread
*/
void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)
{
rt_hw_context_switch_interrupt(from, to);
}
/**
* @brief shutdown CPU
*
*/
rt_weak void rt_hw_cpu_shutdown()
{
rt_base_t level;
rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
}
/**
* @brief Do extra task switch code
*
* @details
*
* - Clear software timer interrupt request flag
* - clear rt_thread_switch_interrupt_flag to 0
*/
void rt_hw_taskswitch(void)
{
/* Clear Software IRQ, A MUST */
SysTimer_ClearSWIRQ();
rt_thread_switch_interrupt_flag = 0;
}
/**
* @brief Setup systimer and software timer interrupt
*
* @details
*
* - Set Systimer interrupt as NON-VECTOR interrupt with lowest interrupt level
* - Set software timer interrupt as VECTOR interrupt with lowest interrupt level
* - Enable these two interrupts
*/
void rt_hw_ticksetup(void)
{
uint64_t ticks = SYSTICK_TICK_CONST;
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
}
/**
* systimer interrupt handler eclic_mtip_handler
* is hard coded in startup_<Device>.S
* We define SysTick_Handler as eclic_mtip_handler
* for easy understanding
*/
#define SysTick_Handler eclic_mtip_handler
/**
* @brief This is the timer interrupt service routine.
*
*/
void SysTick_Handler(void)
{
/* Reload systimer */
SysTick_Reload(SYSTICK_TICK_CONST);
/* enter interrupt */
rt_interrupt_enter();
/* tick increase */
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
/**
* @brief Disable cpu interrupt
*
* @details
*
* - Disable cpu interrupt by clear MIE bit in MSTATUS
* - Return the previous value in MSTATUS before clear MIE bit
*
* @return the previous value in MSTATUS before clear MIE bit
*/
rt_base_t rt_hw_interrupt_disable(void)
{
return __RV_CSR_READ_CLEAR(CSR_MSTATUS, MSTATUS_MIE);
}
/**
* @brief Restore previous saved interrupt status
*
* @param level previous saved MSTATUS value
*/
void rt_hw_interrupt_enable(rt_base_t level)
{
__RV_CSR_WRITE(CSR_MSTATUS, level);
}
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/03/26 hqfang Nuclei RISC-V Core porting code.
*/
#ifndef __CPUPORT_H__
#define __CPUPORT_H__
#include <rtconfig.h>
#include <nuclei_sdk_soc.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Scheduler utilities. */
#define RT_YIELD() \
{ \
/* Set a software interrupt(SWI) request to request a context switch. */ \
SysTimer_SetSWIRQ(); \
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__RWMB(); \
__FENCE_I(); \
}
extern void rt_hw_ticksetup(void);
extern void rt_hw_taskswitch(void);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/03/26 hqfang First Nuclei RISC-V porting implementation
*/
#include "riscv_encoding.h"
.section .text.entry
.align 8
/**
* \brief Global interrupt disabled
* \details
* This function disable global interrupt.
* \remarks
* - All the interrupt requests will be ignored by CPU.
*/
.macro DISABLE_MIE
csrc CSR_MSTATUS, MSTATUS_MIE
.endm
/**
* \brief Macro for context save
* \details
* This macro save ABI defined caller saved registers in the stack.
* \remarks
* - This Macro could use to save context when you enter to interrupt
* or exception
*/
/* Save caller registers */
.macro SAVE_CONTEXT
csrrw sp, CSR_MSCRATCHCSWL, sp
/* Allocate stack space for context saving */
#ifndef __riscv_32e
addi sp, sp, -20*REGBYTES
#else
addi sp, sp, -14*REGBYTES
#endif /* __riscv_32e */
STORE x1, 0*REGBYTES(sp)
STORE x4, 1*REGBYTES(sp)
STORE x5, 2*REGBYTES(sp)
STORE x6, 3*REGBYTES(sp)
STORE x7, 4*REGBYTES(sp)
STORE x10, 5*REGBYTES(sp)
STORE x11, 6*REGBYTES(sp)
STORE x12, 7*REGBYTES(sp)
STORE x13, 8*REGBYTES(sp)
STORE x14, 9*REGBYTES(sp)
STORE x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 14*REGBYTES(sp)
STORE x17, 15*REGBYTES(sp)
STORE x28, 16*REGBYTES(sp)
STORE x29, 17*REGBYTES(sp)
STORE x30, 18*REGBYTES(sp)
STORE x31, 19*REGBYTES(sp)
#endif /* __riscv_32e */
.endm
/**
* \brief Macro for restore caller registers
* \details
* This macro restore ABI defined caller saved registers from stack.
* \remarks
* - You could use this macro to restore context before you want return
* from interrupt or exeception
*/
/* Restore caller registers */
.macro RESTORE_CONTEXT
LOAD x1, 0*REGBYTES(sp)
LOAD x4, 1*REGBYTES(sp)
LOAD x5, 2*REGBYTES(sp)
LOAD x6, 3*REGBYTES(sp)
LOAD x7, 4*REGBYTES(sp)
LOAD x10, 5*REGBYTES(sp)
LOAD x11, 6*REGBYTES(sp)
LOAD x12, 7*REGBYTES(sp)
LOAD x13, 8*REGBYTES(sp)
LOAD x14, 9*REGBYTES(sp)
LOAD x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 14*REGBYTES(sp)
LOAD x17, 15*REGBYTES(sp)
LOAD x28, 16*REGBYTES(sp)
LOAD x29, 17*REGBYTES(sp)
LOAD x30, 18*REGBYTES(sp)
LOAD x31, 19*REGBYTES(sp)
/* De-allocate the stack space */
addi sp, sp, 20*REGBYTES
#else
/* De-allocate the stack space */
addi sp, sp, 14*REGBYTES
#endif /* __riscv_32e */
csrrw sp, CSR_MSCRATCHCSWL, sp
.endm
/**
* \brief Macro for save necessary CSRs to stack
* \details
* This macro store MCAUSE, MEPC, MSUBM to stack.
*/
.macro SAVE_CSR_CONTEXT
/* Store CSR mcause to stack using pushmcause */
csrrwi x0, CSR_PUSHMCAUSE, 11
/* Store CSR mepc to stack using pushmepc */
csrrwi x0, CSR_PUSHMEPC, 12
/* Store CSR msub to stack using pushmsub */
csrrwi x0, CSR_PUSHMSUBM, 13
.endm
/**
* \brief Macro for restore necessary CSRs from stack
* \details
* This macro restore MSUBM, MEPC, MCAUSE from stack.
*/
.macro RESTORE_CSR_CONTEXT
LOAD x5, 13*REGBYTES(sp)
csrw CSR_MSUBM, x5
LOAD x5, 12*REGBYTES(sp)
csrw CSR_MEPC, x5
LOAD x5, 11*REGBYTES(sp)
csrw CSR_MCAUSE, x5
.endm
/**
* \brief Exception/NMI Entry
* \details
* This function provide common entry functions for exception/nmi.
* \remarks
* This function provide a default exception/nmi entry.
* ABI defined caller save register and some CSR registers
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.trap
/* In CLIC mode, the exeception entry must be 64bytes aligned */
.align 6
.global exc_entry
exc_entry:
/* Save the caller saving registers (context) */
SAVE_CONTEXT
/* Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/*
* Set the exception handler function arguments
* argument 1: mcause value
* argument 2: current stack point(SP) value
*/
csrr a0, mcause
mv a1, sp
/*
* TODO: Call the exception handler function
* By default, the function template is provided in
* system_Device.c, you can adjust it as you want
*/
call core_exception_handler
/* Restore the necessary CSR registers */
RESTORE_CSR_CONTEXT
/* Restore the caller saving registers (context) */
RESTORE_CONTEXT
/* Return to regular code */
mret
/**
* \brief Non-Vector Interrupt Entry
* \details
* This function provide common entry functions for handling
* non-vector interrupts
* \remarks
* This function provide a default non-vector interrupt entry.
* ABI defined caller save register and some CSR registers need
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.irq
/* In CLIC mode, the interrupt entry must be 4bytes aligned */
.align 2
.global irq_entry
/* This label will be set to MTVT2 register */
irq_entry:
/* Save the caller saving registers (context) */
SAVE_CONTEXT
/* Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/* This special CSR read/write operation, which is actually
* claim the CLIC to find its pending highest ID, if the ID
* is not 0, then automatically enable the mstatus.MIE, and
* jump to its vector-entry-label, and update the link register
*/
csrrw ra, CSR_JALMNXTI, ra
/* Critical section with interrupts disabled */
DISABLE_MIE
/* Restore the necessary CSR registers */
RESTORE_CSR_CONTEXT
/* Restore the caller saving registers (context) */
RESTORE_CONTEXT
/* Return to regular code */
mret
/* Default Handler for Exceptions / Interrupts */
.global default_intexc_handler
Undef_Handler:
default_intexc_handler:
1:
j 1b
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
csrrw ra, 0x07ED, ra
li t0, 0x08
csrc mstatus, t0
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
### RV32移植指南
#### 1.概述
为了简化RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹
| 文件名 | 文件内容 |
| :-----------------: | :----------------------------: |
| context_gcc.S | 开关全局中断,线程上下文切换等 |
| cpuport.c | 线程栈初始化,软件中断触发等 |
| cpuport.h | 数据加载写入指令 |
| interrupt_gcc.S | 线程间上下文切换 |
| riscv-ops.h | 控制状态寄存器读写 |
| rt_hw_stack_frame.h | 线程栈格式 |
| trap_common.c | 中断注册,中断查询分发 |
#### 2.移植接口
(1)软件中断触发函数,通常向量管理中断需实现该函数,非向量中断管理方式一般不需要
```c
void rt_trigger_software_interrupt(void)
```
(2)保存上文后执行函数,该函数向量中断与非向量中断均需实现
```c
void rt_hw_do_after_save_above(void)
```
该函数需要实现的工作如下:
步骤1:将函数返回地址(ra)保存栈中
步骤2:加载中断处理函数的入口参数
步骤3:调用中断处理函数
步骤4:从栈中加载返回地址(ra),返回至SW_handler函数
#### 3.准备工作
- 准备一个基础的裸机工程,需具备以下条件:
- 明确中断管理方式(向量中断/非向量中断)
- 实现系统节拍定时器中断
- 实现一个串口中断
#### 4.移植步骤
<font color=red>对于新移植的RISC-V 32位内核,若采用非向量中断管理方式,推荐使用common中的文件,除了下述步骤中必要的修改以及中断初始化与注册步骤外,用户仅需拷贝一份cv32e40p移植文件,重命名为具体内核名称即可 。</font>
- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler**
- 根据使用的中断管理方式,执行下述操作
- 向量中断管理方式
> 通常会使用一个软件中断(该中断的优先级被配置为最低)作为在中断中触发上下文切换的入口函数。SW_handler在此仅作为触发软件中断时的入口参数,其他类型中断触发时跳转至各自的中断入口函数。
>
移植方法:修改原有的中断向量表中软件中断所在位置,将原有软件中断函数名修改为**SW_handler**
示例(ch32系列):
```assembly
_vector_base:
.option norvc;
.word _start
...
.word SW_handler /* 将这里原来放置的软件中断函数名修改为SW_handler */
```
- 非向量中断
> 当有中断触发时,会进入一个统一的中断入口函数进行中断查询分发。SW_handler在此处不仅作为作为在中断中触发上下文切换的入口函数,同时承担中断查询分发与执行。
>
移植方法:将**SW_handler**的地址加载到保存统一中断入口地址的寄存器(通常为mtevc,具体名称需要根据具体的内核指定)
示例(hpm6750系列):
```assembly
la t0, SW_handler
csrw mtvec, t0
```
- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码
- 将下述代码放置于链接脚本中中断栈顶名之后
```assembly
PROVIDE( __rt_rvstack = . );
```
- 示例(core-v-mcu链接脚本):
```assembly
.stack : ALIGN(16)
{
stack_start = .;
__stack_bottom = .;
. += __stack_size;
__stack_top = .;
PROVIDE( __rt_rvstack = . );//移植时添加
stack = .;
} > L2
```
> __stack_top为core-v-mcu工程的中断栈顶名 不同工程此处的名称可能不一致 按上述方法将给出的代码放到具体工程链接脚本中断栈顶名称之后即可。
- 步骤三:实现在中断上下文切换的函数接口
<font color=red>RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,为用户提供了统一的中断查询分发函数以及相关函数 ,该部分内容位于common文件夹的trap_common.c文件中,对于移植一个新的RV32内核推荐使用RT-Thread提供的统一函数接口。以下是两种实现方式的示例:</font>
(一)采用RT-Thread通用中断分发函数
采用RT-Thread提供的通用中断查询分发函数时,移植文件直接拷贝一份cv32e40p内核移植文件,重命名为具体内核名称即可,移植代码如下:
```assembly
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call rt_rv32_system_irq_handler
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
```
RT-Thread提供的通用中断分发函数如下:
```c
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
{
rt_uint32_t mscratch = read_csr(0x340);
rt_uint32_t irq_id = (mcause & 0x1F);
rt_uint32_t exception = !(mcause & 0x80000000);
if(exception)
{
s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
rt_show_stack_frame();
}
else
{
rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param);
}
}
```
随后用户仅需调用rt_hw_interrupt_init进行初始化,然后将中断入口函数通过rt_hw_interrupt_install函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下:
```c
rt_hw_interrupt_init();
rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");
rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");
```
(二)采用原有裸机的中断入口处理函数
新建一个文件夹,并以移植的内核的名称命名:
- 向量中断(可参考ch32)
(1)在刚才新建的文件夹下,创建一个c文件,用于实现上文提供的两个函数接口
(2)实现上述两个函数接口
- 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作
- 在void rt_hw_do_after_save_above(void)中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作
- 非向量中断(可参考cv32e40p)
- 在刚才新建的文件夹下,创建一个汇编文件,实现上述提供的函数接口
- 对于非向量中断的管理方式仅需实现rt_hw_do_after_save_above函数即可
示例代码:
```assembly
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4 // 移动栈指针
STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中
csrr a0, mscratch // 加载函数入口参数
call trap_entry // 调用中断处理函数
LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值
addi sp, sp, 4 // 移动栈指针
ret // 返回SW_handler
```
trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。
#### 5.验证
- 创建一个静态线程,在线程中调用RT-Thread提供的与系统时基相关函数接口,例如rt_thread_mdelay,调试观察系统是否可以正常运行
- 移植RT-Thread的shell进一步验证系统是否移植成功
此差异已折叠。
#include "cpuport.h"
.globl rt_hw_do_after_save_above
.type rt_hw_do_after_save_above,@function
rt_hw_do_after_save_above:
addi sp, sp, -4
STORE ra, 0 * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call SystemIrqHandler
LOAD ra, 0 * REGBYTES(sp)
addi sp, sp, 4
ret
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册