網(wǎng)站網(wǎng)址怎么找電商運(yùn)營(yíng)培訓(xùn)班多少錢
前言
最近在對(duì)RISC-V架構(gòu)比較感興趣,正好手頭有《RISC-V體系結(jié)構(gòu)編程與實(shí)踐》的書籍,就打算跟隨笨叔將這塊的知識(shí)學(xué)習(xí)起來,最開始當(dāng)然是需要搭建一個(gè)基礎(chǔ)的實(shí)驗(yàn)平臺(tái),本來笨叔是貼心的提供了VMare的環(huán)境,奈何天生叛逆的我就不下他的大鏡像(我就不說我百度網(wǎng)盤沒會(huì)員),就拿手頭的wsl搭建了一套基于vscode的調(diào)試環(huán)境,可以直接一鍵調(diào)試,感覺還是蠻方便的。這里就進(jìn)行一下記錄。
參考連接:
優(yōu)雅的調(diào)試在vscode上完美調(diào)試xv6
笨叔RISC-V官方示例代碼倉庫
文章目錄
- 前言
- WSL基礎(chǔ)環(huán)境的安裝
- 環(huán)境搭建
- 1. 基礎(chǔ)軟件包安裝
- 2.示例源碼的下載
- 問題解決
- PMP未開啟導(dǎo)致無法進(jìn)入benos
- VScode調(diào)試問題
- 理解調(diào)試方法
- 配置lanuch.json
- 配置tasks.json
- 成果展示
- 小插曲
- .S文件不能打斷點(diǎn)
- 最后
WSL基礎(chǔ)環(huán)境的安裝
我曾經(jīng)寫過兩篇文章來完善這塊內(nèi)容,可以參考:
利用windows自帶的虛擬機(jī)安裝ubuntu的記錄用來完成基礎(chǔ)環(huán)境的安裝
[linux學(xué)習(xí)記錄]win下子系統(tǒng)ubuntu體驗(yàn)記錄用來記錄其中遇到的問題以及對(duì)應(yīng)的解決方案,會(huì)不定時(shí)更新
境搭建
1. 基礎(chǔ)軟件包安裝
QEMU Virt實(shí)驗(yàn)平臺(tái)模擬的是一款通用的RISC-V開發(fā)板。
軟件環(huán)境:
- WSL(ubuntu22.04)
- qemu(QEMU emulator version 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.15))
- riscv64-linux-gnu-gcc-9 (Ubuntu 9.5.0-1ubuntu1~22.04) 9.5.0
- gdb-multiarch(GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1)
安裝參考指令:
sudo apt install qemu-system-misc libncurses5-dev build-essential git bison flex libssl-dev
sudo apt install gcc-9-riscv64-linux-gnu
sudo ln -s /usr/bin/riscv64-linux-gnu-gcc-9 /usr/bin/riscv64-linux-gnu-gcc #切換默認(rèn)版本
sudo apt install gdb-multiarch
其他版本比較叛逆直接安裝,但是對(duì)于gcc的版本還是要慎重,之前編譯oe的5.10內(nèi)核的時(shí)候如果用過高的編譯器版本會(huì)導(dǎo)致鏈接出現(xiàn)問題,所以此處盡量與笨叔要求一致。
2.示例源碼的下載
git clone 笨叔RISC-V官方示例代碼倉庫
大致命令如下:
git clone https://github.com/runninglinuxkernel/riscv_programming_practice
cd riscv_programming_practice/chapter_2/benos
make
即可完成基礎(chǔ)命令的執(zhí)行。
運(yùn)行命令如下:
make debug
然后就會(huì)看到如下的畫面
這個(gè)其實(shí)是可以正常跑并且進(jìn)入到sbi內(nèi)了,只不過按照笨叔的說明文檔,我們遇到了PMP未開啟的問題導(dǎo)致無法進(jìn)入到benos內(nèi)。所以接下來我們有兩個(gè)問題待解決:
- 如何解決PMP問題
- 如何使用vscode進(jìn)行調(diào)試
問題解決
PMP未開啟導(dǎo)致無法進(jìn)入benos
根據(jù)笨叔的介紹:
那我們就以毒攻毒,把第十章的一部分代碼直接CV過來不就好了?雖然我看不懂但是CV我在行(不是),這塊其實(shí)就先解決問題,等到學(xué)到了再認(rèn)真研究就好了,初學(xué)者Hello個(gè)world還是有必要的。
根據(jù)我的觀察大概需要改4個(gè)文件:
//include/asm/csr.h
+/* Machine Memory Protection
+ * 暫時(shí)支持8個(gè)pmpcfg
+*/
+#define RISCV_XLEN 64
+#define MAX_CSR_PMP 8
+#define CSR_PMPCFG0 0x3a0
+#define CSR_PMPADDR0 0x3b0
+#define CSR_PMPADDR1 0x3b1
+#define CSR_PMPADDR2 0x3b2
+#define CSR_PMPADDR3 0x3b3
+#define CSR_PMPADDR4 0x3b4
+#define CSR_PMPADDR5 0x3b5
+#define CSR_PMPADDR6 0x3b6
+#define CSR_PMPADDR7 0x3b7
+#define PMP_R 0x01UL
+#define PMP_W 0x02UL
+#define PMP_X 0x04UL
+#define PMP_A 0x18UL
+#define PMP_A_TOR 0x08UL
+#define PMP_A_NA4 0x10UL
+#define PMP_A_NAPOT 0x18UL
+#define PMP_L 0x80UL
+#define PMP_RWX (PMP_R | PMP_W | PMP_X)
+#define PMP_SHIFT 2
+#ifdef __ASSEMBLY__
+#define __ASM_STR(x) x
+#else
+#define __ASM_STR(x) #x
+#endif
#define read_csr(csr) \({ \register unsigned long __v; \
- __asm__ __volatile__ ("csrr %0, " #csr \
+ __asm__ __volatile__ ("csrr %0, " __ASM_STR(csr) \: "=r" (__v) : \: "memory"); \__v; \#define write_csr(csr, val) \({ \unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrw " #csr ", %0" \
+ __asm__ __volatile__ ("csrw "__ASM_STR(csr)", %0" \: : "rK" (__v) \: "memory"); \})
上面其實(shí)是diff的部分輸出,就是在對(duì)應(yīng)文件進(jìn)行修改,+就是增加,-就是刪除,對(duì)照修改即可。
另外需要將第十章的sbi_lib.c
以及sbi_lib.h
拷貝到對(duì)應(yīng)目錄,以及對(duì)sbi_main.c進(jìn)行如下修改:
//sbi/sbi_main.c{unsigned long val;+ /*
+ * 配置PMP
+ * 所有地址空間都可以訪問
+ */
+ sbi_set_pmp(0, 0, -1UL, PMP_RWX);
+ sbi_set_pmp(1, 0x80000000, 0x40000, PMP_RWX);
其中sbi_set_pmp
函數(shù)也需要從第十章的sbi_main.c
內(nèi)拷貝而來。
如果嫌棄麻煩的話也可以訪問我的gitee分支: https://gitee.com/gaoxinglei/risc-v_practice
VScode調(diào)試問題
由于我是采用WSL的實(shí)驗(yàn)方式,VScode采用ssh遠(yuǎn)程連接,需要以下插件:
- Remote-SSH(Host用于連接WSL)
- C/C++(Ubuntu22.04 用于代碼高亮跳轉(zhuǎn)等)
理解調(diào)試方法
書上以及相關(guān)資料采用的其實(shí)是使用gdb-multiarch
選擇選擇對(duì)應(yīng)的elf進(jìn)行調(diào)試的,使用remote的方式ip+port的形式。一般的調(diào)試形式如下:
gdb-multiarch benos.elf
target remote localhost:1234
然后我們可以配置這些手動(dòng)的過程到launch.json
,并且觀察也更加方便。
配置lanuch.json
理解了上面的過程我們?cè)賮砜催@份lanuch.json就更加方便了
//launch.json
{"version": "0.2.0","configurations": [{"name": "riscvkernel","type": "cppdbg","request": "launch","program": "${fileDirname}/../benos.elf","args": [],"stopAtEntry": true,"cwd": "${workspaceFolder}","miDebuggerServerAddress": "127.0.0.1:1234","miDebuggerPath": "gdb-multiarch","environment": [],"externalConsole": false,"MIMode": "gdb","preLaunchTask": "riscvbuild","setupCommands": [{"description": "pretty printing","text": "-enable-pretty-printing","ignoreFailures": true,},],},]
}
其中的miDebuggerServerAddress
就是對(duì)應(yīng)我們qemu的地址,然后miDebuggerPath
來選擇我們的gdb工具。program
對(duì)應(yīng)我們的命令后接的要調(diào)試的程序,我們這里選擇benos.elf
,如果需要調(diào)試書籍里面的sbi
也可以換成對(duì)應(yīng)的文件,再建一個(gè)調(diào)試即可,具體參考我的gitee。這里我發(fā)現(xiàn)參考代碼都是源碼上一級(jí)就是Makefile,所以我可以簡(jiǎn)單的寫成../benos.elf
這種形式,其他的可能需要思考更合理的判斷方式。但注意到我們其實(shí)還有一個(gè)preLaunchTask
預(yù)處理,這塊就是幫助我們敲make解放雙手。
配置tasks.json
上面說到的preLaunchTask
,其實(shí)就是在這里進(jìn)行定義的,具體內(nèi)容如下:
// tasks.json
{"version": "2.0.0","tasks": [{"label": "riscvbuild","type": "shell","isBackground": true,"command": "cd ${fileDirname}/..;make;make debug","problemMatcher": [{"pattern": [{"regexp": ".","file": 1,"location": 2,"message": 3}],"background": {"beginsPattern": ".*-kernel benos.elf -S -s","endsPattern": "."}}]}]
}
主要注意label要和launch.json文件進(jìn)行對(duì)應(yīng),command就是編譯指令,我們這里也是因?yàn)槟夸泴蛹?jí)簡(jiǎn)單可以這么簡(jiǎn)單書寫。
beginsPattern
是屏幕識(shí)別到相關(guān)代碼才開始調(diào)試,否則認(rèn)為編譯失敗,類似于下圖:
就是未識(shí)別到對(duì)應(yīng)信息,我們這里采用Makefile會(huì)輸出的一句話即可
成果展示
經(jīng)過上面的配置,我們就可以對(duì)遠(yuǎn)程gdb進(jìn)行調(diào)試了,也符合我們?nèi)粘5氖褂昧?xí)慣。
小插曲
這個(gè)地方不定時(shí)更新遇到的問題
.S文件不能打斷點(diǎn)
需要打開這個(gè)設(shè)置,注意打開的是WSL的設(shè)置而不是本地設(shè)置哦。
最后
相關(guān)源碼可以在 https://gitee.com/gaoxinglei/risc-v_practice進(jìn)行獲取哦