DM365视频处理流程/DM368 NAND Flash启动揭秘
?? DM365的視頻處理涉及到三個(gè)相關(guān)處理器,分別是視頻采集芯片、ARM處理器和視頻圖像協(xié)處理器(VICP),整個(gè)處理流程由ARM核協(xié)調(diào)。視頻處理主要涉及三個(gè)處理流程,分別是視頻采集、視頻編碼和對(duì)編碼后的視頻的處理,為了提高性能,通常為每個(gè)處理流程提供一個(gè)處理線程。
視頻采集
? TVP5146將采集到的視頻數(shù)據(jù)轉(zhuǎn)化為數(shù)字信號(hào),并將這些數(shù)據(jù)送入DM365的BT656接口,然后通過(guò)Resize得到所需要的分辨率,然后將這些數(shù)據(jù)寫(xiě)入到指定的內(nèi)存中,這些內(nèi)存空間由cmem模塊分配。cmem模塊用于分配連續(xù)的存儲(chǔ)空間,連續(xù)的存儲(chǔ)空間可以提高數(shù)據(jù)的讀寫(xiě)效率。
視頻編碼
?? VICP從指定的存儲(chǔ)空間中讀入視頻數(shù)據(jù),并將這些數(shù)據(jù)編碼為指定的視頻/圖像格式,然后將編碼后的數(shù)據(jù)寫(xiě)入到指定的存儲(chǔ)空間,這些存儲(chǔ)空間通常也是由cmem模塊分配。
編碼數(shù)據(jù)處理
? ARM從指定的內(nèi)存空間中獲取編碼后的視頻數(shù)據(jù),可以將這些編碼后的數(shù)據(jù)保存到本地或遠(yuǎn)端,也可以使用RTP協(xié)議發(fā)送到網(wǎng)絡(luò)。
整個(gè)過(guò)程由ARM核協(xié)調(diào),為了提高效率,大量使用DMA操作和cmem模塊分配的連續(xù)存儲(chǔ)空間。
?
| ? |
作者:德州儀器現(xiàn)場(chǎng)技術(shù)支持工程師 孟海燕
概要:
本文介紹了DM368 NAND Flash啟動(dòng)的原理,并且以DM368 IPNC參考設(shè)計(jì)軟件為例,介紹軟件是如何配合硬件實(shí)現(xiàn)啟動(dòng)的。
關(guān)鍵字:NAND Flash啟動(dòng),RBL,UBL
芯片上電后是如何啟動(dòng)實(shí)現(xiàn)應(yīng)用功能的?這是許多工程師在看到處理器運(yùn)行的時(shí)候,通常都會(huì)問(wèn)的一個(gè)問(wèn)題。下面我們就以德州儀器的多媒體處理芯片TMS320DM368為例,介紹它的NAND Flash啟動(dòng)原理以及實(shí)現(xiàn)。
一.NAND Flash啟動(dòng)原理
德州儀器的多媒體處理芯片TMS320DM368可以實(shí)現(xiàn)1080P30 h264的編碼,已經(jīng)廣泛的使用在了網(wǎng)絡(luò)攝像機(jī)的應(yīng)用中。DM368可以支持NOR Flash, NAND Flash, UART, SD Card啟動(dòng)等多種啟動(dòng)方式。對(duì)于NAND啟動(dòng),DM365支持的特性如下:
1.?? 不支持一次性全部固件下載啟動(dòng)。相反的,需要使用從NAND flash把第二級(jí)啟動(dòng)代碼(UBL)復(fù)制到ARM的內(nèi)存(AIM),將控制轉(zhuǎn)交給用戶定義的UBL。
2.?? 支持最大4KB頁(yè)大小的NAND。
3.?? 支持特殊數(shù)字標(biāo)志的錯(cuò)誤檢測(cè),在加載UBL的時(shí)候會(huì)嘗試最多24次。例如在NAND的第1個(gè)block沒(méi)有找到特殊數(shù)字標(biāo)志,會(huì)到下一個(gè)block繼續(xù)查找,一直到查找到第24個(gè)block。
4.?? 支持30KB大小的UBL(DM365有32KB的內(nèi)存,其中2KB用作了RBL的堆棧,剩下的空間可以放UBL)
5.?? 用戶可以選擇在RBL執(zhí)行的時(shí)候是否需要支持DMA,I-cache(例如,加載UBL的時(shí)候)
6.?? 使用并且需要4位硬件ECC(支持每512字節(jié)需要ECC位數(shù)小于或等于4位的NAND Flash)。
7.?? 支持需要片選信號(hào)在Tr讀時(shí)間為低電平的NAND Flash。
在網(wǎng)絡(luò)網(wǎng)絡(luò)攝像機(jī)的應(yīng)用中為了節(jié)約成本,有一些用戶使用了NAND Flash啟動(dòng)方式。圖1 就是從上電到Linux啟動(dòng)的一個(gè)概要的流程圖。首先RBL(ROM boot loader)從NAND上讀取UBL(user boot loader)并且復(fù)制到ARM的內(nèi)存里面。UBL運(yùn)行在ARM的內(nèi)存里,初始化系統(tǒng),例如初始化DDR。然后UBL從NAND Flash里面讀取U-Boot的內(nèi)容并且復(fù)制到DDR里運(yùn)行。DDR里面運(yùn)行的U-Boot又從NAND Flash里面讀取Linux內(nèi)核代碼,并且復(fù)制到DDR上,然后啟動(dòng)內(nèi)核。這樣DM365的系統(tǒng)就從上電到完成Linux內(nèi)核啟動(dòng),然后就可以運(yùn)行相應(yīng)的應(yīng)用程序了。
圖1 NAND Flash啟動(dòng)流程
下面我們會(huì)一步一步的介紹從上電到Linux啟動(dòng)是如何實(shí)現(xiàn)的。
首先我們需要提到的一個(gè)概念是RBL,也就是ROM Boot Loader (ROM啟動(dòng)代碼)。在DM368芯片上有一塊ROM的區(qū)域(地址從0x00008000到 0x0000 BFFF),這塊區(qū)域就是存放RBL代碼的地方。ROM上的代碼是在芯片出廠前就燒寫(xiě)好的,用戶是不能修改的。在DM368上,除了AEMIF (Nor Flash)啟動(dòng),其他的啟動(dòng)方式都需要運(yùn)行RBL。
無(wú)論是上電復(fù)位,熱復(fù)位,還是看門狗復(fù)位,在復(fù)位信號(hào)由低到高的時(shí)候,DM368芯片會(huì)檢測(cè)BTSEL[2:0]引腳(啟動(dòng)選擇引腳)。只要檢測(cè)到電平不是001,也就是不是AEMIF (NOR Flash)啟動(dòng),ARM程序就會(huì)從ARM的ROM的地址0x00008000地址開(kāi)始執(zhí)行。
RBL首先會(huì)讀取BOOTCFG寄存器里面的BTSEL信息,如果發(fā)現(xiàn)BTSEL的狀態(tài)是000,就會(huì)得知配置的是NAND Flash啟動(dòng),NAND啟動(dòng)模式開(kāi)始執(zhí)行。注意:為了保證NAND啟動(dòng)正常運(yùn)行,需要保證在復(fù)位的時(shí)候DEEPSLEEPZ/GIO0引腳拉高。在確認(rèn)啟動(dòng)是NAND后,首先RBL會(huì)初始化最高2KB的內(nèi)存為堆棧并且關(guān)閉所以中斷。然后RBL會(huì)讀取NAND的ID信息,然后在RBL的代碼里面的NAND ID 列表,從而得知更詳細(xì)的NAND Flash的信息,例如頁(yè)(page)大小等,對(duì)EMIF做好相應(yīng)的配置。DM368支持啟動(dòng)的NAND的ID信息可以在參考文檔1(ARM子系統(tǒng)用戶手冊(cè))里面找到。硬件選型時(shí),請(qǐng)務(wù)必選擇在NAND ID列表里面支持的NAND芯片。
接下來(lái),RBL會(huì)在NAND Flash的第1塊的第0個(gè)頁(yè)開(kāi)始查找UBL的描述符。如果沒(méi)有找一個(gè)合法的UBL的特殊數(shù)字標(biāo)志,RBL會(huì)繼續(xù)到下一個(gè)塊的第0個(gè)頁(yè)查找描述符,最多第24個(gè)塊。RBL會(huì)到多個(gè)塊里面查找描述符是根據(jù)NAND Flash本身容易與壞塊的特點(diǎn)而設(shè)計(jì)的。24塊應(yīng)該足以避免NAND Flash壞塊的影響。
如RBL在某塊里面找到了合法的UBL描述符,這個(gè)塊號(hào)(block number)就會(huì)寫(xiě)到ARM內(nèi)存最后的32位(0x7FFC~0x8000)用于調(diào)試時(shí)候使用,然后UBL描述符的具體內(nèi)容將被讀取并且處理。UBL描述符告訴RBL關(guān)于下載和將控制權(quán)交給UBL所需要的信息,具體見(jiàn)表1.
| 第0頁(yè)地址 | 32位 | 描述 |
| 0 | 0xA1AC Edxx | 特殊數(shù)字標(biāo)志 |
| 4 | UBL入口地址 | 用戶啟動(dòng)代碼的入口地址(絕對(duì)地址) |
| 8 | UBL使用的頁(yè)數(shù) | 頁(yè)數(shù)(用戶啟動(dòng)diamond的大小) |
| 12 | UBL開(kāi)始的塊號(hào) | 開(kāi)始存放用戶啟動(dòng)代碼的塊號(hào)(block number) |
| 16 | UBL開(kāi)始的頁(yè)數(shù) | 開(kāi)始存放用戶啟動(dòng)代碼的頁(yè)數(shù) |
| 20 | PLL設(shè)置-M | PLL設(shè)置- 倍率(僅在特殊數(shù)字標(biāo)準(zhǔn)表示PLL使能的時(shí)候有效) |
| 24 | PLL設(shè)置-N | PLL設(shè)置- 分率(僅在特殊數(shù)字標(biāo)準(zhǔn)表示PLL使能的時(shí)候有效 |
| 28 | 快速EMIF設(shè)置 | 快速EMIF設(shè)置(僅在特殊數(shù)字標(biāo)準(zhǔn)表示快速EMIF啟動(dòng)的時(shí)候有效) |
表1 NAND UBL描述符
一旦用戶需要的啟動(dòng)設(shè)置配置好,RBL就會(huì)從0x0020第地址開(kāi)始把UBL搬移到ARM內(nèi)存。在從NAND讀取UBL的過(guò)程中中,RBL會(huì)使用4位的硬件ECC對(duì)NAND Flash上的數(shù)據(jù)進(jìn)行檢錯(cuò)和糾錯(cuò)。如果因?yàn)槠渌蜃x失敗,復(fù)制會(huì)立即停止,RBL會(huì)在下個(gè)塊里面繼續(xù)尋找特殊數(shù)字標(biāo)志。
對(duì)于UBL的描述符有幾點(diǎn)注意事項(xiàng):
1.?? 入口地址必須在0x0020到0x781C之間
2.?? 存放UBL的頁(yè)必須是連續(xù)的頁(yè),可以分布在多個(gè)塊內(nèi),總共大小必須小于30KB。
3.?? UBL的起始?jí)K號(hào)(block number)可以是和存放UBL描述符的塊號(hào)一樣。
4.?? 如果UBL的起始?jí)K號(hào)是和存放UBL描述符的塊號(hào)一樣, 那UBL的起始頁(yè)數(shù)一定不可以和UBL描述符存放的頁(yè)數(shù)一樣。
但RBL根據(jù)UBL描述符里提供的UBL大小信息將UBL全部成功復(fù)制到ARM內(nèi)存后,RBL會(huì)跳到UBL起始地址,這樣芯片的控制權(quán)就交給了UBL,UBL開(kāi)始在ARM內(nèi)存里運(yùn)行了。
也許你會(huì)問(wèn),既然RBL可以把NAND Flash上的內(nèi)容復(fù)制到ARM內(nèi)存里運(yùn)行,為什么我們不直接把U-Boot復(fù)制到內(nèi)存運(yùn)行?原因是ARM內(nèi)存太小。一般的U-Boot都是大于100KB,而DM365上可以用于啟動(dòng)的內(nèi)存只有30KB。也許你又要問(wèn)了,那為什么不把U-Boot直接復(fù)制到DDR上運(yùn)行,DDR有足夠大的空間?這個(gè)原因是,芯片上電后并無(wú)法知道用戶在DM365的DDR2接口上接的DDR信息,RBL也就無(wú)法初始化DDR,在RBL運(yùn)行的階段DDR是不可用的。這也是為什么UBL里面初始化DDR是它的一項(xiàng)重要任務(wù)。
當(dāng)NAND啟動(dòng)失敗的時(shí)候,RBL會(huì)繼續(xù)嘗試MMC/SD啟動(dòng)方式。如果你系統(tǒng)使用NAND啟動(dòng),但NAND上的內(nèi)容損壞了,如果你的板子上有SD卡接口,也可以改變啟動(dòng)方式,那你可以用SD卡先把系統(tǒng)啟動(dòng)起來(lái),然后重新燒寫(xiě)NAND Flash上的內(nèi)容。這可以作為產(chǎn)品失效后在客戶側(cè)的一個(gè)補(bǔ)救方法。
二.NAND Flash啟動(dòng)的軟件配合實(shí)現(xiàn)
現(xiàn)在我們知道了DM368 NAND Flash啟動(dòng)的原理,下面我們來(lái)看看軟件是如何根據(jù)并配合硬件的要求實(shí)現(xiàn)啟動(dòng)的。在DM368 IPNC的軟件包里面有一個(gè)工具的目錄,里面有預(yù)先編譯好的燒寫(xiě)NAND的CCS的可執(zhí)行文件, UBL的二進(jìn)制文件以及相關(guān)源碼。
剛才在介紹NAND Flash啟動(dòng)原理的時(shí)候,我們提到了RBL需要到NAND Flash上面搜索特殊數(shù)字標(biāo)志。這個(gè)特殊數(shù)字標(biāo)志就是由燒寫(xiě)NAND的CCS的工程寫(xiě)到Flash上的。在flash_utils_dm36x_1.0.0\flash_utils_dm36x\DM36x\CCS\NANDWriter\src\nandwriter.c里面的LOCAL_writeHeaderAndData()函數(shù)就是用來(lái)寫(xiě)描述符的。
// Setup header to be written
headerPtr = (Uint32 *) gNandTx;
headerPtr[0] = nandBoot->magicNum; //Magic Number
headerPtr[1] = nandBoot->entryPoint; //Entry Point
headerPtr[2] = nandBoot->numPage; //Number of Pages
#if defined(IPNC_DM365) || defined(IPNC_DM368)
headerPtr[3] = blockNum+3; //Starting Block Number
headerPtr[4] = 0; //Starting Page Number - always start data in page 1 (this header goes in page 0)
對(duì)比表1,你可看到headerPtr[3]的內(nèi)容是用來(lái)存放UBL代碼的起始?jí)K號(hào)。這里+3的意思就是UBL是存放在UBL描述符所放塊號(hào)后面的第三塊里面。headerPtr[4] = 0表示是從第0頁(yè)開(kāi)始存放。當(dāng)然這個(gè)值用戶是可以修改的。只要你燒寫(xiě)UBL代碼的位置和描述符里面的起始?jí)K/頁(yè)數(shù)一致就可以了。
在IPNC的代碼里面UBL的描述符是會(huì)從NAND Flash的第1個(gè)塊開(kāi)始寫(xiě),如果塊是好的,就放在第1塊的第0頁(yè)。如果第1塊是壞的,就會(huì)把UBL的描述符寫(xiě)入到下一個(gè)塊的第0頁(yè)。IPNC的代碼里面沒(méi)有將UBL描述符可能有的塊號(hào)從1到24塊(這是RBL搜索的范圍),它只是從第1塊到第3塊。如果UBL描述符放在第1塊,那如果第4塊是好的話,UBL的代碼就從第4塊的第0頁(yè)開(kāi)始放。
#elif defined(IPNC_DM368)
// Defines which NAND blocks the RBL will search in for a UBL image
#define DEVICE_NAND_RBL_SEARCH_START_BLOCK (1)
#define DEVICE_NAND_RBL_SEARCH_END_BLOCK (3)
在nandwriter.c里面你還可以看到UBL的入口地址是固定的0x100。
gNandBoot.entryPoint = 0x0100; // This fixed entry point will work with the UBLs
要了解為什么是0x100,你就必須要看一下UBL的源碼。在UBL源碼的UBL.cmd文件里面,你可以看到下面的定義,將入口地址放在boot的地方,而boot的運(yùn)行地址就是0x100。
-e boot //指定入口地址為boot
...
MEMORY
{
...
UBL_I_TEXT (RX) : origin = 0x00000100 length = 0x00004300
...
UBL_F_TEXT (R) : origin = 0x020000E0 length = 0x00004300
...
}
SECTIONS
{
...
.text : load = UBL_F_TEXT, run = UBL_I_TEXT, LOAD_START(FLASHTEXTStart), LOAD_SIZE(FLASHTEXTSize)
{
*(.boot)
. = align(4);
*(.text)
. = align(4);
}
....
}
在UBL的源碼boot.c里面有強(qiáng)制把啟動(dòng)的最初代碼放在了boot的section里面。
#if defined(__TMS470__)
...
#pragma CODE_SECTION(boot,".boot");
#endif
void boot(void)
{
...
}
這樣從cmd的配置以及代碼指定代碼段,UBL的程序就能確保是從0x100的地址開(kāi)始運(yùn)行。
UBL啟動(dòng)U-Boot的過(guò)程,借鑒了RBL啟動(dòng)UBL的原理。燒寫(xiě)描述符也是用同樣的LOCAL_writeHeaderAndData()函數(shù)。在nandwriter.c里面,我們把U-Boot的代碼叫做應(yīng)用代碼(APP)。
// Defines which NAND blocks are valid for writing the APP data
#define DEVICE_NAND_UBL_SEARCH_START_BLOCK (8)
#define DEVICE_NAND_UBL_SEARCH_END_BLOCK (10)
下面是IPNC啟動(dòng)后串口最初的打印。
Valid magicnum, 0xA1ACED66, found in block 0x00000008.
DONE
Jumping to entry point at 0x81080000.
我們可以看到UBL是指第8塊的地方找到了U-Boot的描述符,這個(gè)DEVICE_NAND_UBL_SEARCH_START_BLOCK的定義是一致的。
IPNC代碼支持在U-Boot里面更新UBL或者U-Boot自己。下面是燒寫(xiě)ubl和U-Boot在U-Boot下的命令。
燒寫(xiě)ubl:
nand write 0x80700000 0x080000 0x08000
燒寫(xiě)U-Boot:
nand write 0x80700000 0x160000 0x28000
要了解為什么NAND Flash的燒寫(xiě)地址是0x80000和0x160000,這還是需要了解nandwriter.c里面的燒寫(xiě)流程。從前面的內(nèi)容我們可以得知,nandwriter.c燒寫(xiě)UBL是從1+3=4塊開(kāi)始的,而燒寫(xiě)U-Boot是從8+3=11塊。在IPNC上使用的NAND Flash是2K一個(gè)頁(yè),每個(gè)塊128KB。所以UBL燒寫(xiě)的地址是128KBx4=0x80000,而燒寫(xiě)U-Boot的地址是128Kx11=0x160000。
所以如果在沒(méi)有NAND Flash壞塊的情況下,nandwriter.c會(huì)把UBL的描述符燒寫(xiě)在第1塊第0頁(yè)上,把UBL的代碼燒寫(xiě)在第4塊第0頁(yè)上,把U-Boot(APP)的描述符燒寫(xiě)在第8塊第0頁(yè)上,把U-Boot的代碼燒寫(xiě)在第11塊第0頁(yè)上。這樣芯片在上電確認(rèn)是NAND Flash啟動(dòng)后,RBL在執(zhí)行的時(shí)候就會(huì)找到UBL相應(yīng)的描述符,把UBL加載的ARM內(nèi)存里運(yùn)行。而UBL又找到了U-Boot的描述符,把U-Boot加載到DDR上運(yùn)行。最后U-Boot加載uImage并啟動(dòng)了Linux,完成了從上電到Linux啟動(dòng)的整個(gè)過(guò)程。
三.結(jié)束語(yǔ)
每個(gè)芯片一般都有多種啟動(dòng)方式,各個(gè)芯片的啟動(dòng)方式都有所不同,但又有類似的地方。上面的介紹也可以作為學(xué)習(xí)其他芯片其他啟動(dòng)方式的一個(gè)參考。
最后感謝李斌在本文整理過(guò)程中的幫助!
參考文獻(xiàn)
1. TMS320DM36x Digital Media System-on-Chip (DMSoC) ARM Subsystem User's Guide Literature Number: SPRUFG5A
2. TMS320DM368 datasheet Literature Number: SPRS668C
總結(jié)
以上是生活随笔為你收集整理的DM365视频处理流程/DM368 NAND Flash启动揭秘的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Activity的四种启动模式-图文并茂
- 下一篇: 阿里UX矢量图标库–最强大的矢量图标库(