寫在之前
這是之前為了工作需要,研究TI的SoC DM6441與Davinci這個公版所做的筆記,原本是放在當時工作所使用的SD Card中,最近因為要拿這張SD Card來作其他事,清理內容的時候找到了這篇文章,所以把他整理一下放了上來。因為長度的關係,我將它分成了三篇,算是那段時間努力的一點紀錄。
DM6441的開機選項
Power on,根據BOOTCFG register,共有四種開機選項:
1.BOOTCFG=0x01, EMIFA boot mode, 直接從NOR flash(0x02000000)開始執行。
2.BOOTCFG=0x00, NAND boot mode, 從internal ROM執行RBL,RBL將UBL從NAND載入internal RAM, UBL將u-boot從NAND載入DDR,u-boot將uImage載入DDR,執行權交給OS。
3.BOOTCFG=0x02, HPI boot mode, External CPU透過HPI(I2C, SPI, USB2.0, VLYNQ) 將UBL載入,餘同 上。
4.BOOTCFG=0x03, UART boot mode, Host透過serial port將UBL載入,餘同上。
DM6441的開機流程
1.RBL不能修改,而真正做hardware initial與load kernel image的是u-boot,所以只要是從internal ROM開機,就需要在RBL的search path上放置它讀得懂的code(UBL),讓UBL去load boot loader。
2.Internal RAM只有16kb,但UBL目前有14kb,u-boot則是96~115kb不等,所以想要把u-boot結合UBL放進internal RAM有困難。
3.可以考慮直接從NOR flash執行u-boot開機,減少search NAND flash與驗證的時間。但有hardware成本問題。
4.可以考慮使用u-boot做為updater,因為u-boot執行期間OS/Driver/GUI都還沒載入,所以可以update完直接開機。
5.恐怕Service Center需要可以off-line操作且具有GUI的updater,可能還需要support USB與SD card driver與file system,這樣就得porting Angelus I所使用的updater給Angelus II使用。
6.恐怕工廠的selftester也會有跟updater一樣的需求,而且selftester可能需要載入大多數的driver。
VanHelsing EVM board的開機流程
![研究TI的SoC DM6441與Davinci這個公版所做的筆記(转载) - hxlhan123 - hxlhan123的博客](https://i-blog.csdnimg.cn/blog_migrate/c5a0b655aed191bcba3fb0a9141af285.gif)
1.根據TI的databook描述,可以選擇從AEMIF(NOR Flash)開機,就可以直接跳到0x02000000去執行放在NOR flash中的u-boot,但旺陽電的VanHelsing並沒有實作NOR flash到EVM board上。
2.因為有NFS/TFTP server,RD在開發期間似乎不需要額外的updater,不管是kernel image/device driver或gui application都可以在u-boot執行期間透過NFS或TFTP server將update file載入target,下command或使用script file都可以輕鬆完成update的動作。
3.u-boot本身兼具bootloader與monitor的功能,將monitor予以disable之後就成為正常的bootloader,如果安排short-cut key讓系統在boot期間(甚至OS在跑的期間也可以跳)跳到它的command handle routine,它就成為一個簡單的on-line debug tool,可以read/write flash、update image、update file system,如果可以加上dump CPU register、dump OS information等功能,或許透過serial port的console就可以滿足大多數的debug需求(它本身有一個exception handler可以做這些事,不過做完就當機,很麻煩)。
Tool Chain
Tool Path Description
GCC /opt/mv_pro_4.0/monstavista/ compiler and linker.
GDB pro/devkit/arm/v5t_le/bin/ software debug tool.
bmp_logo /u-boot/tools/ u-boot logo maker.
envsrc /u-boot/tools/ verify environment for u-boot.
gen_eth_addr /u-boot/tools/ generate ethernet MAC address.
img2srec /u-boot/tools/ make u-boot format image.
mkimage /u-boot/tools/ convert u-boot format image to SREC format.
updater /u-boot/tools/ u-boot auto updater.
U-Boot Command
1.bootp [loadAddress] [bootfilename]
要求DHCP server分配IP給target,然後透過TFTP下載指定的image到memory中。
第1個參數是destination address。
第2個參數是file name,這個file必須已經存在host的tftpboot/底下。
要注意serverip必須已經設定好。
2.tftpboot [loadAddress] [bootfilename]
使用tftp以binary file格式下載file到target。
第1個參數是destination address。
第2個參數是file name,這個file必須已經存在host的tftpboot/底下。
要注意serverip與ipaddr必須已經設定好,file必須已經存在host的tftpboot/底下。
3.nfs [loadAddress] [host ip addr:bootfilename]
使用nfs下載file到target上指定的位址,若未指定host ip, path以及target的address的話,會使用預設值下載kernel image。
第1個參數是destination address。
第2個參數是host端的path與file name。
要注意serverip與ipaddr必須已經設定好,host端的path與file必須已經export。
4.bootm [addr [arg ...]]
從RAM或Flash開機,uImage必須已經load好,rootfs的mount pointer也都指定好。
第1個參數是image address,image必須是u-boot格式。
第2個參數是要pass給kernel的argument,也可以做為RAMDISK address。
5.erase all
erase [start add.] [end add.]
erase bank N
可以設定erase整個nor flash,或指定的區域,或某個bank。
6.nand
nand info - 顯示所有可用的nand flash.
nand read[.jffs2[s]] addr off size - 從」off」讀」size」大小的資料到」addr」,addr指的是memory,off指的是flash。
nand write[.jffs2] addr off size - 從」addr」寫」size」大小的資料到」off」。
nand erase [clean] [off size] - 從」off」開始,清除」size」大小的資料。
nand bad - 顯示壞掉的block。
7.flinfo
flinfo N
可以列出flash所有bank的infomation或只列印指定的bank。
8.iminfo addr [addr ...]
可以列出指定address的data的header。
9.loadb [offset] [baudrate]
透過serial port下載binary data。
10.loads [offset]
透過serial port下載S-Record的data。
11.printenv [name]
印出environment variable的value,若未指定variable則印出全部。
12.setenv name [value]
設定environment variable。
13.md address [address]
印出指定位址(區域)的hex data。
U-Boot Souce Code Architecture
Dirctory Explain
board board dependent files and u-boot.lds.
cpu CPU specific files
lib_arm
common misc architecture independent functions
disk source code for disk driver.
doc simple document for u-boot.
drivers commonly used device drivers
dtt Digital Thermometer and Thermostat drivers
fs source cdoe for file system support
include header Files
lib_generic files generic to all architectures
net networking code
post Power On Self Test
rtc Real Time Clock drivers
tools Tools to build S-Record or U-Boot images, etc.
examples Example code for standalone applications, etc.
Booting Code Trace
由於使用JTAG的reset pin開機會因為RBL所做的hardware check而導致系統停在RBL不出來,所以RBL、UBL與部份的u-boot可能都沒辦法逐行trace,不過可以在u-boot進入main_loop之後再connect CCStudio,至少可以監看network behavior、load/Uncompressing image的動作,也可以監看到kernel開始run的過程。
UBL Source Code Trace
Function Description
selfcopy()
1)Enable ITCM與DTCM。
2)將__selfcopysrc中的資料搬到__selfcopydest中。
3)呼叫boot()。
boot()
1)設定為supervisor mode,disable FIQ & IRQ。
2)將Interrupt Vector Table放到ARM RAM1(0x2000)的位置。
3)設定Stack Pointer。
4)執行main()。
5)執行main()從flash或uart端搬進DDR2的application。
main()
1)執行PSCInit(),初始化Power & Sleep Control的feature。
2)檢查BOOTCFG的第6~7個bit,若為0則表示從NAND開機,若為1則表示從NOR開機,若都不
是則進入無窮迴圈等待RBL對UART的存取結束。
3)呼叫DM644xInit(),對UARTs/PLL1/PLL2/DDR2/IVT做initial。
4)將current_mem_loc設為0,也就是RAM0開始的位置(0x0000)。
5)分別呼叫NAND_Copy()與NOR_Copy(),到flash中去尋找符合的application,並且將它搬
到DDR2中。
6)若flash中沒有符合的applcation,則使用UART下載。
7)application放進DDR2之後,return回boot(),執行application。
PSCInit()
1) PSC是Power and Sleep Control的意思。
2)Reset DSP core,Power on internal component。
3)設定EMURSTIE。
4)設定」Always on」與」DSP」兩部份的power domain。
5)清除EMURSTIE。
Importance Configure
File Name Description
davinci.h 1.由start.s所include。
2.紀錄MCU與mainboard的hardware configure,包括:
1)CPU and software information
2)LCD configure information
3)Flash configure information
4)Memory configure information
5)Serial driver information
6)I2C configure information
7)Linux information
8)Network and Ethernet information
cmd_confdefs.h 1.由davinci.h所include。
2.紀錄command handle相關的設定。
U-Boot Source Code Trace
Function Description
start.S
程式起始點:
1)根據/u-boot-1.1.3/board/davinci/u-boot.lds描述,程式的起始點為globle symbol
_start,它同時也是系統power on之後第一個執行的指令。
2)跳到reset(129行),讓CPU進入supervisor mode。
3)使用coprocessor指令對CACHE, TLB, MMU做initial,並且執行platform setup對內部
硬體做initial,做完跳回。
4)對u-boot做rellocate,若已經做過reallocate則跳過,。
5)計算statck位置與大小,放置stack pointer。
6)並將bss的空間清為0。
7)跳到C程式start_armboot()去執行。
platformsetup:
1)Mask all IRQs by setting all bits in the EINT default.
2)Put the GEM in reset.
3)Enable L1 & L2 Memories in Fast mode.
4)DDR2 PLL Intialization.
5)Issue Soft Reset to DDR Module.
6)Program DDR2 MMRs for 135MHz Setting.
7)Issue Soft Reset to DDR Module.
8)Turn DDR2 Controller Clocks On.
9)System PLL Intialization.
10)AEMIF configuration for NOR Flash (double check).
11)VTP manual Calibration.
relocate:
adr r0, _start /* 將_start的位址存到R0中 */
ldr r1, _TEXT_BASE /* 將_TEXT_BASE的位址存到R1中 */
cmp r0, r1 /* 若_start的位址與_TEXT_BASE相同 */
beq stack_setup /* 表示已經做過reallocate,可以跳過 */
ldr r2, _armboot_start /* 將_armboot_start的位址存到R2 */
ldr r3, _bss_start /* 將_bss_start的位址存到R3 */
sub r2, r3, r2 /* 相減得到armboot的size存到R2 */
add r2, r0, r2 /* 將armboot的結束位址存到R2 */
copy_loop: /* M:multiple,IA:Increment After */
ldmia r0!, {r3-r10} /* 從R0的位址開始循序取值存到R3~R10 */
stmia r1!, {r3-r10} /* 將R3~R10的資料循序存到R1指的位址 */
cmp r0, r2 /* 直到armboot全部複製完畢 */
ble copy_loop
start_armboot()
1)init_sequence[]存放許多hardware initial的function pointer,循序執行,若有錯則
顯示error message。
2)呼叫flash_init()做flash information setting與size detect,並印出size。
3)VDF未define,lcd_setmem()用來預留momory space給LCD display。
4)將準備給malloc()使用的位置清空,大小為64k+128k,_armboot_start在0x81050044。
5)呼叫nand_init()對NAND flash(EMIFA,0x02000000)做initial,取得flash的info並且選
定file system為JFFS2(實際上是nand_probe()在做)。
6) AT91F_DataflashInit()與dataflash_print_info()沒build。
7)呼叫env_relocate(),若environment不可使用則載入defualt setting,否則將可用的
environment寫回flash。
8)drv_vfd_init()未build。
9)呼叫getenv_Ipaddr()取得target ip,呼叫getenv_r()代入」 ethaddr」取得MAC
address。
10)呼叫devices_init()對device做initial,目前只有i2c_init()與drv_system_init()。
11)呼叫jumptable_init()去為jumptable中的function pointer指定function body。
12)呼叫console_init_r()建立console到serial port。
13)呼叫misc_init_r()透過I2C取得MAC address,並寫入environment。
14)enable_interrupts()是空的function。
15)設定ethaddr, loadaddr, bootfile等environment。
16)設定ethernet。
17)進入main_loop(),等待command的輸入並予以處理。
console_init_r()
1)搜尋現有的standard I/O device。
2)為stdin, stdout, stderr指定getc, tstc, putc, puts與printf等function到實際上的
device driver上(serial port),其實是keep function pointer到gb->jt[]之中。
3)印出stdio相對應的device。
4)將stdio的information寫到environment中,並建立console。
main_loop()
1)使用getenv()取出」bootdelay」,delay過後繼續執行。
2)取出」menucmd」執行。
3)呼叫readline(),印出提示符號並且持續去取得console輸入的command,存到
console_buffer[]中,直到Entry鍵被按下,會傳回command length。
4)呼叫run_command()來執行console_buffer中的command。
5)無窮迴圈。
run_command()
1)檢查command是否為null或長度是否超出限制。
2)呼叫process_macros()與parse_line()取出macro string放進argv[]之中。
3)透過find_cmd()到存放u-boot command的記憶體區塊中尋找相對應的command,若找得到
相對應的command,則將整個指向structure cmd_tbl_t的指標傳回,若否則傳回NULL。
4)若command為bootd,先確認CMD_FLAG_BOOTD已經寫入flag(若否則寫入),然後傳入flag
與argc, argv,執行cmd_tbl_t所紀錄的command function。
5)執行完cmd之後,會再執行run_command()。(這樣stack不會爆掉嗎?recursive)
do_bootm()
1)呼叫memmove(),將uImage從指定的地方搬到DDR中。
2)檢查magic number,若不相符則return 1。
3)檢查CRC check sum,若不正確則return 1。
4)若以上均正確則呼叫print_image_hdr()從console印出image information。
5)檢查image source的CRC check sum,若不正確則return 1。
6)判斷image type為stand-alone file,將argument 2紀錄起來。
7)disable_interrupts()與enable_interrupts()均被disable掉,沒作用。
8)判斷image壓縮的格式,執行解壓縮並將解壓縮後的image放到指定address。
9)跳到image header中指定的entry pointer去執行。
10)執行do_bootm_linux()。
do_bootm_linux()
1)檢查initrd_high這個enviornment。
2)取得bootargs,設定clock。
3)判斷image是stand-alone、multi或載入RAMDisk。
若需要載入RAMDisk,則依augument 2將RAMDisk image載入,執行與kernel image一樣的
magic number check與check sum verify動作,若verify fail則reset CPU。
若載入的是multi file,則將data指向第二個file的起始位置,len為長度。
若是stand-alone則將data與len設為0。
4)用memmove()將RAMDisk搬到DDR。
5)執行kernel image的entry point。
do_nand()
cmd_nand.c就是nand operation的driver,所有對nand的操作都實作在這邊。
1)主要是parse argument並且執行相關的處理,argument以print info與flash operation
為主,print info的部份主要是從nand_dev_desc[]將一些與NAND相關的資料印到
console,flash operation則是有關flash read/write/erase,其中read/write的部份還
分為jaffs2與oob兩種方式。
2)如果是erease,呼叫nand_erase()對指定的區域做清除的動作。
3)如果是read或wreite,先判斷要寫入的資料是jffs2或是oob,然後呼叫nand_rw()做讀
或寫的動作。
4)如果是oob,則讀寫的動作改為以nand_read_oob()及nand_write_oob()執行。
do_nandboot()
1)使用getenv()從enviornment與argument取出bootdevice、addr、offset等資訊。
2)使用nand_rw()將image的前512 byte載入DDR。
3)驗證magic number,並呼叫print_image_hdr()印出image infomation。
4)再次使用nand_rw()將image剩餘的資料載入DDR。
5)檢查autostart的內容,執行do_bootm()。
do_nfs()
cmd_net.c主要是實作網路功能的介面,部份功能由/net/net.c實作。
1)從argument取得load address、host ip、file name(含path)。
2)呼叫NetLoop()做網路卡的initial與protocol的設定。如果是使用NFS則呼叫NfsStart(),
如果是TFTP則呼叫TftpStart(),它們會去執行load image的動作。
3)netboot_update_env()會將一些網路相關的設定存到enviorment。
4)如果autostart有被設定,則執行do_bootm()。
do_load_serial_bin()
1)從argument或environment取得load address、baudrate、offset。
2)呼叫serial_setbrg()之後,進入等待」\r」的無窮迴圈。
3)呼叫load_serial_bin()從serial port接收image,經過驗證之後放到load address。
4)重設baudrate之後,進入無窮迴圈,輸入ESC鍵之後退出。
Power-Down Solution
Sprs359b.pdf這份document中有提到DM6441有四個power-down mode可以選擇:
1.Stand By mode – 幾乎全關,只有GPIO(interrupt)、UARTs、I2C、MAC醒著。
2.Low Power mode –不給clock,只有ARM、GPIO、UARTs、SPI、I2C、PWM、Timer醒著,ARM降頻。
3.Preview mode – ARM、DDR、Flash、HDD醒著,其餘必要的component也醒著。
4.Active mode – 全開。
但是並沒有提到要怎麼trigger這四個mode,或是那一個register可以控制所有的component進入這四個mode,可能power-down solution需要由software自己做。
查閱sprue14a.pdf與sprs359b.pdf,總結如下:
1.PLL
PLL本身可以降頻,也可以將PLL設定為By Pass,讓PLL完全停止工作。
2.ARM
ARM本身是Always-On,但是可以降頻,同時ARM有一個」wait-for-interrupt mode」可以關掉clock並且讓ARM完全停止工作。
3.DSP
C64x+本身提供一個power-down controller,可以把DSP、Internel Memory、External Memory、Cache Memory都power-down。
4.MODULE
MODULE可以分別clock off,也可以透過PLL降頻來省電。理論上clock off的module,它的power comsumption是0,但不包括銲接與電路設計問題產生的漏電。
5.I/O
透過I/O連接的裝置,也可以進入stand-by mode省電,其中GPIO與MMC/SD的部份是分開的。應該LCD與HDD也都有自己的power-down solution吧!
RAMDISK
RAMDISK是把RAM拿來當DISK,一般用來暫時取代root file system,做一些特殊的工作,譬如Angules的update OS/GUI/module與selftest就是在掛載RAMDISK時執行。
1.建立空的initrd.img檔案:
$ dd if=/dev/zero of=initrd.img bs=1k count=4096
$ mkfs.ext2 –F initrd.img
2.掛載initrd:
$ mkdir /mnt/initrd
$ omunt –t ext2 –o loop initrd.img /mnt/initrd
3.建立所需的目錄並複製檔案:
$ cd /mnt/intrd
$mkdir bin dev etc lib mnt proc sbin syst usr
4.壓縮initrd.img並轉換成u-boot格式:
$ umount /mnt/initrd
$ gzip –best –c initrd.img > initrd.img.gz
$ mkimage –n 『RAMDISK' –A arm –O linux –T ramdisk –C gzip –d initrd.img.gz initrd.uboot
5.在u-boot的enviorment中的bootcmd加上:
root=/dev/ram rw initrd=0x80000000,4M
Study Question
Q1:How to install/configure NFS server?
Ans:
1)Install rpm file:
host $ rpm –ivh nfs-utils-1.0.6-1.rpm
host $ rpm –ivh portmap-4.0-57.rpm
2)Fedora Core 7 rename service 「protmap」 to 「rpcbind」.
Q2:How to check NFS was work correct?
Ans:
1)Check service and port number mapping:
host $ netstat -tunlp
2)Check portmap:
host $ rpcinfo
3)Check iptables:
host $ iptables –L
4)Turn off iptables:
host $ iptables –F
host $ iptables –X
host $ iptables –Z
Q3:How to operate NFS both client and host side(send/get)?
Ans:
1)Startup NFS server on host:
host $ /usr/sbin/exportfs –a
host $ /sbin/service nfs restart
2)Export share directory(kernel image and root file system) on host:
host $ vi /etc/exports
Add share directory and authority:
/root/workdir/filesys *(rw,no_root_squash,no_all_squash,sync)
/opt *(rw,sync)
3)Check host IP:
host $ ifconfig
4)Check nfs support:
host $ cat /proc/filesystems
5)Check share directory:
host $ showmount –e localhost
target $ showmount –e host_ip
6)Mount share directory on client:
target $ mount host_ip:/remote_dirctory client_dirctory
7)check xinetd service:
host $ /sbin/chkconfig --list
Q4:The u-boot command study.
Ans:check u-boot command list previous.
Q5:How to set environment variable for booting?
Ans:
1)OS image and root file system load form NFS server both:
bootdelay=3
baudrate=115200
filesize=14C4C0
stdin=serial
stdout=serial
stderr=serial
ethaddr=00:0e:99:02:51:90
videostd=ntsc
serverip=10.4.5.20
nfshost=10.4.5.20
ipaddr=10.4.5.18
bootfile=/opt/mv_pro_4.0/montavista/pro/devkit/lsp/ti-davinci/arch/arm/boot/uImage
rootpath=/home/tester/workdir/filesys
bootargs=console=ttyS0,115200n8 noinitrd rw ip=dhcp root=/dev/nfs nfsroot=10.4.5.20:/home/tester/workdir/filesys,nolock mem=120M
bootcmd=dhcp;bootm
2)OS image load form NAND flash, root file system load form NFS server:
bootdelay=3
baudrate=115200
filesize=14b084
fileaddr=80700000
stdin=serial
stdout=serial
stderr=serial
ethaddr=00:0e:99:02:51:90
videostd=ntsc
nfshost=10.4.5.20
ipaddr=10.4.5.18
serverip=10.4.5.20
bootfile=/opt/mv_pro_4.0/montavista/pro/devkit/lsp/ti-davinci/arch/arm/boot/uImage
bootargs=console=ttyS0,115200n8 noinitrd rw ip=dhcp root=/dev/nfs nfsroot=10.4.5.20:/home/tester/workdir/filesys,nolock mem=56M
bootcmd=nand read.jffs2 0x80700000 0x200000 0x200000\;bootm 0x80700000
rootpath=/home/tester/workdir/filesys
3)OS image load form NAND flash, root file system load form HDD
bootdelay=3
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
ethaddr=00:0e:99:02:51:90
videostd=ntsc
nfshost=10.4.5.20
filesize=14b084
fileaddr=80700000
ipaddr=10.4.5.18
serverip=10.4.5.20
bootfile=/opt/mv_pro_4.0/montavista/pro/devkit/lsp/ti-davinci/arch/arm/boot/uImage
bootcmd=nand read.jffs2 0x80700000 0x200000 0x200000;bootm 0x80700000
bootargs=mem=120M console=ttyS0,115200n8 root=/dev/hda5 rw noinitrd ip=dhcp
rootpath=/
Q7:What are the u-boot image build setting? How to update?
Ans:
1)首先要修改Makefile,因為原始的Makefile企圖使用rm -f刪巢狀目錄,所以在config & make時會發生錯誤而中止,
所以要將"~/examples/Makefile"與~/Makefile打開,將所有的"rm -f"改為"rm -fr"。
2)"~/examples/Makefile"除了rm的問題之外,還有第126行與第129行需改為:
126 %.srec: %.o
129 %.bin: %.o
3)執行"make davinci_config",執行完在~/include/底下將產生config.mk,會記錄ARCH, CPU與BOARD等資訊。
4)執行"make",開始build u-boot的binary file,完成後將產生下列檔案:
u-boot ELF格式的u-boot image
u-boot.bin 原始binary格式的u-boot image
u-boot.map u-boot的symbol list
u-boot.srec S-Record格式的u-boot image
5)使用CCStudio即可將u-boot.bin燒錄到flash中。
Q8:How to arrange the kernel image that get from NFS, Flash or SD cord? (timing, format, version verify)
Ans:主要是修改u-boot的enviornment中的」bootfile」、」bootcmd」、」bootargs」,但是若有使用NFS或TFTP server就需要要先設定好serverip/nfshost/ipaddr等,若是從local media載入則需寫好load image的script並且指定file size。
Q9:How to arrange the root file system that get from NFS, HDD, or Ramdisk?
Ans:如果是從NFS server掛載,注意事項與load image from NFS相同,如果是mount from HDD,則需要再指定rootpath,bootargs的設定也不相同。