色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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匯編注釋

冬至子 ? 來源:HAHABO ? 作者:HAHABO ? 2023-10-12 17:26 ? 次閱讀

以rt-smart在全志D1上的代碼為例,主要注釋了rt-smart在riscv64上的系統(tǒng)初始化和異常處理的代碼

啟動(dòng)

代碼路徑

libcpurisc-vt-headc906startup_gcc.S

/*

Copyright (c) 2006-2018, RT-Thread Development Team

SPDX-License-Identifier: Apache-2.0

Change Logs:
Date Author Notes
2018/10/01 Bernard The first version
2018/12/27 Jesven Add SMP support
2020/6/12 Xim Port to QEMU and remove SMP support
/
#define ASSEMBLY
#define SSTATUS_FS 0x00006000U /
initial state of FPU, clear to disable /
#include
.global _start
.section ".start", "ax"
_start:
j 1f
.word 0xdeadbeef
.align 3
.global g_wake_up
g_wake_up:
.dword 1
.dword 0
1:
csrw sie, 0 / 超級(jí)用戶模式中斷使能關(guān)閉 /
csrw sip, 0 / 超級(jí)用戶模式中斷等待關(guān)閉 /
la t0, trap_entry / 將trap_entry的地址放入t0寄存器 /
csrw stvec, t0 / 配置異常服務(wù)程序的入口地址 /
li x1, 0
/
.........../ / 初始化通用寄存器 /
li x31,0
/
set to disable FPU */
li t0, SSTATUS_FS / 將FS的bit位寫入t0寄存器 /
csrc sstatus, t0 / 清除sstatus中的FS bit,關(guān)閉浮點(diǎn)單元 /
li t0, 0x40000 / 當(dāng) SUM=1 時(shí),超級(jí)用戶模式下,加載、存儲(chǔ)和取指令請(qǐng)求可以訪問標(biāo)記為用戶態(tài)的虛擬內(nèi)存空間 /
csrs sstatus, t0 / 置位sstatus中的SUM位 /
.option push
.option norelax
la gp, __global_pointer$
.option pop
// removed SMP support here
la sp, stack_start / 棧指針的值來自于鏈接腳本中的__stack_start /
li t0, STACKSIZE
add sp, sp, t0 / 棧自上到下增長(zhǎng) /
csrw sscratch, sp /*sscratch存儲(chǔ)棧頂?shù)牡刂?*/
j primary_cpu_entry / 跳轉(zhuǎn)到board中的C程序入口 /
//BSP的C入口
void primary_cpu_entry(void)
{
extern void entry(void);
//初始化BSS
init_bss();
//關(guān)中斷
rt_hw_interrupt_disable();
rt_assert_set_hook(__rt_assert_handler);
//啟動(dòng)RT-Thread Smart內(nèi)核
entry();
}

異常處理

異常處理流程圖

1.jpg

異常處理上半部分

/ libcpurisc-vt-headc906interrupt_gcc.S /
#define ASSEMBLY
#include "cpuport.h"
#include "encoding.h"
#include "stackframe.h"
.section .text.entry
.align 2
.global trap_entry
.extern __stack_cpu0
.extern get_current_thread_kernel_stack_top
trap_entry: / 異常處理函數(shù)的入口 /
//backup sp
csrrw sp, sscratch, sp / 將當(dāng)前棧與sscratch做交換 /
//load interrupt stack
la sp, __stack_cpu0 / sp指向cpu0的中斷棧的棧頂 /
//backup context
SAVE_ALL / CPU寄存器入棧,使能浮點(diǎn)的情況下浮點(diǎn)相關(guān)的寄存器也要入棧 并且要保存sstatus中浮點(diǎn)的運(yùn)算狀態(tài) /
RESTORE_SYS_GP / gp操作不用了解 /
//check syscall
csrr t0, scause / 讀取scaue到t0 /
li t1, 8 //environment call from u-mode / 用戶模式環(huán)境調(diào)用異常 /
beq t0, t1, syscall_entry / 如果是系統(tǒng)調(diào)用則跳轉(zhuǎn)到系統(tǒng)調(diào)用處理函數(shù),這個(gè)函數(shù)最終會(huì)調(diào)用sret /
csrr a0, scause / 讀取scause到a0,機(jī)器模式異常事件向量寄存器(MCAUSE)用于保存觸發(fā)異常的異常事件向量號(hào),用于在異常服務(wù)程序中處理對(duì)應(yīng)事件 /
csrrc a1, stval, zero / 讀取stval到a1,發(fā)生異常或者中斷,且在機(jī)器模式響應(yīng)時(shí),處理器會(huì)更新 pc 到 MEPC,并根據(jù)異常類型更新 MTVAL /
csrr a2, sepc / 讀取sepc到a2, 超級(jí)用戶模式異常保留程序計(jì)數(shù)器(SEPC)用于存儲(chǔ)程序從異常服務(wù)程序退出時(shí)的程序計(jì)數(shù)器值(即
PC 值)
/
mv a3, sp / 讀取sp的值到a3 /
/* scause, stval, sepc, sp /
call handle_trap / 進(jìn)行中斷處理 /
中斷處理
/ libcpurisc-vt-headc906trap.c /
/
Trap entry /
void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_stack_frame sp)
{
/

SCAUSE
bit63 Interrupt-中斷標(biāo)記位
當(dāng) Interrupt 位為 0 時(shí),表示觸發(fā)異常的來源不是中斷, Exception Code 按照異常解析。當(dāng) Interrupt 位為 1 時(shí),表示觸發(fā)異常的來源是中斷, Exception Code 按照中斷解析。該位會(huì)被 reset 置為 1’ b0。
bit04 Exception Code-異常向量號(hào)位
在處理器響應(yīng)異常或中斷時(shí),該域會(huì)被更新為對(duì)應(yīng)異常號(hào),具體請(qǐng)參考 表 3.9 異常和中斷向量分
配。該位會(huì)被 reset 置為 5’ b0。
*/
/ 我理解這里是想獲取Exception Code,但是Exception Code是bit0 ~ bit4,這里用__MASK(5UL)更合適吧 /
rt_size_t id = __MASKVALUE(scause,__MASK(63UL));
const char msg;
/
supervisor external interrupt */
/*如果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í)器中斷 /
else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause)
{
/* supervisor timer /
rt_interrupt_enter();
tick_isr();
rt_interrupt_leave();
return;
} / 其他中斷 /
else if (SCAUSE_INTERRUPT & scause)
{
if(id < sizeof(Interrupt_Name) / sizeof(const char ))
{
msg = Interrupt_Name[id];
}
else
{
msg = "Unknown Interrupt";
}
LOG_E("Unhandled Interrupt %ld:%sn",id,msg);
}
else / 異常處理 /
{
#ifdef RT_USING_USERSPACE
/
page fault 缺頁異常處理
/
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(id < sizeof(Exception_Name) / sizeof(const char *))
{
msg = Exception_Name[id];
}
else
{
msg = "Unknown Exception";
}
rt_kprintf("Unhandled Exception %ld:%sn",id,msg);
}
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%pn",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ù)中完成。

異常處理下半部分

/* need to switch new thread 查詢線程切換的flag是否被置位為1*/
la s0, rt_thread_switch_interrupt_flag / 讀取rt_thread_switch_interrupt_flag /
lw s2, 0(s0)
beqz s2, spurious_interrupt / rt_thread_switch_interrupt_flag如果為0那么直接跳轉(zhuǎn)到spurious_interrupt進(jìn)行寄存器恢復(fù),并調(diào)用sret回到異常之前的狀態(tài) /
sw zero, 0(s0) / rt_thread_switch_interrupt_flag = 0 /
.global rt_hw_context_switch_interrupt_do
rt_hw_context_switch_interrupt_do:
//swap to thread kernel stack
csrr t0, sstatus / 讀取sstatus到t0 /
andi t0, 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。
/
beqz t0, __restore_sp_from_tcb_interrupt / 如果是內(nèi)核態(tài)發(fā)生異常 /
__restore_sp_from_sscratch_interrupt:
csrr t0, sscratch / 獲取發(fā)生異常時(shí)的上下文數(shù)據(jù) /
j __move_stack_context_interrupt / 如果是用戶態(tài)發(fā)生異常 /
/ 獲取當(dāng)前線程的棧頂位置存到t0中 /
__restore_sp_from_tcb_interrupt:
la s0, rt_interrupt_from_thread
LOAD a0, 0(s0)
jal rt_thread_sp_to_thread
jal get_thread_kernel_stack_top
mv t0, a0
__move_stack_context_interrupt:
mv t1, sp//src / 當(dāng)前棧,當(dāng)前棧存儲(chǔ)的是發(fā)生異常時(shí)的通用寄存器信息 /
mv sp, t0//switch stack /
將發(fā)生異常時(shí)的棧的值寫回到sp寄存器 */
addi sp, sp, -CTX_REG_NR * REGBYTES / 棧指針向下移動(dòng)CTX_REG_NR * REGBYTES /
//copy context
li s0, CTX_REG_NR//cnt / 需要恢復(fù)的寄存器的個(gè)數(shù)加載到s0 /
mv t2, sp//dst / 棧指針加載到t2 /
/ 總結(jié)就是,當(dāng)前CPU的中斷棧存儲(chǔ)了當(dāng)前線程的通用寄存器的信息,如果發(fā)生任務(wù)切換,需要把這些信息拷貝到線程的棧里 /
copy_context_loop_interrupt:
LOAD t0, 0(t1) / t1的值放到t0 /
STORE t0, 0(t2) / t0的值放到t2 /
addi s0, s0, -1 / 要恢復(fù)的寄存器個(gè)數(shù)-1 /
addi t1, t1, 8 / t1的地址加8 /
addi t2, t2, 8 / t2的地址加8 /
bnez s0, copy_context_loop_interrupt / 如果s0不為0就重復(fù)拷貝 /
la s0, rt_interrupt_from_thread
LOAD s1, 0(s0)
STORE sp, 0(s1) / 更新from線程的sp指針 /
la s0, rt_interrupt_to_thread
LOAD s1, 0(s0)
LOAD sp, 0(s1) / 恢復(fù)to線程的sp /
#ifdef RT_USING_USERSPACE
mv a0, s1
jal rt_thread_sp_to_thread
jal lwp_mmu_switch / 切換mmu,函數(shù)內(nèi)部會(huì)判斷from線程和to線程是不是在同一個(gè)lwp中,不是的話就會(huì)切換MMU /
#endif
spurious_interrupt:
RESTORE_ALL / 恢復(fù)寄存器 /
sret / 超級(jí)用戶模式異常返回指令 /

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

    關(guān)注

    31

    文章

    5336

    瀏覽量

    120230
  • 中斷處理
    +關(guān)注

    關(guān)注

    0

    文章

    94

    瀏覽量

    10967
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1285

    瀏覽量

    40085
  • RISC-V
    +關(guān)注

    關(guān)注

    45

    文章

    2270

    瀏覽量

    46129
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Smart的資料合集

    1、RT-Smart的啟動(dòng)過程在熟悉 RT-Smart 架構(gòu)的過程中,研究其啟動(dòng)過程的是必不可少的,那么在系統(tǒng)正常運(yùn)行之前,需要做哪些準(zhǔn)備工作呢。本文將以 32 位 RT-Smart 的源代碼為
    發(fā)表于 03-22 15:06

    請(qǐng)問rt-smart支持64位的編譯嘛?

    我看入門指南上寫目前rt-smart僅支持32位的系統(tǒng),所以有辦法編譯成64位嗎?
    發(fā)表于 04-15 09:47

    D1哪吒開發(fā)板rt-smart內(nèi)核固件的燒寫與運(yùn)行步驟

    前BSP需要簡(jiǎn)單的修改才能保證編譯通過,這里注意講解 rt-smart 內(nèi)核固件的燒寫與運(yùn)行搭建d1-allwinner-nezha 的 rt-smart 最小系統(tǒng)后,在ubuntu RISCV64
    發(fā)表于 06-17 11:06

    如何在RT-Thread Smart下使用gcc交叉編譯工具鏈呢

    前言RT-Thread Smart的BSP rt-smartspd1-allwinner-nezha,也全志D1s的哪吒開發(fā)板,基于RISCV64平臺(tái),需要CV
    發(fā)表于 06-17 11:13

    在虛擬機(jī)Ubuntu18.04中配置RT-Smart RISC-V64報(bào)unknown arch錯(cuò)誤?

    嘗試在linux中進(jìn)行RT-Smart開發(fā),在tools目錄下運(yùn)行完配置腳本后,在userapps目錄下運(yùn)行smart-env.sh時(shí)發(fā)現(xiàn)參數(shù)為riscv64一直報(bào)unknown arch但是參數(shù)為arm時(shí)則正常,向大佬們求助。
    發(fā)表于 02-10 14:05

    RT-Smartriscv64上的系統(tǒng)初始化和異常處理的代碼注釋

    RT-Smart riscv64匯編注釋rt-smart在全志D1上的代碼為例,主要注釋
    發(fā)表于 02-10 16:43

    rt-smartriscv64上的系統(tǒng)初始化和異常處理的代碼注釋

    rt-smart在全志D1上的代碼為例,主要注釋rt-smartriscv64上的系統(tǒng)初始化和異常處理的代碼啟動(dòng)代碼路徑libcpu\\risc-v\\t-head\\c906
    發(fā)表于 02-15 11:04

    怎么解決rt-smart在適配riscv64虛擬地址和物理地址映射問題?

    )--------------Backtrace--------------riscv64-unknown-linux-musl-addr2line -e rtthread.elf -a -f 00000000500248b0目前關(guān)于RT-SMART的資料較少,官網(wǎng)文檔中
    發(fā)表于 03-16 11:29

    riscv64裸機(jī)編程實(shí)踐與分析

    在啟動(dòng)之前都需要有一段匯編代碼,從這段匯編代碼上就可以體現(xiàn)一些架構(gòu)設(shè)計(jì)的特點(diǎn)。往往做嵌入式底層開發(fā)都需要關(guān)注這段匯編代碼的含義,這樣在使用的時(shí)候才能全面的了解啟動(dòng)時(shí)做了什么事情,在后續(xù)的程序中遇到問題也能復(fù)盤推演。 本文就針對(duì)
    的頭像 發(fā)表于 12-31 10:54 ?4483次閱讀
    <b class='flag-5'>riscv64</b>裸機(jī)編程實(shí)踐與分析

    樹莓派上rt-smart的應(yīng)用編程入門

    我們從現(xiàn)在開始會(huì)逐步連載RT-Thread Smart(簡(jiǎn)稱rt-smart,甚至有時(shí)會(huì)稱為smart os)的介紹文章,旨在讓大家認(rèn)識(shí),接觸到sm
    的頭像 發(fā)表于 05-13 14:10 ?3159次閱讀
    樹莓派上<b class='flag-5'>rt-smart</b>的應(yīng)用編程入門

    第一屆RISC-V中國(guó)峰會(huì)最新內(nèi)容:RV64上的微內(nèi)核操作系統(tǒng)rt-smart介紹

    RT-Thread自開始就在推進(jìn)對(duì)RISCV架構(gòu)的支持,同時(shí)也包括社區(qū)、態(tài)合作伙伴在RISCV方面的貢獻(xiàn)。本文主要對(duì)RV64上的微內(nèi)核操作系統(tǒng)rt-
    的頭像 發(fā)表于 06-23 11:49 ?2451次閱讀
    第一屆RISC-V中國(guó)峰會(huì)最新內(nèi)容:RV<b class='flag-5'>64</b>上的微內(nèi)核操作系統(tǒng)<b class='flag-5'>rt-smart</b>介紹

    rt-smart移植分析:從樹莓派3b入手

    移植rt-smart到最新的板子上具體需要注意哪些細(xì)節(jié),哪些才是移植rt-smart的關(guān)鍵點(diǎn)?本文從樹莓派3b上移植rt-smart的角度,從頭分析rt-sm...
    發(fā)表于 01-25 18:48 ?0次下載
    <b class='flag-5'>rt-smart</b>移植分析:從樹莓派3b入手

    絲滑的在RT-Smart用戶態(tài)運(yùn)行LVGL

    開發(fā)流程 1、RT-Smart 環(huán)境搭建 下載 RT-Smart 用戶態(tài)應(yīng)用代碼: 1 git?clone?https: //github.com/RT-Thread/userapps.git
    的頭像 發(fā)表于 11-22 20:20 ?1260次閱讀

    RT-Smart riscv64匯編注釋

    rt-smart在全志D1上的代碼為例,主要注釋rt-smartriscv64上的系統(tǒng)初始化和異常處理的代碼倉庫地址https://gitee.com/rtthread/
    的頭像 發(fā)表于 02-08 21:40 ?1149次閱讀

    riscvrt-smart中的板級(jí)初始化

    本文章的代碼來自于rt-smart中針對(duì)qemu-virt-riscv的bsp 倉庫地址 https://gitee.com/rtthread/rt-thread/tree/rt-smart
    的頭像 發(fā)表于 02-09 17:45 ?957次閱讀
    主站蜘蛛池模板: babesvideos性欧美| 性xxx在线观看| 日韩综合网| 56prom在线精品国产| 好大太快了快插穿子宫了| 婷婷久久无码欧美人妻| 99久久蜜臀亚洲AV无码精品| 狼群资源网中文字幕| 亚洲乱码国产一区三区| 国精产品一区一区三区有限在线 | 秋霞电影午夜伦午夜| 91久久99久91天天拍拍| 久久成人午夜电影mp4| 亚洲中久无码永久在线| 好男人的视频在线观看| 亚洲精品国产一区二区贰佰信息网| 国产免费高清mv视频在线观看| 色人阁综合| 国产精品嫩草影院| 吸奶舔下面| 狠狠干福利视频| 亚洲日产2020乱码草莓毕| 久久 这里只精品 免费| 中文字幕久久久| 嫩草欧美曰韩国产大片| a三级黄色片| 日产精品高潮呻吟AV久久| 国产99在线视频| 亚洲 欧美 制服 视频二区| 好爽胸大好深好多水| 一区视频免费观看| 美女内射少妇一区二区四区| 99影视久久电影网久久看影院| 泡妞高手在都市免费观看| 顶级少妇AAAAABBBBB片| 午夜dj免费中文字幕| 好男人WWW免费高清视频在线| 正在播放国产精品| 啪啪激情婷婷久久婷婷色五月| 囯产免费久久久久久国产免费| 亚洲不卡视频在线|