移植u-boot2009.08到OK2440V3開發(fā)板(1)---方向與方法開發(fā)板到了之后,用的是板子自帶的bootloader、linux內(nèi)核和文件系統(tǒng),在上面跑了幾個(gè)小程序知道流程和方法后,就想著用自已移植的這些東西了,因?yàn)榧热灰愕讓拥臇|西,我想這些東西還是要學(xué)會的。 剛開始躊躇滿志,以為不會有什么困難,網(wǎng)上不都多得是文章嗎??蓪?shí)際上,下了N多資料,看了N多文章之后,下到flash中一運(yùn)行,串口控制臺中什么都沒 有,當(dāng)時(shí)真有點(diǎn)蒙了。其實(shí)不成功,倒還沒什么,關(guān)鍵是你想繼續(xù)努力的時(shí)候,卻沒有方向和方法,那真的才是又浪費(fèi)時(shí)間,又郁悶。 不過還得感謝網(wǎng)絡(luò),文章看多了,就知道哪些可以直接close,那些可以復(fù)制下來慢慢看(我通常都是一氣狂搜,一氣“另存為”,最后再集中在一起看)。三五天后,終于找到了方向和方法,而且在sdram中運(yùn)行,成功地在串口輸出里看到了u-boot啟動信息。 第一次學(xué)做u-boot移植,綜合別人的方法,總結(jié)歸納如下: 1. 先不去考慮nor/nand flash啟動,先讓u-boot在SDARM中成功運(yùn)行。 2. 把那個(gè)既經(jīng)典又簡單又very useful的調(diào)試方法用上,那就是在程序中需要的地方加上led燈指示。 (有時(shí)串口沒信息,一頭霧水,連自己的程序是否在運(yùn)行都不知道,這里在程序開頭加led的代碼,最合適不過了) 3. u-boot能在SDRAM中運(yùn)行后,先考慮nor flash中運(yùn)行(如果有nor flash的話),因?yàn)橹С謓or flash比支持nand flash改動少,較容易一些。SMDK2410里也是支持nor flash的,那里用的是AMD公司的。 4. 能在flash 中啟動后,增加nand支持,看是否能檢測到nand,并在u-boot中用些nand的命令驗(yàn)證驅(qū)動是否有問題。 5. 增加代碼,讓u-boot從nand啟動。 6. u-boot可是從nand啟動后,增加代碼,讓代碼能自動識別跳線的設(shè)置,從相應(yīng)的flash啟動。 以上6步完成之后,關(guān)于啟動方面的就完成了,如果有需要,再增加這個(gè)u-boot的其它功能,比如:網(wǎng)絡(luò)支持、USB支持等,這些部分如果自已的開發(fā)板和SMDK2410不同的話,也是要做移植的。 這個(gè)過程我正在進(jìn)行中,已進(jìn)行到第三步,前兩部的具體實(shí)現(xiàn)過程在后面的文章中寫出來,只為了自已以后用到的時(shí)候,有資料可查,不然忘了又得花時(shí)間,相當(dāng)于做筆記吧。 移植u-boot2009.08到OK2440V3開發(fā)板(2)---在SDRAM中運(yùn)行(2009-12-8 17:07)其實(shí)這篇日記早就該出爐了,只因?yàn)樵谶M(jìn)行下一步(nor flash驅(qū)動)的移植中,遇到了麻煩,很大的麻煩,所以也沒時(shí)間來寫這一篇日記。nor flash驅(qū)動還沒有搞定,自己花了太多的時(shí)間,又沒人指導(dǎo),身心疲憊,想先放一放,或者先跳過。于是現(xiàn)在來整理一下移植過程的第一步---u-boot 在SDRAM中運(yùn)行。 前一篇移植日記之所以把移植過程分那么多步,是因?yàn)檫@樣可以減少問題出現(xiàn)的范圍,也可以讓自己更清楚所有的移植是怎樣一步步做起來的。這一步是移植中最簡單的,也是最基本的,先這樣做可以為以后的移植搭好一個(gè)平臺和框架。 1.拷貝/board/samsung/目錄下smdk2410文件夾到/board/samsung/下,取名為ok2440v3;并修改ok2440v3目錄下的smdk2410.c文件的文件名為ok2440v3.c。(建立自己的開發(fā)板目錄) 2.拷貝/include/configs目錄下smdk2410.h,并重命名為ok2440v3.h(建立自己的開發(fā)板的配屬文件); 因?yàn)槲覀兪窃赟DRAM中運(yùn)行,所以在此文件中定義兩個(gè)宏,不拷貝代碼到ram中和不進(jìn)行底層初始化: #define CONFIG_SKIP_LOWLEVEL_INIT 1 #define CONFIG_SKIP_RELOCATE_UBOOT 1 3.修改頂層Makefile文件,在smdk2410_config后面添加ok2440v3_config,如下所示:(設(shè)置自己的開發(fā)板的編譯配置) # added by liweikui for supporting OK2440V3 ok2440v3_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t ok2440v3 samsung s3c24x0 4.修改頂層Makefile文件,在CROSS_COMPILE ?=后面添加自己的交叉編譯工具。(設(shè)置交叉編譯工具) CROSS_COMPILE ?= /usr/local/arm_across/4.3.2/bin/arm-linux- 5.修改/board/samsung/ok2440v3目錄下的Makefile文件中的COBJS,如下所示: COBJS := ok2440v3.o flash.o 上面這幾步是很通用的了,到這里,就可以用下面兩條命令編譯,測試一下是否可以生成最后的u-boot.bin文件: make ok2440v3_config make 成功生成u-boot.bin文件后,對于CPU為s3c2410,控制臺串口用的是串口0的開發(fā)板來說,應(yīng)當(dāng)就可以使用了。但對于s3c2440來說,運(yùn)行這個(gè)bin文件是沒有串口輸出的! ************************************ 原來,2440與2410的一個(gè)重要的區(qū)別就是,在相同的外部時(shí)鐘(12M)的情況下,默認(rèn)得到的內(nèi)部時(shí)鐘FCLK/HCLK/PCLK是不一樣的,而這些時(shí)鐘會影響到口串口的波特率。具體修改如下: 1.修改/cpu/arm920t/start.S中的相關(guān)部分: (1)先在相應(yīng)位置增加如下宏定義: # define LOCKTIME 0x4C000000 # define MPLLCON 0x4C000004 # define UPLLCON 0x4C000008 # define CAMDIVN 0x4C000018 (2) 修改禁止中斷部分,2440比2410的中斷多了幾位,相應(yīng)部分,修改如下: /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x7fff ldr r0, =INTSUBMSK str r1, [r0] # endif (3)中斷修改完后,新增下述兩個(gè)寄存器的配置: //locktime用來在正常運(yùn)行時(shí)更改時(shí)鐘的時(shí)候保護(hù)時(shí)鐘 ldr r0,=LOCKTIME mov r1,#0xffffff str r1,[r0] //清除攝像頭分頻寄存器值,這個(gè)值會影響HCLK ldr r0,=CAMDIVN mov r1,#0 str r1,[r0] (4)關(guān)于時(shí)鐘的初始化部分,把相應(yīng)部分替換為: //初始化時(shí)鐘,晶振為12MHz,主頻為405MHz /* FCLK:HCLK:PCLK = 1:4:8 */ ldr r0, =CLKDIVN mov r1, #5 str r1, [r0] //在2440的手冊中寫著若HDIVN不為0,則需要下面幾句 mrc p15, 0, r1, c1, c0, 0 //read ctrl register orr r1, r1, #0xc0000000 //Asynchronous mcr p15, 0, r1, c1, c0, 0 //write ctrl register //USB時(shí)鐘48MHz (56<<12)+(2<<4)+(2) ldr r0, =UPLLCON ldr r1, =0x00038022 str r1, [r0] //arm920t為5級流水線,延遲幾個(gè)周期,使指令生效 nop nop nop nop nop nop nop nop //寫MPLL使pll生效,405MHz,(127<<12)+(2<<4)+(1) ldr r0, =MPLLCON ldr r1, =0x0007f021 str r1, [r0] (注:上述的遇到CONFIG_S3C2410保持原樣,如果要u-boot能分辯2410與2440的話,定義CONFIG_S3C2440后,改的地方很多,為了抓住移植的關(guān)鍵部分,我暫沒有那樣做) 2.修改/board/samsung/ok2440v3目錄下ok2440v3.C文件中關(guān)于時(shí)鐘的部分,如下所示: #elif FCLK_SPEED==1 /* Fout = 405MHz FCLK:HCLK:PCLK = 1:4:8 */ #define M_MDIV 0x7f #define M_PDIV 0x2 #define M_SDIV 0x1 3.因?yàn)?440與2410對FCLK的計(jì)算公式不一樣,所以還要修改/cpu/arm920t/s3c24x0/speed.c文件中FCLK的計(jì)算: 把下面的部分: m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; return((CONFIG_SYS_CLK_FREQ * m) / (p << s)); 替換為: m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; if(pllreg == MPLL) return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); else return((CONFIG_SYS_CLK_FREQ * m) / (p << s)); 4.修改/cpu/arm920t/s3c24x0/speed.c中的 get_HCLK函數(shù)如下: /* return HCLK frequency */ ulong get_HCLK(void) { S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); //return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK()); return (get_FCLK()/4); //for s3c2440 1:4:8 !!! } (注:這里的修改采取了一個(gè)簡單的,但適應(yīng)性不好的改法,只用于FCLK:HCLK:PCLK = 1:4:8的情況,如果要完整修改的話,按2440的數(shù)據(jù)手冊,這里不能這么簡單處理。如何做,網(wǎng)上很多,可以找到) 到這里,關(guān)于串口的修改就結(jié)束了。說來不怕笑話,因?yàn)檫@個(gè)問題,我也被搞了兩天,一直沒串口輸出,問題不難,卻真的是一個(gè)時(shí)鐘頻率引發(fā)的血案啊,呵呵。。 好了,做完上面所有修改后,執(zhí)行make ok2440v3_config與make,生成u-boot.bin,下載到SDRAM中,就可以從串口看到信息了。 ************************************* 如果在實(shí)驗(yàn)中遇到了問題,可以用led燈來跟蹤的方法,這里,我附上針對OK2440V3開發(fā)板的點(diǎn)亮led燈的匯編代碼和C代碼: /* leds for testing and tracing ,GPF3-6 : LED0-3 */ #define GPFCON 0x56000050 #define GPFDAT 0x56000054 #define GPFUP 0x56000058 ldr r0,=GPFUP // 0:enable pull up ; 1:disable pull up ldr r1,=0xfffff87 //使能上拉F3-6 str r1,[r0] ldr r0,=GPFCON ldr r1,=0xd57f //將F3-6設(shè)為輸出口 str r1,[r0] ldr r0,=GPFDAT ldr r1,=0xf7 //點(diǎn)亮LED0 (不同的地方我們可以點(diǎn)亮不同的燈) str r1,[r0] /* end of leds testing */ /* leds test for ok2440v3 */ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); gpio->GPFCON = 0xd57f; //將F3-6設(shè)為輸出口 gpio->GPFUP = 0xfffff87; //使能上拉F3-6 gpio->GPFDAT = 0xe7; //再點(diǎn)亮LED1 (注:若要使用上述C語言的led測試程序,需包含頭文件 s3c2410.h) ******************************* 這里再總結(jié)一下,在這一移植過程中,我們要關(guān)注的有哪些文件: 1.兩個(gè)Makefile文件,頂層Makefile和自已的開發(fā)板下的Makefile; 2.自已的開發(fā)板下ok2440v3.c文件; 3.啟動后執(zhí)行的第一個(gè)文件,/cpu/arm920t/start.S; 4.C語言入口文件/lib_arm/board.c,start.S執(zhí)行完后跳到此文件執(zhí)行; 5.和時(shí)鐘計(jì)算相關(guān)的文件/cpu/arm920t/s3c24x0/speed.c 6.板級初始化/board/samsung/ok2440v3/ok2440v3.C文件 7.板級配置文件/include/configs/ok2440v3.h 移植u-boot2009.08到OK2440V3開發(fā)板(3)---nor flash啟動(2009-12-10 19:43)前面一篇移植關(guān)鍵在于串口輸出的部分,當(dāng)時(shí)花了我2,3天時(shí)間,我叫它“一個(gè)時(shí)鐘引發(fā)的慘案”,現(xiàn)在想起來,那還是小的,這篇日記要記錄的,整整花了我一個(gè)星期的時(shí)間!真的可以叫做“一個(gè)驅(qū)動引發(fā)的血案”了,呵呵。 本來如果只是支持從nor flash啟動倒是不難,u-boot的啟動過程中只用到了一個(gè)flash的初始化函數(shù)。如下所示: #ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */ display_flash_config (flash_init ()); #endif /* CONFIG_SYS_NO_FLASH */ 關(guān)鍵是,我沒有在linux下燒寫我這款nor flash的工具!我必須要切換到windows下才行,這太麻煩了,我就想在u-boot里把我這款nor flash的驅(qū)動搞定,包括保護(hù)、去保護(hù)、擦除、讀寫等,好讓u-boot啟動后能使用flash的命令,然后燒寫nor flash。這一想不要緊,在u-boot里找到的驅(qū)動程序有問題。為了解決這個(gè)問題,自己又不想放棄,“血案”就這樣發(fā)生了,呵呵。 不過一個(gè)星期后的痛苦掙扎后,問題總算解決了。(雖然問題不大,但對我這樣的新手來說,又沒人指導(dǎo),有時(shí)一個(gè)小問題真的會讓人郁悶透頂?。?br> ************************************* 下面先看如何在u-boot中支持nor flash的燒寫,我的開發(fā)板上的nor flash芯片是Intel的JS28F320(4MB)(1device=32blocks,1block=128MB)。為了縮小問題發(fā)生的范圍,我們還是先讓u-boot在SDRAM中運(yùn)行(仍然要定義那兩個(gè)宏定 義:不復(fù)制代碼到SDARM和不進(jìn)行底層初始化)。當(dāng)然,在SDRAM中運(yùn)行前,需要用別的初始化程序先初始化內(nèi)存才行。 下面的操作都是前一篇移植完成后的基礎(chǔ)上進(jìn)行的。 1. 把開發(fā)板的配置文件ok2440v3.h(/include/configs/ok2440v3.h)中關(guān)于flash的配置部分都刪掉,換成下面的配置: /*----------------------------------------------------------------------- * Physical Memory Map */ #define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ #define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */ #define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */ #define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ #define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 #define CONFIG_SYS_MONITOR_BASE TEXT_BASE #define FLASH_BASE0_PRELIM PHYS_FLASH_1 /*------------------------------------------------------------ * FLASH and environment organization */ #define CONFIG_SYS_FLASH_PROTECTION 1 #define CONFIG_SYS_MAX_FLASH_BANKS 1 /*max number of memory banks*/ #define CONFIG_SYS_FLASH_SIZE 0x00400000 /*4 MB*/ #define CONFIG_SYS_MAX_FLASH_SECT 32 /*max number of sectors on one chip*/ /*timeout values are in ticks*/ #define CONFIG_SYS_FLASH_ERASE_TOUT (2*CONFIG_SYS_HZ) /*Timeout for Flash Erase*/ #define CONFIG_SYS_FLASH_WRITE_TOUT (2*CONFIG_SYS_HZ) /*Timeout for Flash Write*/ #define CONFIG_ENV_IS_IN_FLASH 1 #define CONFIG_ENV_SIZE 0x20000 /*128KB*/ #define CONFIG_ENV_OFFSET 0x40000 2.把開發(fā)板目錄下flash.c文件替換成下面的/board/cmi/下面的flash.c文件,然后刪除這個(gè)write_short函數(shù)的申明和定 義、刪除write_buff函數(shù)。替換成下面的兩個(gè)函數(shù):(為了不占篇幅,我把這兩個(gè)函數(shù)單獨(dú)寫在名為<<Intel JS28F320 nor flash 的write_buff函數(shù)>>這篇日記中。 3. 修改flash.c文件中的一個(gè)宏定義: 把: #define FLASH_BLOCK_SIZE 0x00010000 改為: #define FLASH_BLOCK_SIZE 0x00020000 上述3步完成后,生新編譯,下載u-boot.bin文件到SDRAM中運(yùn)行,便可看到u-boot檢測到了我們的flash。用flinfo命令可以看 到具體的塊信息,還可以用flash的各種命令對flash進(jìn)行操作,從而實(shí)現(xiàn)這塊nor flash驅(qū)動的完全支持。燒寫當(dāng)然也是沒問題的了,把需要燒寫的文件下載到SDRAM中后,用cp.b命令就可以了。 下面大該分析一下這個(gè)驅(qū)動文件的函數(shù)調(diào)用,此flash.c文件中有如下幾個(gè)函數(shù): static ulong flash_get_size (vu_short *addr, flash_info_t *info); static void flash_get_offsets (ulong base, flash_info_t *info); static int write_word (flash_info_t *info, ulong dest, ushort data) unsigned long flash_init (void) void flash_print_info (flash_info_t *info) int flash_erase (flash_info_t *info, int s_first, int s_last) int flash_real_protect(flash_info_t *info, long sector, int prot) int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) 1.u-boot啟動只會用到flash.c文件中的flash_init函數(shù),正如上面所述; 2.以static修飾的3個(gè)函數(shù)只在flash.c文件中被調(diào)用; 3.最后面的4個(gè)函數(shù)會被/common/cmd_flash.c文件中的函數(shù)調(diào)用,以實(shí)現(xiàn)u-boot下的各種命令操作。 ************************************* 上面的操作做完之后,如果沒有問題,我們就可以考慮讓u-boot從nor flash啟動了。為了實(shí)現(xiàn)這個(gè)目的,有下面幾步操作: 1.注釋或刪除掉下面的兩個(gè)宏定義: //#define CONFIG_SKIP_LOWLEVEL_INIT 1 //#define CONFIG_SKIP_RELOCATE_UBOOT 1 2.修改開發(fā)板目錄下的lowlevel_init.S文件中SDARM刷新參數(shù)為: #define REFCNT 1258 /* period=7.8125us, HCLK=405/4 Mhz, (2048+1-7.8125*405/4) */ 重新編譯,設(shè)置好開發(fā)板上的跳線,下載到nor flash中,重啟開發(fā)板,串口控制臺看到u-boot啟動成功! **************************************** 后記: 也許,很多人覺得這篇文章的移植怎么會花了一個(gè)星期這么長時(shí)間,現(xiàn)在想來,我自己也不太相信,不過確是事實(shí)。那是哪里出錯(cuò)了呢,現(xiàn)特記錄下來,以提醒自己: 1. CONFIG_SYS_FLASH_ERASE_TOUT和 CONFIG_SYS_FLASH_WRITE_TOUT定義出錯(cuò)。首先我用的就是拷貝過來的參數(shù),不行,我又把它增大了一倍,有改善,便還是不行。原 因:不要把time out直接定義為以ms為單位的值,要定義為以“ticks“為單位的值,即次數(shù)。因?yàn)樵隍?qū)動中進(jìn)行比較時(shí),get_timer得到的值就是PWM4定時(shí) 器中的值經(jīng)過一些計(jì)數(shù)后得到的。 2. FLASH_BLOCK_SIZE定義錯(cuò),應(yīng)當(dāng)以字節(jié)為單位,是20000,而不是以半字為單位為10000。我之前一直以為,我的flash是16位位寬的,那就當(dāng)以半字為單位,其實(shí)不是這樣的。 3.刷新參數(shù)沒改正確,我之前都是用別人的值,因?yàn)閯e人的也是2440,后來不這樣想了,自已計(jì)算!從而解決問題!因?yàn)檫@個(gè)還和時(shí)鐘有關(guān)! 移植u-boot2009.08到OK2440V3開發(fā)板(4)---nand flash識別與操作(2009-12-13 20:06)出了問題是痛苦的,但是解決了問題又是讓人興奮的。摸爬滾打三四天后,我的u-boo終于可以正確識別nand flash了!也許就是這一次次,哪怕是一瞬間的興奮,才讓自己堅(jiān)持了下來。郁悶幾天又如何,呵呵。 正如此系列日記的第一篇所述,為了降低解決問題的難度,縮小問題問題出現(xiàn)的范圍,我們先在這篇日記中完成nand驅(qū)動支持這個(gè)功能,能在u-boot中對nand進(jìn)行各種命令操作,從nand啟動u-boot的功能在下篇日記中完成。 ********************************************************************************************** 為了支持nand,我們必須知道nand是如何與u-boot作用的,我們先來看這個(gè)版本中nand驅(qū)動框架。 網(wǎng)上看了很多的相關(guān)資料,都說nand驅(qū)動有兩種不同的實(shí)現(xiàn)流程和框架,取決于是否定義CONFIG_NAND_LEGACY,其實(shí)這個(gè)現(xiàn)象在u- boot2009.08這個(gè)版本中已經(jīng)不存在了。nand驅(qū)動現(xiàn)在用的就是和linux內(nèi)核一樣的MTD(內(nèi)存技術(shù)設(shè)備)架構(gòu),這個(gè)在u-boot根目錄 下有清楚的說明: The current NAND implementation is based on what is in recent Linux kernels. The old legacy implementation has been removed. If you have board code which used CONFIG_NAND_LEGACY, you'll need to convert to the current NAND interface for it to continue to work. 說來好笑,我為了弄清這個(gè)問題,盡然在網(wǎng)上到處確認(rèn),現(xiàn)在的nand驅(qū)動架構(gòu)是什么樣子,原來真的是舍近求遠(yuǎn)了,浪費(fèi)了些時(shí)間。這也是引發(fā)我寫<<自學(xué)嵌入式中的點(diǎn)點(diǎn)滴滴>>這篇日記的原因之一。 ***************************************************************************************** 我們先從u-boot啟動過程中,以s3c2410為例,怎樣調(diào)用到nand驅(qū)動這個(gè)角度來分析。還有另外一個(gè)角度,那就是在u-boot中執(zhí)行某一nand命令時(shí),從上到下到底發(fā)生了什么。 u-boot啟動到第二個(gè)階段后,在/cpu/arm920t/board.c這個(gè)文件中start_armboot函數(shù)里,有下面的代碼: #if defined(CONFIG_CMD_NAND) puts ("NAND: "); nand_init(); /* go init the NAND */ #endif 所以,我們只要定交了CONFIG_CMD_NAND這個(gè)宏,就會開始nand初始化。通過用KScope(Linux下的一個(gè)不錯(cuò)的IDE,可用來做代碼分析)來一步步地查看函數(shù)執(zhí)行過程,得出下面的nand執(zhí)行流程: 1./cpu/arm920t/board.c文件中的start_armboot函數(shù)調(diào)用/drivers/mtd/nand/nand.c文件中的nand_init函數(shù); 2.nand_init調(diào)用同文件下的nand_init_chip函數(shù); 3.nand_init_chip函數(shù)調(diào)用/drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函數(shù),然后再調(diào)用/drivers/mtd/nand/nand_base.c函數(shù)中的nand_scan函數(shù); 4.s3c2410_nand.c就是我們做移植需要實(shí)現(xiàn)的文件,是與具體的硬件密切相關(guān)的。 5.nand_scan函數(shù)會調(diào)用同文件下的nand_scan_ident等函數(shù)。 從這里我們得知,我們要把nand移植到2440上,就要修改s3c2410_nand.c這個(gè)文件!因?yàn)閷and flash的操作,實(shí)際上就是對nand控制器的操作,而2440的nand控制器和2410相比,有很大的不同!我們的修改工作量主要也是在這里。 s3c2410與s3c2440具體有什么區(qū)別,請看我的另一篇日記<<s3c2410與s3c2440的全方位對比>> ********************************************************************************* 下一步就是根據(jù)s3c2440的手冊中nand控制器部分修改s3c2410_nand.c文件,我們在同目錄下(/drivers/mtd/nand /)復(fù)制此文件,并重命名為s3c2440_nand.c,下面我們來對s3c2410_nand.c文件進(jìn)行修改: (這里我使用的是網(wǎng)上別人的函數(shù),文末有說明) 1.修改s3c2410_nand.c文件中NAND Flash控制器的相關(guān)定義: (針對S3C2440 NAND Flash控制器的不同來重新定義一些寄存器,把原文件中對s3c2410 nand寄存器的定義刪除,重新定義如下) #define NF_BASE 0x4e000000 #define NFCONF __REGi(NF_BASE + 0x0) #define NFCONT __REGi(NF_BASE + 0x4) #define NFCMD __REGb(NF_BASE + 0x8) #define NFADDR __REGb(NF_BASE + 0xc) #define NFDATA __REGb(NF_BASE + 0x10) #define NFMECCD0 __REGi(NF_BASE + 0x14) #define NFMECCD1 __REGi(NF_BASE + 0x18) #define NFSECCD __REGi(NF_BASE + 0x1C) #define NFSTAT __REGb(NF_BASE + 0x20) #define NFSTAT0 __REGi(NF_BASE + 0x24) #define NFSTAT1 __REGi(NF_BASE + 0x28) #define NFMECC0 __REGi(NF_BASE + 0x2C) #define NFMECC1 __REGi(NF_BASE + 0x30) #define NFSECC __REGi(NF_BASE + 0x34) #define NFSBLK __REGi(NF_BASE + 0x38) #define NFEBLK __REGi(NF_BASE + 0x3c) #define S3C2440_NFCONT_nCE (1<<1) #define S3C2440_ADDR_NALE 0x0c #define S3C2440_ADDR_NCLE 0x08 2.增加一個(gè)全局變量:ulong IO_ADDR_W = NF_BASE; 3.修改s3c2410_nand.c文件的s3c2410_hwcontrol函數(shù)和board_nand_init函數(shù): (為了不在這里占篇幅,具體修改的內(nèi)容請看我的另一篇日記<<s3c2440的hwcontrol和board_nand_init函數(shù)>>) 4.除了以上對3c2410_nand.c的文件進(jìn)行修改之外,我們還要在開發(fā)板的配置文件中(ok2440v3.h)定義支持nand的相關(guān)的宏: /* Command line configuration. */ ...... #define CONFIG_CMD_NAND #define CONFIG_CMDLINE_EDITING #ifdef CONFIG_CMDLINE_EDITING #undef CONFIG_AUTO_COMPLETE #else #define CONFIG_AUTO_COMPLETE #endif /* NAND flash settings */ #if defined(CONFIG_CMD_NAND) #define CONFIG_NAND_BASE 0x4E000000 #define CONFIG_MAX_NAND_DEVICE 1 #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #define NAND_SAMSUNG_LP_OPTIONS 1 /*注意,這個(gè)定義很重要,因?yàn)槲覀冇玫氖谴髩Knand!!我就是因?yàn)闆]定義這里卡了較長時(shí)間 */ #undef CONFIG_ENV_IS_IN_FLASH #define CONFIG_ENV_IS_IN_NAND 1 /* 環(huán)境變量的保存位置 */ #define CONFIG_ENV_SIZE 0x20000 #define CONFIG_ENV_OFFSET 0x40000 #endif 5.我們要把新建立的這個(gè)文件編譯進(jìn)去,所以要修改相同目錄(/drivers/mtd/nand/)下的Makefile文件: 在相應(yīng)位置加入: COBJS-y += s3c2440_nand.o COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o 6.我們?yōu)榱嗽赟DRAM中調(diào)試,定義上下面的兩個(gè)宏定義,下載到SDRAM中運(yùn)行: #define CONFIG_SKIP_LOWLEVEL_INIT 1 #define CONFIG_SKIP_RELOCATE_UBOOT 1 7.編譯,下載到SDRAM中運(yùn)行,成功檢測到nand: U-Boot 2009.08 (12栽? 13 2009 - 18:03:40) DRAM: 64 MB Flash: 4 MB NAND: 128 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial OK2440V3 # OK2440V3 # nand info Device 0: NAND 128MiB 3,3V 8-bit, sector size 128 KiB OK2440V3 # 進(jìn)行nand命令的基本操作,nand info、nand dump、nand read、nand write,都能夠成功! ********************************************************************************** 下面列一下,此篇移植中,我們需關(guān)注的文件: /cpu/arm920t/board.c /drivers/mtd/nand/nand.c /drivers/mtd/nand/s3c2410_nand.c /drivers/mtd/nand/nand_base.c /driver/mtd/nand/Makefile /include/configs/ok2440v3.h 移植u-boot2009.08到OK2440V3開發(fā)板(5)---nand flash啟動(2009-12-16 21:35)在完成前面的nand flash識別與操作后(在nor flash中運(yùn)行,檢測到nand外設(shè)并可對其用u-boot命令進(jìn)行操作),讓u-boot從nand中啟動,就相對比較簡單了。當(dāng)然,這個(gè)簡單的前提 是是,有開發(fā)板自帶的bootloader中的nand啟動代碼可參考。 移植的重要關(guān)鍵部分是是代碼的拷貝,從nand拷貝到sdram。從編程的角度看,nor flash是存儲設(shè)備,而nand是I/O外設(shè),對它們的底層操作有本質(zhì)的不同。u-boot中對ARM的支持部分,沒有支持nand啟動的代碼,只有 nor flash的,拷貝u-boot的那部分代碼只適用于nor flash,不適用于nand。 1. 刪除或注釋掉原來的 relocate 部分,用飛凌公司提供的bootloader中的nand啟動相關(guān)部分來替代。由于這個(gè)bootloader用的是匯編語言環(huán)境是armasm的,不是 GUN ARM的,所以要進(jìn)行一些語法上的轉(zhuǎn)換。轉(zhuǎn)換之后的結(jié)果如下: /**********************************************************/ //如果是從nand啟動,到這里執(zhí)行 //將程序從nandflash拷貝到sdram #ifndef CONFIG_SKIP_RELOCATE_UBOOT #define NFCONF 0x4E000000 relocate_nand: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup mov r5, #NFCONF //set timing value ldr r0, =(7<<12)|(7<<8)|(7<<4) str r0, [r5] //enable control ldr r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0) str r0, [r5, #4] bl ReadNandID mov r6, #0 ldr r0, =0xecF1 cmp r5, r0 beq 1f ldr r0, =0xec76 cmp r5, r0 beq 1f mov r6, #1 1: bl ReadNandStatus mov r8, #0 ldr r9, =_start mov r10, #128 //u-boot 256k,128頁 --這里原來是32!! 2: ands r0, r8, #0x3f //如果是第一頁,則檢測壞塊 bne 3f mov r0, r8 bl CheckBadBlk cmp r0, #0 addne r8, r8, #64 //每塊的頁數(shù) addne r10,r10,#64 //+081010 feiling bne 4f 3: mov r0, r8 mov r1, r9 bl ReadNandPage add r9, r9, #2048 //每頁的字節(jié)數(shù) add r8, r8, #1 //頁數(shù)+1 4: cmp r8, r10 //要拷貝的頁數(shù) 081010 pht:#32->r10 bcc 2b mov r5, #NFCONF //DsNandFlash ldr r0, [r5, #4] bic r0, r0, #1 str r0, [r5, #4] #endif (注意上面的mov r10, #128 那一句,把拷貝的頁數(shù)改大一些,原來是32。我之前,怎么都沒調(diào)通,就是因?yàn)檫@里,因?yàn)閡-boot編譯出來比飛凌的bootloader大多了) 2. 上述代碼中用到的幾個(gè)子函數(shù)ReadNandID、ReadNandStatu、 WaitNandBusy、CheckBadBlk、ReadNandPage也一同拷貝過來,并進(jìn)行簡單的一些語法修改。 3. s3c2440的兩種啟動方式,nor 和 nand 啟動在原理上不些不同,若從nor 啟動,就是直接從nor flash的0地址開始執(zhí)行(flash 映射到bank0),可以執(zhí)行flash的內(nèi)部的任意地址的內(nèi)容。而從nand啟動,是在運(yùn)行之前,由CPU自動地拷貝nand的前4K的內(nèi)容到內(nèi)部的 4K RAM中,再從內(nèi)部的這個(gè)RAM中的0地址開始執(zhí)行。所以我們必須保證在跳到SDARM運(yùn)行之前的所有代碼,都在前4K范圍之內(nèi)。 而通過查看編譯后u-boot根目錄下的u-boot.map文件可知,lowlevel_init.o并不在 前4K的范圍: .text 0x33f948e0 0x9c board/samsung/ok2440v3/libok2440v3.a(lowlevel_init.o) 0x33f948e4 lowlevel_init // (u-boot的起始地址為0x33f80000) 所以我們要修改/cpu/arm920t/u-boot.lds文件,使lowlevel_init.o在前4K范圍: .text : { cpu/arm920t/start.o (.text) board/samsung/ok2440v3/lowlevel_init.o (.text) *(.text) } 修改后,重新編譯,再次查看,已在前4K,如下: board/samsung/ok2440v3/lowlevel_init.o(.text) .text 0x33f80700 0x64 board/samsung/ok2440v3/lowlevel_init.o 0x33f80704 lowlevel_init 把編譯之后的u-boot.bin文件下載到nand 中,重新啟動,串口控制臺得出正確的啟動信息,完成。 OK2440V3 # reset resetting ... U-Boot 2009.08 (12栽? 16 2009 - 20:30:08) DRAM: 64 MB ## Unknown FLASH on Bank 0: ID 0xffff, Size = 0x00000000 = 0 MB Flash: 0 kB NAND: 128 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial OK2440V3 # 后記:這篇移植就兩個(gè)重點(diǎn),一是修改復(fù)制u-boot時(shí)要復(fù)制nand的頁數(shù),一是lowlevel_init.o的連接位置保證在前4K。 |
|
|