0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

RT-Smart riscv64匯編注釋

RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 來源:未知 ? 2023-02-08 21:40 ? 次閱讀

以rt-smart在全志D1上的代碼為例,主要注釋了rt-smart在riscv64上的系統(tǒng)初始化和異常處理的代碼倉庫地址https://gitee.com/rtthread/rt-thread/tree/rt-smart

啟動(dòng)

代碼路徑

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/*超級(jí)用戶模式中斷使能關(guān)閉*/
csrwsip,0/*超級(jí)用戶模式中斷等待關(guān)閉*/
lat0,trap_entry/*將trap_entry的地址放入t0寄存器*/
csrwstvec,t0/*配置異常服務(wù)程序的入口地址*/

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

/*settodisableFPU*/
lit0,SSTATUS_FS/*將FS的bit位寫入t0寄存器*/
csrcsstatus,t0/*清除sstatus中的FSbit,關(guān)閉浮點(diǎn)單元*/
lit0,0x40000/*當(dāng)SUM=1時(shí),超級(jí)用戶模式下,加載、存儲(chǔ)和取指令請(qǐng)求可以訪問標(biāo)記為用戶態(tài)的虛擬內(nèi)存空間*/
csrssstatus,t0/*置位sstatus中的SUM位*/

.optionpush
.optionnorelax
lagp,__global_pointer$
.optionpop

//removedSMPsupporthere
lasp,__stack_start__/*棧指針的值來自于鏈接腳本中的__stack_start*/
lit0,__STACKSIZE__
addsp,sp,t0/*棧自上到下增長*/
csrwsscratch,sp/*sscratch存儲(chǔ)棧頂?shù)牡刂?/
jprimary_cpu_entry/*跳轉(zhuǎn)到board中的C程序入口*/
//BSP的C入口
voidprimary_cpu_entry(void)
{
externvoidentry(void);

//初始化BSS
init_bss();
//關(guān)中斷
rt_hw_interrupt_disable();
rt_assert_set_hook(__rt_assert_handler);
//啟動(dòng)RT-ThreadSmart內(nèi)核
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:/*異常處理函數(shù)的入口*/
//backupsp
csrrwsp,sscratch,sp/*將當(dāng)前棧與sscratch做交換*/
//loadinterruptstack
lasp,__stack_cpu0/*sp指向cpu0的中斷棧的棧頂*/
//backupcontext
SAVE_ALL/*CPU寄存器入棧,使能浮點(diǎn)的情況下浮點(diǎn)相關(guān)的寄存器也要入棧并且要保存sstatus中浮點(diǎn)的運(yùn)算狀態(tài)*/

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

//checksyscall
csrrt0,scause/*讀取scaue到t0*/
lit1,8//environmentcallfromu-mode/*用戶模式環(huán)境調(diào)用異常*/
beqt0,t1,syscall_entry/*如果是系統(tǒng)調(diào)用則跳轉(zhuǎn)到系統(tǒng)調(diào)用處理函數(shù),這個(gè)函數(shù)最終會(huì)調(diào)用sret*/

csrra0,scause/*讀取scause到a0,機(jī)器模式異常事件向量寄存器(MCAUSE)用于保存觸發(fā)異常的異常事件向量號(hào),用于在異常服務(wù)程序中處理對(duì)應(yīng)事件*/
csrrca1,stval,zero/*讀取stval到a1,發(fā)生異?;蛘咧袛?,且在機(jī)器模式響應(yīng)時(shí),處理器會(huì)更新pc到MEPC,并根據(jù)異常類型更新MTVAL*/
csrra2,sepc/*讀取sepc到a2,超級(jí)用戶模式異常保留程序計(jì)數(shù)器(SEPC)用于存儲(chǔ)程序從異常服務(wù)程序退出時(shí)的程序計(jì)數(shù)器值(即
PC值)*/

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

/*scause,stval,sepc,sp*/
callhandle_trap/*進(jìn)行中斷處理*/

中斷處理

/*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-中斷標(biāo)記位
當(dāng) Interrupt 位為0時(shí),表示觸發(fā)異常的來源不是中斷, Exception Code 按照異常解析。當(dāng) Interrupt 位為 1 時(shí),表示觸發(fā)異常的來源是中斷, Exception Code 按照中斷解析。該位會(huì)被 reset 置為 1’ b0。
bit0~4ExceptionCode-異常向量號(hào)位
在處理器響應(yīng)異?;蛑袛鄷r(shí),該域會(huì)被更新為對(duì)應(yīng)異常號(hào),具體請(qǐng)參考表3.9異常和中斷向量分
配。該位會(huì)被 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超級(jí)用戶模式外部中斷*/
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是超級(jí)用戶模式計(jì)時(shí)器中斷*/
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/*其他異常處理,走到這里后打印一些必要信息,最終會(huì)走到while(1),進(jìn)入死循環(huán)*/
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中任務(wù)切換有三個(gè)相關(guān)的線程函數(shù)

  • rt_hw_context_switch_to():沒有來源線程,切換到目標(biāo)線程,在調(diào)度器啟動(dòng)第一個(gè)線程的時(shí)候 被調(diào)用
  • rt_hw_context_switch():在線程環(huán)境下,從當(dāng)前線程切換到目標(biāo)線程
  • rt_hw_context_switch_interrupt ():在中斷環(huán)境下,從當(dāng)前線程切換到目標(biāo)線程。

rt_hw_context_switch_interrupt ()會(huì)將rt_thread_switch_interrupt_flag置為1,真正的線程切換動(dòng)作在異常處理函數(shù)中完成。

異常處理下半部分

/*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那么直接跳轉(zhuǎn)到spurious_interrupt進(jìn)行寄存器恢復(fù),并調(diào)用sret回到異常之前的狀態(tài)*/
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超級(jí)用戶模式保留特權(quán)狀態(tài)位*/
/*
該位用于保存處理器在降級(jí)到超級(jí)用戶模式進(jìn)入異常服務(wù)程序前的特權(quán)狀態(tài)。
?當(dāng) SPP 為 2’ b00時(shí),表示處理器進(jìn)入異常服務(wù)程序前處于用戶模式;
?當(dāng) SPP 為 2’ b01 時(shí),表示處理器進(jìn)入異常服務(wù)程序前處于超級(jí)用戶模式;
該位會(huì)被 reset 置 2’ b01。
*/

beqzt0,__restore_sp_from_tcb_interrupt/*如果是內(nèi)核態(tài)發(fā)生異常*/

__restore_sp_from_sscratch_interrupt:
csrrt0,sscratch/*獲取發(fā)生異常時(shí)的上下文數(shù)據(jù)*/
j__move_stack_context_interrupt/*如果是用戶態(tài)發(fā)生異常*/

/*獲取當(dāng)前線程的棧頂位置存到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/*當(dāng)前棧,當(dāng)前棧存儲(chǔ)的是發(fā)生異常時(shí)的通用寄存器信息*/
mvsp,t0//switchstack/*將發(fā)生異常時(shí)的棧的值寫回到sp寄存器*/
addisp,sp,-CTX_REG_NR*REGBYTES/*棧指針向下移動(dòng)CTX_REG_NR*REGBYTES*/
//copycontext
lis0,CTX_REG_NR//cnt/*需要恢復(fù)的寄存器的個(gè)數(shù)加載到s0*/
mvt2,sp//dst/*棧指針加載到t2*/
/*總結(jié)就是,當(dāng)前CPU的中斷棧存儲(chǔ)了當(dāng)前線程的通用寄存器的信息,如果發(fā)生任務(wù)切換,需要把這些信息拷貝到線程的棧里*/

copy_context_loop_interrupt:
LOADt0,0(t1)/*t1的值放到t0*/
STOREt0,0(t2)/*t0的值放到t2*/
addis0,s0,-1/*要恢復(fù)的寄存器個(gè)數(shù)-1*/
addit1,t1,8/*t1的地址加8*/
addit2,t2,8/*t2的地址加8*/
bnezs0,copy_context_loop_interrupt/*如果s0不為0就重復(fù)拷貝*/

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

las0,rt_interrupt_to_thread
LOADs1,0(s0)
LOADsp,0(s1)/*恢復(fù)to線程的sp*/

#ifdefRT_USING_USERSPACE
mva0,s1
jalrt_thread_sp_to_thread
jallwp_mmu_switch/*切換mmu,函數(shù)內(nèi)部會(huì)判斷from線程和to線程是不是在同一個(gè)lwp中,不是的話就會(huì)切換MMU*/
#endif

spurious_interrupt:
RESTORE_ALL/*恢復(fù)寄存器*/
sret/*超級(jí)用戶模式異常返回指令*/

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


你可以添加微信:rtthread2020 為好友,注明:公司+姓名,拉進(jìn)RT-Thread官方微信交流群!



愛我就給我點(diǎn)在看

點(diǎn)擊閱讀原文


原文標(biāo)題:RT-Smart riscv64匯編注釋

文章出處:【微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1239

    瀏覽量

    39437

原文標(biāo)題:RT-Smart riscv64匯編注釋

文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RK3568平臺(tái)RT-smart系統(tǒng)跑不起來,為什么?

    RK3568平臺(tái)RT-smart系統(tǒng)跑不起來
    發(fā)表于 09-13 07:28

    在ubuntu 24.04下嘗試使用riscv64-linux-musleabi_for_x86_64-pc-linux-gnu工具鏈編譯cv1800大核出現(xiàn)報(bào)錯(cuò)的原因?

    在ubuntu 24.04下嘗試使用riscv64-linux-musleabi_for_x86_64-pc-linux-gnu工具鏈編譯cv1800大核,結(jié)果出現(xiàn)如下報(bào)錯(cuò): /home
    發(fā)表于 07-16 08:20

    谷歌安卓系統(tǒng)即將取消對(duì)RISC-V架構(gòu)的支持

    負(fù)責(zé)安卓Linux核心分支開發(fā)的谷歌高級(jí)工程師向AOSP提交了一系列補(bǔ)丁,其中顯示“已去除ACK對(duì)riscv64的支持”。這些補(bǔ)丁詳細(xì)描述指出“對(duì)risc64 GKI內(nèi)核的支持已停止”。
    的頭像 發(fā)表于 04-30 15:40 ?1304次閱讀

    rtthread d1s編譯報(bào)錯(cuò)的原因是什么?如何處理?

    我使用使用的是現(xiàn)在git上的rtthread的最新的master分支,因?yàn)?b class='flag-5'>rt-smart已經(jīng)并入主線,所以我想在windows下用env工具編譯。 因?yàn)橐幾griscv架構(gòu)的全志D1S,我下載了
    發(fā)表于 02-22 06:43

    ART Pi Smart基于RT-Thread Smart系統(tǒng)的LVGL移植

    ART-Pi Smart開發(fā)板為RT-Thread聯(lián)合百問科技出品,使用的是 NXP 公司的 i.MX6ULL 處理器,具備單核 ARM Cortex-A7,最高運(yùn)行頻率可以達(dá)到 800MHz。
    的頭像 發(fā)表于 11-29 14:29 ?968次閱讀
    ART Pi <b class='flag-5'>Smart</b>基于<b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b>系統(tǒng)的LVGL移植

    RT-Smart開發(fā)筆記:int類型數(shù)值溢出造成的奇怪問題的分析與排查記錄

    最近在調(diào)試 RT-Smart 上的用戶態(tài) mq(消息隊(duì)列)時(shí),遇到一個(gè)奇怪的問題,這個(gè)例程打印了一下獲取的時(shí)間,就可以正常的工作(超時(shí)退出),否則,就一直卡?。o法超時(shí))
    的頭像 發(fā)表于 10-31 16:16 ?626次閱讀
    <b class='flag-5'>RT-Smart</b>開發(fā)筆記:int類型數(shù)值溢出造成的奇怪問題的分析與排查記錄

    RT-Smart應(yīng)用開發(fā)筆記:fopen造成文件被清空問題的分析記錄

    RT-Smart 應(yīng)用(apps)開發(fā)環(huán)境,ubuntu 20.04 + win10 VS Code
    的頭像 發(fā)表于 10-20 16:01 ?467次閱讀
    <b class='flag-5'>RT-Smart</b>應(yīng)用開發(fā)筆記:fopen造成文件被清空問題的分析記錄

    RT-Smart riscv64匯編注釋

    rt-smart在全志D1上的代碼為例,主要注釋rt-smartriscv64上的系統(tǒng)初始化和異常處理的代碼
    的頭像 發(fā)表于 10-12 17:26 ?507次閱讀
    <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板是一個(gè)不對(duì)應(yīng)于任何真實(shí)硬件的平臺(tái);它是為虛擬機(jī)設(shè)計(jì)的。如果你只是想運(yùn)行Linux等客戶機(jī),而不關(guān)心重現(xiàn)真實(shí)世界硬件的特殊性和局限性,那么它是推薦的板卡類型。
    的頭像 發(fā)表于 10-12 14:15 ?1438次閱讀
    <b class='flag-5'>Rt-Smart</b>在<b class='flag-5'>riscv</b>中的初始化流程

    RT-Thread BSP qemu-virt64-aarch64文件系統(tǒng)

    前面大體上搭建了 RT-Thread BSP qemu-virt64-aarch64 的交叉編譯環(huán)境,運(yùn)行后發(fā)現(xiàn),文件系統(tǒng)沒有掛載上,感覺是沒有 mkfs。
    的頭像 發(fā)表于 10-08 16:34 ?781次閱讀
    <b class='flag-5'>RT</b>-Thread BSP qemu-virt<b class='flag-5'>64-aarch64</b>文件系統(tǒng)

    RT-Thread BSP qemu-virt64-riscv的編譯環(huán)境搭建步驟

    最近需要使用 RT-Thread smart 開發(fā)調(diào)試一些軟件功能,由于軟件功能平臺(tái)無關(guān),使用實(shí)際硬件操作,會(huì)耗費(fèi)較多的時(shí)間在程序燒寫環(huán)節(jié)。
    的頭像 發(fā)表于 10-08 15:41 ?1415次閱讀
    <b class='flag-5'>RT</b>-Thread BSP qemu-virt<b class='flag-5'>64-riscv</b>的編譯環(huán)境搭建步驟

    RT-Thread Smart qemu-virt64-riscv用戶態(tài)userapps的編譯與運(yùn)行

    rt-smart 上,為了實(shí)現(xiàn)用戶態(tài)與內(nèi)核態(tài)的分離,使用了【系統(tǒng)調(diào)用】,這個(gè)系統(tǒng)調(diào)用可以認(rèn)為是個(gè) sdk
    的頭像 發(fā)表于 10-08 15:33 ?800次閱讀
    <b class='flag-5'>RT</b>-Thread <b class='flag-5'>Smart</b> qemu-virt<b class='flag-5'>64-riscv</b>用戶態(tài)userapps的編譯與運(yùn)行

    swagger和smart-doc的區(qū)別

    ? smart-doc簡介 今天了不起給大家推薦一個(gè)技術(shù):smart-doc,看名字就知道,它是 智能-文檔。直接分析代碼,根據(jù)代碼含義生成文檔(開個(gè)玩笑,它還沒有那么智能);其實(shí)它是利用的注釋,來生成文檔,還是需要寫
    的頭像 發(fā)表于 09-30 16:08 ?915次閱讀
    swagger和<b class='flag-5'>smart</b>-doc的區(qū)別

    swagger和smart-doc的區(qū)別

    ? smart-doc簡介 今天了不起給大家推薦一個(gè)技術(shù):smart-doc,看名字就知道,它是 智能-文檔。直接分析代碼,根據(jù)代碼含義生成文檔(開個(gè)玩笑,它還沒有那么智能);其實(shí)它是利用的注釋,來生成文檔,還是需要寫
    的頭像 發(fā)表于 09-30 10:01 ?430次閱讀
    swagger和<b class='flag-5'>smart</b>-doc的區(qū)別

    搭建D1s RT-Smart開發(fā)環(huán)境踩坑筆記

    作為一個(gè)linux新手想要嘗試RT-Smart的開發(fā),但是網(wǎng)上教程前輩們的linux環(huán)境都是已經(jīng)相對(duì)完備的,因此像我這樣新手在搭建環(huán)境時(shí)常常缺這缺那的導(dǎo)致報(bào)錯(cuò),經(jīng)過一段時(shí)間的踩坑終于搞定了,因此和大家分享我遇到的坑和解決方法。
    的頭像 發(fā)表于 09-28 16:26 ?689次閱讀
    搭建D1s <b class='flag-5'>RT-Smart</b>開發(fā)環(huán)境踩坑筆記