[libcpu/risc-v]更新移植readme
This commit is contained in:
parent
e722733178
commit
cfc6bf9b12
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#### 1.概述
|
#### 1.概述
|
||||||
|
|
||||||
为了简化RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹
|
为了简化32位RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹
|
||||||
|
|
||||||
| 文件名 | 文件内容 |
|
| 文件名 | 文件内容 |
|
||||||
| :-----------------: | :----------------------------: |
|
| :-----------------: | :----------------------------: |
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#### 2.移植接口
|
#### 2.移植接口
|
||||||
|
|
||||||
(1)软件中断触发函数,通常向量管理中断需实现该函数,非向量中断管理方式一般不需要
|
(1)软件中断触发函数,通常向量管理中断方式需实现该函数,非向量中断管理方式一般不需要
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void rt_trigger_software_interrupt(void)
|
void rt_trigger_software_interrupt(void)
|
||||||
|
@ -34,7 +34,7 @@ void rt_hw_do_after_save_above(void)
|
||||||
|
|
||||||
步骤2:加载中断处理函数的入口参数
|
步骤2:加载中断处理函数的入口参数
|
||||||
|
|
||||||
步骤3:调用中断处理函数
|
步骤3:调用中断处理函数(新移植的BSP推荐使用RT-Thread common_trap.c文件中提供的统一中断处理函数:rt_rv32_system_irq_handler)
|
||||||
|
|
||||||
步骤4:从栈中加载返回地址(ra),返回至SW_handler函数
|
步骤4:从栈中加载返回地址(ra),返回至SW_handler函数
|
||||||
|
|
||||||
|
@ -49,8 +49,6 @@ void rt_hw_do_after_save_above(void)
|
||||||
|
|
||||||
#### 4.移植步骤
|
#### 4.移植步骤
|
||||||
|
|
||||||
<font color=red>对于新移植的RISC-V 32位内核,若采用非向量中断管理方式,推荐使用common中的文件,除了下述步骤中必要的修改以及中断初始化与注册步骤外,用户仅需拷贝一份cv32e40p移植文件,重命名为具体内核名称即可 。</font>
|
|
||||||
|
|
||||||
- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler**
|
- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler**
|
||||||
|
|
||||||
- 根据使用的中断管理方式,执行下述操作
|
- 根据使用的中断管理方式,执行下述操作
|
||||||
|
@ -88,7 +86,7 @@ void rt_hw_do_after_save_above(void)
|
||||||
|
|
||||||
- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码
|
- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码
|
||||||
|
|
||||||
- 将下述代码放置于链接脚本中中断栈顶名之后
|
- 将下述代码放置于链接脚本中中断栈顶名称之后
|
||||||
|
|
||||||
```assembly
|
```assembly
|
||||||
PROVIDE( __rt_rvstack = . );
|
PROVIDE( __rt_rvstack = . );
|
||||||
|
@ -112,11 +110,11 @@ void rt_hw_do_after_save_above(void)
|
||||||
|
|
||||||
- 步骤三:实现在中断上下文切换的函数接口
|
- 步骤三:实现在中断上下文切换的函数接口
|
||||||
|
|
||||||
<font color=red>RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,为用户提供了统一的中断查询分发函数以及相关函数 ,该部分内容位于common文件夹的trap_common.c文件中,对于移植一个新的RV32内核推荐使用RT-Thread提供的统一函数接口。以下是两种实现方式的示例:</font>
|
<font color=red>RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,针对非向量模式的中断管理方式,common文件夹中的trap_common.c为用户提供了一套统一的中断查询分发、中断入口函数注册以及中断初始化函数,在rthw.h中声明,对于移植一个新的RV32内核,若采用非向量中断管理的方式,推荐使用方式一,若采用向量中断管理方式或针对中断的处理有专门的优化时推荐使用方式二,期望采用原有裸机工程的统一的中断查询与处理函数也可使用方式二。以下是两种实现方式的示例:</font>
|
||||||
|
|
||||||
(一)采用RT-Thread通用中断分发函数
|
方式一:面向非向量中断管理方式(例:core-v-mcu)
|
||||||
|
|
||||||
采用RT-Thread提供的通用中断查询分发函数时,移植文件直接拷贝一份cv32e40p内核移植文件,重命名为具体内核名称即可,移植代码如下:
|
在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,该函数的实现如下(用户直接使用,无需修改):
|
||||||
|
|
||||||
```assembly
|
```assembly
|
||||||
#include "cpuport.h"
|
#include "cpuport.h"
|
||||||
|
@ -137,69 +135,46 @@ void rt_hw_do_after_save_above(void)
|
||||||
ret
|
ret
|
||||||
```
|
```
|
||||||
|
|
||||||
RT-Thread提供的通用中断分发函数如下:
|
随后用户仅需调用rt_hw_interrupt_init进行初始化,再将中断入口函数通过rt_hw_interrupt_install函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下(相关设备的中断入口函数注册之前不可使用该设备):
|
||||||
|
|
||||||
```c
|
```c
|
||||||
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
|
rt_hw_interrupt_init();//中断入口函数初始化
|
||||||
{
|
rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");//注册系统定时器中断入口函数
|
||||||
rt_uint32_t mscratch = read_csr(0x340);
|
rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");//注册外部中断入口函数
|
||||||
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函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下:
|
方式二:面向向量中断管理方式(例:CH32)与针对中断管理有专门优化的内核(例:GD32)
|
||||||
|
|
||||||
```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)
|
- 向量中断(可参考ch32)
|
||||||
|
|
||||||
(1)在刚才新建的文件夹下,创建一个c文件,用于实现上文提供的两个函数接口
|
在RT-Thread的BSP框架中的board文件夹创建需要的文件,实现下述的两个函数:
|
||||||
|
|
||||||
(2)实现上述两个函数接口
|
|
||||||
- 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作
|
- 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作
|
||||||
- 在void rt_hw_do_after_save_above(void)中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作
|
|
||||||
|
|
||||||
- 非向量中断(可参考cv32e40p)
|
- 在void rt_hw_do_after_save_above(void) 中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作
|
||||||
|
|
||||||
- 在刚才新建的文件夹下,创建一个汇编文件,实现上述提供的函数接口
|
- 非向量中断(期望采用原有裸机工程的统一的中断查询与处理函数)
|
||||||
- 对于非向量中断的管理方式仅需实现rt_hw_do_after_save_above函数即可
|
|
||||||
|
|
||||||
示例代码:
|
在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,此步骤与方式一提供的方法相似,仅在调用中断处理函数以及传递的参数不同,需要根据具体的移植工程实现,方式二下该函数的实现如下:
|
||||||
|
|
||||||
```assembly
|
示例代码:
|
||||||
|
|
||||||
|
```assembly
|
||||||
#include "cpuport.h"
|
#include "cpuport.h"
|
||||||
|
|
||||||
.globl rt_hw_do_after_save_above
|
.globl rt_hw_do_after_save_above
|
||||||
.type rt_hw_do_after_save_above,@function
|
.type rt_hw_do_after_save_above,@function
|
||||||
rt_hw_do_after_save_above:
|
rt_hw_do_after_save_above:
|
||||||
addi sp, sp, -4 // 移动栈指针
|
addi sp, sp, -4 // 移动栈指针
|
||||||
STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中
|
STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中
|
||||||
|
|
||||||
csrr a0, mscratch // 加载函数入口参数
|
csrr a0, mscratch// 加载函数入口参数
|
||||||
call trap_entry // 调用中断处理函数
|
call trap_entry// 调用中断处理函数
|
||||||
|
|
||||||
LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值
|
LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值
|
||||||
addi sp, sp, 4 // 移动栈指针
|
addi sp, sp, 4// 移动栈指针
|
||||||
ret // 返回SW_handler
|
ret // 返回SW_handler
|
||||||
```
|
```
|
||||||
|
|
||||||
trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。
|
trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue