copy_from_nand函數簡介:
函數將會把nand flash中的uboot二進位程式鏡像拷貝到記憶體中,通常這一步出現問題,uboot是不可能引導起來的,串口也不會有資訊吐出(當然啦,因為uboot不在記憶體,如何執行啊)
程式碼分析:
1.先貼函數代碼,在後面再分析,copy_from_nand函數的代碼我們可以在cpu/s3c64xx/start.S的278行看到,:
圖(1)
273~277行:解釋很給力,273行告訴你了這個函數的功能就是把nand flash中存放的uboot鏡像檔案拷貝到記憶體中,然後再到記憶體中去執行uboot,這樣我們的uboot就可以在記憶體中運行起來了。274行告訴我們r0是會被比較的大小。293行把0x0c000000裡面的值賦給r0了,我們要比較拷貝到記憶體的uboot和steppingstone裡面是否一樣啊?所以我們要比較一下咯(295和297行)
288行:copy_uboot_to_ram這個函數是在C語言裡面寫的,C語言的程式在編譯器編譯的時候肯定會有出入棧的操作,會用到sp指標,所以我們在進入這個函數之前是必須設定sp的,所以288行前的不解釋了。我們直接進入這個copy_uboot_to_ram函數吧:
圖(2)
這個函數的實現在cpu/s3c64xx/nand_cp.c的133行,注意的是這個函數必須在整個uboot.bin檔案的前4KB,所以我們看到u-boot.lds中會把nand_cp.o連結到uboot二進位檔案靠前的位置
139~148行:主要想做的事情就是判斷我們的nand flash是大頁得還是小頁的,現在主流的的nand flash有512頁和2048頁兩種,在後續的代碼操作中有區別,所以在進行nand操作前,必須先判斷出是大頁還是小頁。139行是在使能晶片,代碼是(NFCONT_REG &= ~(1 << 1)),即會把0x70200004這個地址的[1]位清零,那麼為什麼清零[1]位就能夠使能nand flash晶片了呢,我們看下s3c6410 datasheet才能夠明白:
圖(3)
我們看到圖3中的[1]位為0的含義是讓Xm0CSn2變成低電平,因為我們的nand flash是接在SRAM2上的,
當Xm0CSn2為低電平時,將能訪問我們的nand flash晶片了。
140行:在給nand_flash發送命令,發送的值為0x90,含義是讀取晶片的ID等廠商資訊,話說對nand flash的控制都是這個套路,因為這就是硬體協議,先使能晶片->發送命令->發送地址序列->讀或寫資料寄存器->判斷準備就緒狀態->禁止晶片,這是對nand flash操作的大體過程,根據發送命令的不同還有些區別。我們這次發送的是0x90,代表讀取ID資訊。發送命令的含義通過讀取你nand flash datasheet來查看,你需要看你的nand flash晶片是哪個廠家生產的,下載它的datasheet,如:
圖(4)
你會發現圖(2)在發送命令後,會讀兩次寄存器。這是因為我們發送完0x90,nand flash會返回5次(好像)值給我們,我們需要的值是第二次返回的值,接著148行判斷是否id大於0x80,大於的話就是大頁2048位元組的。我的晶片是K9F84G08U0B,是大頁的,所以這個讀出來的值是大於0x80的;
155行:拷貝功能主函數,CFG_PHY_UBOOT_BASE第一個代表要拷貝到記憶體的地址(0x57e00000),第二個參數0x3c000代表要從nand flash中拷貝的大小,我們進入這個函數:
圖(5)
圖(5)直接看126行,這個迴圈會執行0x3c000>>page_shift次,如果是9代表除以512,如果是11代表除以2048,這下明白這個for迴圈的意思了吧,nand flash硬體一次會讀取一個頁的大小給我們,那麼我們就進入127行的讀一頁吧,注意會讀到buf中,buf可就是我們指定的0x57e00000哦:
圖(6)
圖6函數會讀一頁的資料到buf中,即記憶體中。然後一直讀0x3c000/512(2048)次,看你是大頁還是小頁nand,我的是大頁。
圖6的85行使能晶片,前面已經說過,87行發送讀命令,是0x0,你可以查看圖(4),發送讀之後,我們就要開始向地址寄存器中寫一些地址,告訴nand flash我們要從什麼地方開始讀資料,:
圖(7)
看圖(7),我們知道我們要寫5次地址來確認我們要從nand flash中讀的內容,第一次是列地址,第二次也是,這是因為如果只有1次,那麼8位最大表示256,而一列的大小是2K,所以需要有兩個列地址來代表。那麼我們一共有256K頁,所以需要3次8位的行地址來代表我們要讀的是哪行,其實具體的還要看你的nand flash datasheet來決定如何給定地址清單。
圖6的102行,是在迴圈判斷是否是否已經準備好了,如果準備好了,我們才能再105行把這一整頁得內容讀到buf裡面,注意看是從那個寄存器讀取的哦,NF_DATA8_REG(nand flash資料寄存器);
109行禁止晶片,然後回到圖(5)的nandll_read_blocks繼續讀下一頁,直到讀了0x3c000/page_shift個頁為止,正好是192K,uboot的大小,並放到了buf中(0x57e00000記憶體)。
好了,分析完了
感謝網友的這篇部落格,對Uboot NandFlash的啟動過程進行了詳細的分析,推薦給大 家,原文連結 http://hi.baidu.com/__eabi/blog/item/2bb8fd38f9904cadd1a2d352.html