小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

移植u-boot2009.08到OK2440V3開發(fā)板

 rookie 2012-12-15

移植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。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多