以rt-smart在全志D1上的代碼為例,主要注釋了rt-smart在riscv64上的系統初始化和異常處理的代碼倉庫地址https://gitee.com/rtthread/rt-thread/tree/rt-smart
啟動
代碼路徑
/*
*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(idsizeof(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(idsizeof(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-Thread
+關注
關注
32文章
1613瀏覽量
44868
原文標題:RT-Smart riscv64匯編注釋
文章出處:【微信號:RTThread,微信公眾號:RTThread物聯網操作系統】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
熱點推薦
debian-202308 映像不支持 firmware-realtek 包 riscv64嗎?
我發現在 riscv64 架構的 debian-202308 映像中缺少為帶有 Realtek 芯片的 USB 集線器以太網端口提供驅動程序的 firmware-realtek 包。我發現
發表于 02-26 10:49
玄鐵K230 + RT-Smart + MicroPython:打造高實時性FOC云臺控制系統 | 技術集結
發送控制信號,再由其他單片機驅動無刷電機。并且玄鐵K230上的FOC控制算法是在RT-Smart(RT-Thread的分支)上實現,使用硬件定時器更新輸出力矩,比
【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
QEMU快速上手(Win),源碼文件夾對不上是為什么?
想要照著RTT文檔里的RT-Smart的QEMU快速上手 https://www.rt-thread.org/document/site/#/rt
發表于 09-29 06:57
求助,關于rt-smart用戶態線程實時性差的問題求解
我在樹莓派4B上使用v5.2.0 開啟smart的rt-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
【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邊緣計算領域帶來了一站式
RT-Smart riscv64匯編注釋
評論