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
    +关注

    关注

    31

    文章

    1148

    浏览量

    38875

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

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

收藏 人收藏

    评论

    相关推荐

    rtthread d1s编译报错的原因是什么?如何处理?

    我使用使用的是现在git上的rtthread的最新的master分支,因为rt-smart已经并入主线,所以我想在windows下用env工具编译。 因为要编译riscv架构的全志D1S,我下载了
    发表于 02-22 06:43

    RT-Smart开发笔记:int类型数值溢出造成的奇怪问题的分析与排查记录

    最近在调试 RT-Smart 上的用户态 mq(消息队列)时,遇到一个奇怪的问题,这个例程打印了一下获取的时间,就可以正常的工作(超时退出),否则,就一直卡住(无法超时)
    的头像 发表于 10-31 16:16 442次阅读
    <b class='flag-5'>RT-Smart</b>开发笔记:int类型数值溢出造成的奇怪问题的分析与排查记录

    RT-Smart应用开发笔记:fopen造成文件被清空问题的分析记录

    RT-Smart 应用(apps)开发环境,ubuntu 20.04 + win10 VS Code
    的头像 发表于 10-20 16:01 298次阅读
    <b class='flag-5'>RT-Smart</b>应用开发笔记:fopen造成文件被清空问题的分析记录

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释rt-smartriscv64上的系统初始化和异常处理的代码
    的头像 发表于 10-12 17:26 340次阅读
    <b class='flag-5'>RT-Smart</b> <b class='flag-5'>riscv64</b><b class='flag-5'>汇编</b><b class='flag-5'>注释</b>

    Rt-Smartriscv中的初始化流程

    Virt板是一个不对应于任何真实硬件的平台;它是为虚拟机设计的。如果你只是想运行Linux等客户机,而不关心重现真实世界硬件的特殊性和局限性,那么它是推荐的板卡类型。
    的头像 发表于 10-12 14:15 1147次阅读
    <b class='flag-5'>Rt-Smart</b>在<b class='flag-5'>riscv</b>中的初始化流程

    RT-Thread Smart qemu-virt64-riscv用户态userapps的编译与运行

    rt-smart 上,为了实现用户态与内核态的分离,使用了【系统调用】,这个系统调用可以认为是个 sdk
    的头像 发表于 10-08 15:33 609次阅读
    <b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b> qemu-virt<b class='flag-5'>64-riscv</b>用户态userapps的编译与运行

    搭建D1s RT-Smart开发环境踩坑笔记

    作为一个linux新手想要尝试RT-Smart的开发,但是网上教程前辈们的linux环境都是已经相对完备的,因此像我这样新手在搭建环境时常常缺这缺那的导致报错,经过一段时间的踩坑终于搞定了,因此和大家分享我遇到的坑和解决方法。
    的头像 发表于 09-28 16:26 500次阅读
    搭建D1s <b class='flag-5'>RT-Smart</b>开发环境踩坑笔记

    基于xmake的RT-Thread Smart用户态开发教程

    RT-Thread Smart(以下简称 Smart) 是基于 RT-Thread 操作系统上的混合操作系统,简称为 rt-smart,它把
    的头像 发表于 09-14 11:48 712次阅读
    基于xmake的<b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b>用户态开发教程

    rt-smart应用程序系统调用实现过程是怎么样的?

    rt-smart应用程序系统调用实现过程是怎么样的? 比如open时候怎么一步一步切换到内核态的?
    发表于 09-08 17:00

    全志D1开发板RISCV64开箱评测

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

    零基础上手rt-smart适配bsp

    RT-Thread Smart(简称rt-smart)是基于RT-Thread操作系统衍生,面向带MMU(Memory Management Unit),中高端应用的芯片,例如ARM
    的头像 发表于 08-08 10:34 591次阅读
    零基础上手<b class='flag-5'>rt-smart</b>适配bsp

    请问一下rt-smart可以运行opencv吗?

    rt-smart可以运行opencv吗?
    发表于 08-04 16:40

    基于xmake的RT-Thread Smart用户态开发教程

    RT-Thread Smart(以下简称 Smart) 是基于 RT-Thread 操作系统上的混合操作系统,简称为 rt-smart,它把
    的头像 发表于 06-07 11:44 964次阅读
    基于xmake的<b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b>用户态开发教程

    RT-Thread BSP qemu-virt64-riscv的编译环境搭建

    的 gcc 交叉编译工具链了   在 rt-thread/bsp/qemu-virt64-riscv 目录下创建 一个设置环境变量的 shell 脚本,如 smart_env.sh   #!/bin
    发表于 05-16 10:37

    RT-Smart使用menuconfig配置后,rtconfig.h没有更新?

    开发环境:ubuntu20.04开发板:全志D1S系统:RT-Smart问题描述:我在使用menuconfig进行内核与驱动配置完成后,rtconfig.h内容没有更新?需要实现内容:当前在D1S
    发表于 05-12 15:05