0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Smart riscv64汇编注释

RTThread物联网操作系统 来源:未知 2023-02-08 21:40 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

以rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码仓库地址https://gitee.com/rtthread/rt-thread/tree/rt-smart

启动

代码路径

libcpu isc-v -headc906startup_gcc.S

/*
*Copyright(c)2006-2018,RT-ThreadDevelopmentTeam
*
*SPDX-License-Identifier:Apache-2.0
*
*ChangeLogs:
*DateAuthorNotes
*2018/10/01BernardThefirstversion
*2018/12/27JesvenAddSMPsupport
*2020/6/12XimPorttoQEMUandremoveSMPsupport
*/


#define__ASSEMBLY__
#defineSSTATUS_FS0x00006000U/*initialstateofFPU,cleartodisable*/
#include

.global_start
.section".start","ax"
_start:
j1f
.word0xdeadbeef
.align3
.globalg_wake_up
g_wake_up:
.dword1
.dword0
1:
csrwsie,0/*超级用户模式中断使能关闭*/
csrwsip,0/*超级用户模式中断等待关闭*/
lat0,trap_entry/*将trap_entry的地址放入t0寄存器*/
csrwstvec,t0/*配置异常服务程序的入口地址*/

lix1,0
/*...........*//*初始化通用寄存器*/
lix31,0

/*settodisableFPU*/
lit0,SSTATUS_FS/*将FS的bit位写入t0寄存器*/
csrcsstatus,t0/*清除sstatus中的FSbit,关闭浮点单元*/
lit0,0x40000/*当SUM=1时,超级用户模式下,加载、存储和取指令请求可以访问标记为用户态的虚拟内存空间*/
csrssstatus,t0/*置位sstatus中的SUM位*/

.optionpush
.optionnorelax
lagp,__global_pointer$
.optionpop

//removedSMPsupporthere
lasp,__stack_start__/*栈指针的值来自于链接脚本中的__stack_start*/
lit0,__STACKSIZE__
addsp,sp,t0/*栈自上到下增长*/
csrwsscratch,sp/*sscratch存储栈顶的地址*/
jprimary_cpu_entry/*跳转到board中的C程序入口*/
//BSP的C入口
voidprimary_cpu_entry(void)
{
externvoidentry(void);

//初始化BSS
init_bss();
//关中断
rt_hw_interrupt_disable();
rt_assert_set_hook(__rt_assert_handler);
//启动RT-ThreadSmart内核
entry();
}

异常处理

异常处理流程图



异常处理上半部分

/*libcpu
isc-v	-headc906interrupt_gcc.S*/

#define__ASSEMBLY__
#include"cpuport.h"
#include"encoding.h"
#include"stackframe.h"

.section.text.entry
.align2
.globaltrap_entry
.extern__stack_cpu0
.externget_current_thread_kernel_stack_top
trap_entry:/*异常处理函数的入口*/
//backupsp
csrrwsp,sscratch,sp/*将当前栈与sscratch做交换*/
//loadinterruptstack
lasp,__stack_cpu0/*sp指向cpu0的中断栈的栈顶*/
//backupcontext
SAVE_ALL/*CPU寄存器入栈,使能浮点的情况下浮点相关的寄存器也要入栈并且要保存sstatus中浮点的运算状态*/

RESTORE_SYS_GP/*gp操作不用了解*/

//checksyscall
csrrt0,scause/*读取scaue到t0*/
lit1,8//environmentcallfromu-mode/*用户模式环境调用异常*/
beqt0,t1,syscall_entry/*如果是系统调用则跳转到系统调用处理函数,这个函数最终会调用sret*/

csrra0,scause/*读取scause到a0,机器模式异常事件向量寄存器(MCAUSE)用于保存触发异常的异常事件向量号,用于在异常服务程序中处理对应事件*/
csrrca1,stval,zero/*读取stval到a1,发生异常或者中断,且在机器模式响应时,处理器会更新pc到MEPC,并根据异常类型更新MTVAL*/
csrra2,sepc/*读取sepc到a2,超级用户模式异常保留程序计数器(SEPC)用于存储程序从异常服务程序退出时的程序计数器值(即
PC值)*/

mva3,sp/*读取sp的值到a3*/

/*scause,stval,sepc,sp*/
callhandle_trap/*进行中断处理*/

中断处理

/*libcpu
isc-v	-headc906	rap.c*/
/*Trapentry*/
voidhandle_trap(rt_size_tscause,rt_size_tstval,rt_size_tsepc,structrt_hw_stack_frame*sp)
{
/*
SCAUSE
bit63Interrupt-中断标记位
当 Interrupt 位为0时,表示触发异常的来源不是中断, Exception Code 按照异常解析。当 Interrupt 位为 1 时,表示触发异常的来源是中断, Exception Code 按照中断解析。该位会被 reset 置为 1’ b0。
bit0~4ExceptionCode-异常向量号位
在处理器响应异常或中断时,该域会被更新为对应异常号,具体请参考表3.9异常和中断向量分
配。该位会被 reset 置为 5’ b0。
*/



/*我理解这里是想获取ExceptionCode,但是ExceptionCode是bit0~bit4,这里用__MASK(5UL)更合适吧*/
rt_size_tid=__MASKVALUE(scause,__MASK(63UL));
constchar*msg;

/*supervisorexternalinterrupt*/
/*如果scause的bit63是1,scause的bit0~4是9超级用户模式外部中断*/
if((SCAUSE_INTERRUPT&scause)&&SCAUSE_S_EXTERNAL_INTR==(scause&0xff))
{
rt_interrupt_enter();
plic_handle_irq();
rt_interrupt_leave();
return;
}/*如果scause的bit63是1,scause的bit0~4是超级用户模式计时器中断*/
elseif((SCAUSE_INTERRUPT|SCAUSE_S_TIMER_INTR)==scause)
{
/*supervisortimer*/
rt_interrupt_enter();
tick_isr();
rt_interrupt_leave();
return;
}/*其他中断*/
elseif(SCAUSE_INTERRUPT&scause)
{
if(id< sizeof(Interrupt_Name)/sizeof(constchar*))
{
msg=Interrupt_Name[id];
}
else
{
msg="UnknownInterrupt";
}
LOG_E("UnhandledInterrupt%ld:%s ",id,msg);
}
else/*异常处理*/
{
#ifdefRT_USING_USERSPACE
/*pagefault缺页异常处理*/
if(id==EP_LOAD_PAGE_FAULT||
id==EP_STORE_PAGE_FAULT)
{
arch_expand_user_stack((void*)stval);
return;
}
#endif/*其他异常处理,走到这里后打印一些必要信息,最终会走到while(1),进入死循环*/
if(id< sizeof(Exception_Name)/sizeof(constchar*))
{
msg=Exception_Name[id];
}
else
{
msg="UnknownException";
}

rt_kprintf("UnhandledException%ld:%s ",id,msg);
}

rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p ",scause,stval,sepc);
dump_regs(sp);
while(1);
}

在rt-smart中任务切换有三个相关的线程函数

  • rt_hw_context_switch_to():没有来源线程,切换到目标线程,在调度器启动第一个线程的时候 被调用
  • rt_hw_context_switch():在线程环境下,从当前线程切换到目标线程
  • rt_hw_context_switch_interrupt ():在中断环境下,从当前线程切换到目标线程。

rt_hw_context_switch_interrupt ()会将rt_thread_switch_interrupt_flag置为1,真正的线程切换动作在异常处理函数中完成。

异常处理下半部分

/*needtoswitchnewthread查询线程切换的flag是否被置位为1*/
las0,rt_thread_switch_interrupt_flag/*读取rt_thread_switch_interrupt_flag*/
lws2,0(s0)
beqzs2,spurious_interrupt/*rt_thread_switch_interrupt_flag如果为0那么直接跳转到spurious_interrupt进行寄存器恢复,并调用sret回到异常之前的状态*/
swzero,0(s0)/*rt_thread_switch_interrupt_flag=0*/

.globalrt_hw_context_switch_interrupt_do
rt_hw_context_switch_interrupt_do:

//swaptothreadkernelstack
csrrt0,sstatus/*读取sstatus到t0*/
andit0,t0,0x100/*bit8超级用户模式保留特权状态位*/
/*
该位用于保存处理器在降级到超级用户模式进入异常服务程序前的特权状态。
•当 SPP 为 2’ b00时,表示处理器进入异常服务程序前处于用户模式;
•当 SPP 为 2’ b01 时,表示处理器进入异常服务程序前处于超级用户模式;
该位会被 reset 置 2’ b01。
*/

beqzt0,__restore_sp_from_tcb_interrupt/*如果是内核态发生异常*/

__restore_sp_from_sscratch_interrupt:
csrrt0,sscratch/*获取发生异常时的上下文数据*/
j__move_stack_context_interrupt/*如果是用户态发生异常*/

/*获取当前线程的栈顶位置存到t0中*/
__restore_sp_from_tcb_interrupt:
las0,rt_interrupt_from_thread
LOADa0,0(s0)
jalrt_thread_sp_to_thread
jalget_thread_kernel_stack_top
mvt0,a0

__move_stack_context_interrupt:
mvt1,sp//src/*当前栈,当前栈存储的是发生异常时的通用寄存器信息*/
mvsp,t0//switchstack/*将发生异常时的栈的值写回到sp寄存器*/
addisp,sp,-CTX_REG_NR*REGBYTES/*栈指针向下移动CTX_REG_NR*REGBYTES*/
//copycontext
lis0,CTX_REG_NR//cnt/*需要恢复的寄存器的个数加载到s0*/
mvt2,sp//dst/*栈指针加载到t2*/
/*总结就是,当前CPU的中断栈存储了当前线程的通用寄存器的信息,如果发生任务切换,需要把这些信息拷贝到线程的栈里*/

copy_context_loop_interrupt:
LOADt0,0(t1)/*t1的值放到t0*/
STOREt0,0(t2)/*t0的值放到t2*/
addis0,s0,-1/*要恢复的寄存器个数-1*/
addit1,t1,8/*t1的地址加8*/
addit2,t2,8/*t2的地址加8*/
bnezs0,copy_context_loop_interrupt/*如果s0不为0就重复拷贝*/

las0,rt_interrupt_from_thread
LOADs1,0(s0)
STOREsp,0(s1)/*更新from线程的sp指针*/

las0,rt_interrupt_to_thread
LOADs1,0(s0)
LOADsp,0(s1)/*恢复to线程的sp*/

#ifdefRT_USING_USERSPACE
mva0,s1
jalrt_thread_sp_to_thread
jallwp_mmu_switch/*切换mmu,函数内部会判断from线程和to线程是不是在同一个lwp中,不是的话就会切换MMU*/
#endif

spurious_interrupt:
RESTORE_ALL/*恢复寄存器*/
sret/*超级用户模式异常返回指令*/

———————End———————


你可以添加微信:rtthread2020 为好友,注明:公司+姓名,拉进RT-Thread官方微信交流群!



爱我就给我点在看

点击阅读原文


原文标题:RT-Smart riscv64汇编注释

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RT-Thread
    +关注

    关注

    32

    文章

    1540

    浏览量

    44251

原文标题:RT-Smart riscv64汇编注释

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【CIE全国RISC-V创新应用大赛】+MUSE Pi Pro RiscV UEFI固件开发

    /edk2-non-osi 1.4 RiscV64工具链的前缀定义 为RiscV64工具链指定前缀变量,参考如下命令: #define RISCV64 prefix export
    发表于 11-13 00:20

    全志D1开发板(哪吒 RISCV64)开箱评测

    ,WIFI之类的全都不开源,另外完整的原理图也没有。玩上层应用很简单,但是底层就很复杂了。 这块板子,因为只配置了单核,感觉学习Linux、学习riscv,使用rtos等等,都是不错的选择,我感觉移植rt-smart或者鸿蒙系统还是有点意思。
    发表于 10-31 07:50

    riscv实现自定义指令并用qemu运行

    sifive的交叉编译工具链即可,不需要自己编译工具链,添加到系统环境变量,即可编译。 通过反汇编查看 riscv64-unknown-elf-objdump-D build/bin/rv64
    发表于 10-31 07:37

    请问rt smart 的用户应用程序能自动加载吗?

    请问rt smart 的用户应用程序能自动加载吗?只需要将内核和用户程序隔离开,开机自动加载
    发表于 10-13 06:17

    QEMU快速上手(Win),源码文件夹对不上是为什么?

    想要照着RTT文档里的RT-Smart的QEMU快速上手 https://www.rt-thread.org/document/site/#/rt
    发表于 09-29 06:57

    求助,关于rt-smart用户态线程实时性差的问题求解

    我在树莓派4B上使用v5.2.0 开启smartrt-thread 并启用SMP多核(4核)内核时,在用户态和内核态运行同样的代码测试: #include #include
    发表于 09-26 08:25

    目前最新版的userapps如何安装D1s环境?

    存在问题的,报错信息如下: oxlm@IT000:~/workspace/rt-smart/userapps$ python3 tools/get_toolchain.py riscv64
    发表于 09-25 07:33

    riscv virt64编译后 ls无法运行怎么解决?

    用仓库里的默认配置编译qemu-virt64-riscv 生成后运行,显示 [E/DBG] virtio-blk0 mount failed ls看不到文件夹 msh />ls No such directory
    发表于 09-22 06:38

    RT-Thread BSP全面支持玄铁全系列RISC-V 处理器 | 技术集结

    RT-Thread标准版已全面适配玄铁E、R、C系列内核,并在C906内核上支持RT-Smart微内核操作系统。本文将以E906运行RT-Thread和C906运行
    的头像 发表于 07-03 18:03 2635次阅读
    <b class='flag-5'>RT</b>-Thread BSP全面支持玄铁全系列RISC-V 处理器 | 技术集结

    【M-K1HSE开发板免费体验】超高性能与颜值RISCV64位8核视美泰M-K1HSE开发板

    【超高性能与颜值RISCV64位8核视美泰M-K1HSE开发板】 https://www.bilibili.com/video/BV1dQKZzsERi/?share_source
    发表于 06-26 23:14

    请问Openvino是否支持 Risc-V (riscv64) 架构?

    在spacemit k1型板(bpi-f3)上编译OpenVINO™,但失败。 使用 riscv64 构建OpenVINO™并崩溃。
    发表于 06-24 07:26

    如何在K230上移植mipi sensor,然后读取mipi接口的raw数据?

    知道吗? 期待结果 给出移植的教程,CanMV、linux平台、RT-Smart或者Linux+RT-Smart的都可以 软硬件版本信息 CanMV-K230-LP4-V3.0
    发表于 06-17 06:22

    K230使用RT-Smart SDK开发怎么连接Wifi?

    RT-Smart SDK开发K230怎么去连接无线网,板子上面有网络模块和天线,01Studio的K230,找不到相关资料,求助大佬,感谢感谢
    发表于 06-10 08:23

    RT-Thread Smart携手K230/K230D打造多核RISC-V高性能嵌入式操作系统

    在万物互联的智能时代,国产软硬件技术的突破正成为推动产业升级的核心动力。RT-ThreadSmart(简称:RT-Smart)操作系统与嘉楠科技K230芯片的深度融合,为AI边缘计算领域带来了一站式
    的头像 发表于 03-17 16:35 2316次阅读
    <b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b>携手K230/K230D打造多核RISC-V高性能嵌入式操作系统

    RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!

    2024年RT-Thread开发者大会将于12月21日正式拉开帷幕!本次大会以“开源共生商业共赢”为主题,RT-Thread将携手合作伙伴、客户伙伴、行业专家,以及全球开发者,共同探索如何在开源
    的头像 发表于 12-11 18:41 2937次阅读
    <b class='flag-5'>RT-Smart</b>首次线下培训,锁定2024 <b class='flag-5'>RT</b>-Thread开发者大会!