關于d1哪吒開發板的啟動流程分析
1.本文概述
2.D1上電后啟動的第一個程序
3.啟動SPL
4.啟動opensbi
5.裸機程序的編寫
6.小結
1.本文概述
從RISCV生態的角度上來看,D1哪吒開發板確實是一塊不錯的可以研究很深的開發板。本文主要從研究D1啟動流程的角度出發,探索一下D1的裸機開發實踐。對于研究D1的底層裸機開發,首先需要知道可以玩那些東西,也可以對RISCV相關的軟件生態有比較透徹的理解,本文會從spl階段到opensbi階段以及后續階段做一個簡單的分析。
2.D1上電后啟動的第一個程序
D1上電后,首先啟動一個(Boot ROM)BROM。根據芯片手冊的描述,該BROM的啟動地址是0地址處開始啟動。
一共是48KB的內存空間用于運行BROM,那么這個BROM做了哪些事情?首先它根據efuse和GPIO選擇了啟動的媒體類型。支持的啟動方式有
SD card
eMMC
SPI NOR Flash
SPI NAND Flash
并且可以根據GPIO的選擇和Efuse的選擇決定啟動的模式。同時也支持USB的啟動方式,這就為fel啟動方式做了很好鋪墊。
總的說來,BROM就是從其他的介質中讀取SPL,然后放到SRAM中執行,同時也通過FEL運行環境。
3.啟動SPL
當BROM啟動完成后,接下來要去存儲介質中尋找SPL的程序,這部分可以通過對全志D1 SDK的源代碼進行查看。
不難看出,在tina-d1-open的源代碼下有lichee的代碼。另外brandy-2.0下有spl、opensbi和u-boot的代碼。通過對spl代碼的研究,主要從流程上可以知道,spl的代碼運行在sram中。
通過查看,可以看到SRAM為32KB,但是實際編譯出來的估計大小在32KB~64KB,遠大于32KB,這樣懷疑的可能性是SRAM可能大于32KB或者利用了DSP0 IRAM的空間。在編譯的過程中,發現SPL的固件的頭部一段區域,也就是0x00020000地址開始處的一段空間,是初始化的參數,SPL可以根據這個參數選擇初始化的串口編號,初始化的DDR參數等等。在這里面編譯的串口并非開發板的參數的串口參數,后面在制作固件的時候,會將頭部的信息替換。為此我做了一個專門研究D1 哪吒裸機的倉庫,來研究其實際的啟動信息。
然后通過設置
export PATH=/yourpath/:$PATH
將gcc的路徑添加到環境變量,直接在spl目錄下編譯即可。
編譯后會在nboot的目錄下生成相關的固件。
在生成的固件中,每個固件分別表示從哪種介質中啟動下一階段。前面說過,spl的頭部存放了一些初始化的參數變量,所以我直接通過一個腳本make_download.sh將spl的頭部一些信息替換了。這樣下來,就能夠正常的啟動spl階段了,并且可以正常的初始化DDR。按下開發板的FEL鍵并且上電。
下載可以利用tools/windows目錄下的xfel工具進行下載。
可以正常的啟動SPL。xfel的工具是xboot大佬旨在打造全志裸機的萬能開發工具,感覺用起來還是挺好。
當前xfel在d1上支持了ddr初始化,下載到SRAM和DDR3等操作,并支持運行程序。非常的強大,后面做裸機開發會經常用到,后續如果能夠支持USB燒錄SPI NAND Flash,那會更加的好用。那么在spl里做了哪些事情?首先SPL是運行在SRAM中的程序,這段程序受到SRAM尺寸大小的影響,并不會做的很復雜。主要功能來說:
1.通過引腳判斷是否啟動JTAG
2.初始化DDR
3.使能MMU
4.根據SD CARD、SPI NAND FLASH 、SPI NOR FLASH判斷初始化那種外設。
5.根據opensbi/rtos/uboot,將其搬運到DDR中執行,然后程序運行在DDR中。
4.啟動opensbi
此時程序就運行在DDR中了,對于開發RISCV的人來說,opensbi并不陌生,一方面這個是后臺常駐程序,提供S-mode和M-mode的轉換層,另外也起到引導下一階段程序的目的。這個d1下個階段指的是uboot。然后opensbi就常駐在M-mode下了。作為獨立的程序,我也在裸機層面去編譯下載opensbi。
https://github.com/bigmagic123/d1-nezha-baremeta/tree/main/opensbi
編譯的過程可以通過
要想在d1上運行opensbi,首先需要根據下面的情況進行編譯。
cd d1-nezha-baremeta/opensbi
然后導入環境變量
export CROSS_COMPILE=/home/bigmagic/work/toolchain-thead-glibc/riscv64-glibc-gcc-thead_20200702/bin/riscv64-unknown-linux-gnu- PLATFORM_RISCV_ISA=rv64gcxthead FW_JUMP_ADDR=0x40200000 FW_TEXT_START=0x40000000
最后進行編譯
make PLATFORM=thead/c910
正常情況下,生成
AS platform/thead/c910/standby-normal/standby.o
CC platform/thead/c910/standby-normal/loadelf.o
CC platform/thead/c910/sunxi_platform.o
CC platform/thead/c910/opensbi_head.o
AS platform/thead/c910/sunxi_cpuidle.o
CC platform/thead/c910/sunxi_idle.o
AR platform/thead/c910/lib/libplatsbi.a
AS platform/thead/c910/firmware/fw_dynamic.o
ELF platform/thead/c910/firmware/fw_dynamic.elf
OBJCOPY platform/thead/c910/firmware/fw_dynamic.bin
AS platform/thead/c910/firmware/fw_jump.o
ELF platform/thead/c910/firmware/fw_jump.elf
OBJCOPY platform/thead/c910/firmware/fw_jump.bin
可以把build/platform/thead/c910/firmware/fw_jump.bin文件下載。
可以通過下面的三條指令進行下載
.xfel.exe ddr ddr3
.xfel.exe write 0x40000000 fw_jump.bin
.xfel.exe exec 0x40000000
最后可以看到啟動如下
其中對opensbi的下載流程,實際上這里直接是通過xfel初始化ddr,然后將程序加載到ddr中直接啟動運行。并沒有通過spl階段,如果想要自己編譯的程序通過spl --》 opensbi??梢栽贚inux上通過dd命令將程序燒錄到sd卡中。
這里將boot0的固件燒錄到sd卡的8K處,系統可以正常的啟動。
5.裸機程序的編寫
在分析了上述SPL和opensbi的啟動流程后,自行編譯一個簡單的裸機程序就容易許多。從啟動流程的角度上來說,只需要實現初始化時鐘、串口即可。這樣就能夠享受D1上裸機開發的樂趣了。更多的外設擴展需要根據芯片手冊去進行編程。
https://github.com/bigmagic123/d1-nezha-baremeta/tree/main/src/1.startup
而燒錄的流程,可以利用xfel初始化ddr,然后燒錄到ddr中,這樣方便調試。目前裸機開發代碼比較好的可以參考xboot的代碼。
https://github.com/xboot/xboot/tree/test-d1
xboot的底層也會用到基本的裸機編程部分的代碼實現,也是非常值得研究和學習的。
6.小結
全志D1芯片的啟動流程最底層的分析來看,和其他全志產品線的芯片的啟動流程基本類似,主要需要理解的是fel模式下對SRAM,DDR等操作,這樣在做裸機開發的時候,才能將程序下載進去。有了這些理解,在做riscv的底層編程的時候,才能透徹的理解其啟動的流程和原理。
原文標題:關于d1哪吒開發板的啟動流程分析
文章出處:【微信公眾號:嵌入式IoT】歡迎添加關注!文章轉載請注明出處。
責任編輯:haq
-
芯片
+關注
關注
455文章
50714瀏覽量
423158 -
開發板
+關注
關注
25文章
5032瀏覽量
97375
原文標題:關于d1哪吒開發板的啟動流程分析
文章出處:【微信號:Embeded_IoT,微信公眾號:嵌入式IoT】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論