OK6410 tftp下載內核、文件系統以及nand flash地址相關整理、總結


        飛凌官方提供了一鍵下載燒寫linux的方式,相對來說比較方便,但是對於開發來說不夠靈活,因此這篇文章把tftp相關的點介紹一下,整理下其中遇到的一些問題。

         一鍵燒寫本質上是啟動位於SD卡中的Uboot,通過uboot讀取sd卡中的文件到SRAM最后通過nand指令實現一鍵燒寫,這一塊可以參考飛凌提供的uboot源碼中include\configs 中的smdk6410.h 的529行,代碼如下:

代碼1:

#elif defined(FORLINX_BOOT_SD)
#define FORLINX_DEBUG
#define CONFIG_MMC    1
#define CONFIG_LCD
#define CONFIG_BOOT_MOVINAND
#define CFG_ENV_IS_IN_MOVINAND

#define CONFIG_BOOTCOMMAND  "nand led-start;nand erase  ;fatload mmc 0:1 0x50008000 u-boot.bin;nand write.uboot 0x50008000 0 0x200000;fatload mmc 0:1 0x50008000 zImage;nand write.e    0x50008000 0x200000 0x500000; fatload mmc 0:1 0x50008000 rootfs.yaffs2; nand write.yaffs2 0x50008000 0x00700000 $filesize;  nand  beep; nand led-end"

        從這段代碼代碼可以看出,uboot中通過宏定義的方式,當定義為FORLINX_BOOT_SD 式通過對相應配置相應的環境變量完成特定的操作,其中定義CONFIG_BOOTCOMMAND 后就可以自動進行nand的查處,從sd卡加載uboot等,這段代碼內容稍后繼續分析。

 

下面說一下tftp和地址相關的知識總結

        tftp是指通過tftp協議通過網絡的方式進行文件傳輸,需要說明的是ok6410的出廠uboot是不支持網絡的,這也就意味着nfs根文件系統以及通過tftp下載內核等都無法操作,其實解決這個問題也很簡單,只需要替換網卡相關的文件就可以了,改動不是很大,這個可以找到很多資料,這里不再贅述。不過飛凌在12年9月的更新光盤中已經做了更新,uboot已經支持網絡操作了,查一下源碼也就是改了那幾個文件,因此可以下載燒寫最新版uboot。

        在進行tftp的操作時最開始可能容易搞混的就是燒寫內核啥的應該燒寫到哪一個地址去,最開始也有點混,比如有人的博客里是tftp c0008000 zImage 這個地址是c0008000,國嵌的視頻教程中是c0800000,各不相同,沒看到具體的敘述,而在通過usb等方式中通過usb傳送的地址是50008000,因此可能會存在混亂,因此覺得有必要在博客中總結一下。關於地址空間的分配首先還需要看一下芯片手冊。芯片手冊中關於地址空間的安排如圖所示。

image

        有一點需要說明的是,圖中的地址空間是針對通過地址總線與數據總線進行操作的設備的,通過不同的片選信號來確定對應的地址,所以可以通過圖中查表可以確定ok6410的256M RAM的地址范圍為0x50000000-0x5FFFFFFF 256M的地址空間,因此通過tftp下載到0x50008000也就是加載到RAM中(向后偏移了32K的地址,稍后在介紹)。到這兒對於0x50008000這個地址的由來就初步了解了。

再來看看很多資料中都提到的0xc0008000這個地址,smdk6410.h這個文件的501行可以找到這部分配置:

代碼2

//uboot-2M ,zImage-5M ,FS-200M,user-other
#define CFG_NAND_ERASE_LEN  0xCF00000 //200MB

#if defined(FORLINX_BOOT_NAND)
#define CONFIG_BOOT_NAND
#define CFG_ENV_IS_IN_NAND
//#define CFG_NAND_LARGEPAGE_SAVEENV
//#define CFG_NAND_FLASH_BBT
#define CONFIG_BOOTCOMMAND    "nand read 0xc0008000 0x200000 0x500000;bootm 0xc0008000"

        這部分定義了nand flash的地址空間划分和啟動的地址:bootm 0xc0008000,也就是說是從內存中的這個地址啟動內核的,但問題是在上圖的地址划分中地址最大值也只到0x6FFFFFFF,0xc0008000這個地址是什么地方呢?一樣從源碼入手,繼續找!

同樣從smdk6410.h這個文件的452行可以找到這部分配置。

代碼3

/* base address for uboot */
#ifdef CONFIG_ENABLE_MMU
#define CFG_UBOOT_BASE        TEXT_BASE
#define CFG_PHY_UBOOT_BASE    (MEMORY_BASE_ADDRESS + (TEXT_BASE - 0xC0000000))
#else
#define CFG_UBOOT_BASE        TEXT_BASE
#define CFG_PHY_UBOOT_BASE    TEXT_BASE
#endif

        看了這段代碼就明白了,在使能了MMU之后,這段代碼相當於對地址做了一個重映射,經過(MEMORY_BASE_ADDRESS + (TEXT_BASE - 0xC0000000))計算后,因為MEMORY_BASE_ADDRESS  為0x50000000(可以在文件開始找到定義)所以經過這樣的一個計算,0xc0008000就是0x5000c000。而0xc0008000是內核啟動的起始虛擬地址,因此需要做這樣的一個映射來和內核對應。

        到這兒可能很多人和我當初有一樣的疑惑,那就是如果tftp燒寫文件系統應該燒寫到哪一個地址去呢?在回到上面的地址圖表,在最開始我就說過,這個表是針對使用地址總線與數據總線操作的設備而言,因此對於NOR flash、SRAM、DRAM等都是可以直接尋址讀寫的,而對於Nand Flash,可以參考下電路圖,使用的是8個IO進行操作,右Nand控制器彎沉相關的操作,因此是沒有一個絕對的地址的。需喲啊注意圖表中的黃色框部分,One Nand並不是普通Nand Flash,區別就在於這種Nand是和NOR、SRAM一樣的通過地址總線、數據總線進行操作的方式,因此它是有地址的,對於板子所用的Nand Flash來說只有偏移地址,沒有絕對地址。

        到這里,對於tftp下載內核、文件系統的相關操作應該清楚了,具體地址其實看看uboot源碼就清楚了,可以參考代碼1中的這部分:

#define CONFIG_BOOTCOMMAND  "nand led-start;nand erase  ;fatload mmc 0:1 0x50008000 u-boot.bin;nand write.uboot 0x50008000 0 0x200000;fatload mmc 0:1 0x50008000 zImage;nand write.e    0x50008000 0x200000 0x500000; fatload mmc 0:1 0x50008000 rootfs.yaffs2; nand write.yaffs2 0x50008000 0x00700000 $filesize;  nand  beep; nand led-end"

如果通過sd卡啟動時跳過自動操作進入手動選擇操作的話就應該有印象,可以單獨選擇燒寫某一個文件,例如單獨燒寫文件系統,操作如下圖所示:

SNAGHTML1ac3bff

那么通過找到對應的命令源碼也是可以的,源碼位於common/mian.c 343行:

void arm_USBfuse(void)
{
    unsigned char select;
    while(1)
    {
        printf("\n##### Select the fuction #####\n");
        printf("[1] Flash u-boot\n");
        printf("[2] Flash kernel\n");    
        printf("[3] Flash system\n");        
        printf("[4] Exit\n");
        printf("Enter your Selection:");
    
        select = getc();
        printf("%c\n", select >= ' ' && select <= 127 ? select : ' ');    
void arm_sdfuse(void)
{
    unsigned char select;
    while(1)
    {
        printf("\n##### flash from SDcard  #####\n");
        printf("\n##### Select the fuction #####\n");
        printf("[1] Flash all image\n");
        printf("[2] Flash u-boot\n");
        printf("[3] Flash kernel\n");
        printf("[4] Flash system\n");            
        printf("[5] Exit\n");
        printf("Enter your Selection:");
    
        select = getc();
        printf("%c\n", select >= ' ' && select <= 127 ? select : ' ');    
    
        switch(select) 
        {
            case '1':
                ExecuteCmd("nand erase");
                ExecuteCmd("fatload mmc 0:1 50008000 u-boot.bin");
                ExecuteCmd("nand write.uboot 50008000 0 200000");
                ExecuteCmd("fatload mmc 0:1 50008000 zImage");
                ExecuteCmd("nand write.e 50008000 200000 500000");
                ExecuteCmd("fatload mmc 0:1 50008000 rootfs.yaffs2");
                ExecuteCmd("nand write.yaffs2 50008000 700000 $filesize");
                break;
            
            case '2':
                ExecuteCmd("nand erase 0 200000");
                ExecuteCmd("fatload mmc 0:1 50008000 u-boot.bin");
                ExecuteCmd("nand write.uboot 50008000 0 200000");
                break;
                    
            case '3':
                ExecuteCmd("nand erase 200000 500000");
                ExecuteCmd("fatload mmc 0:1 50008000 zImage");
                ExecuteCmd("nand write.e 50008000 200000 500000");
                break;

            case '4':
                ExecuteCmd("nand erase 700000");
                ExecuteCmd("fatload mmc 0:1 50008000 rootfs.yaffs2");
                ExecuteCmd("nand write.yaffs2 50008000 700000 $filesize");
                break;
            case '5':
                return;
            default:
                break;
        }
    }
}

通過tftp單獨燒寫內核或者文件系統時只需要參考一鍵燒寫的命令燒寫到對應的nand 偏移地址即可。

 

好了,寫了那么多,就是想把這中間原由寫清楚,而不是簡單告訴大家怎樣做就完事了,授人以魚不如授人以漁。

轉載請注明出處 http://emouse.cnblogs.com/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM