3.移植uboot-使板卡支持nor、nand

来源:https://www.cnblogs.com/lifexy/archive/2018/01/08/8243972.html
-Advertisement-
Play Games

在上一章,我們添加了nor,nand啟動後,uboot啟動出如下圖所示: 上面的Flash: *** failed *** 是屬於uboot第二階段函數board_init_r()里的代碼, 代碼如下所示(位於arch/arm/lib/board.c): 從上面代碼看出, board_init_r( ...


         

上面的Flash: *** failed *** 是屬於uboot第二階段函數board_init_r()里的代碼, 代碼如下所示(位於arch/arm/lib/board.c):

/*第二階段*/
void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
     ... ...
  puts("Flash: ");                        //列印flash:
  flash_size = flash_init();                    //初始化nor_flash
  if (flash_size > 0)
  {
       ... ...
       print_size(flash_size, "\n");            //列印nor_flash的大小
  }
  else
  {
    puts(failed);                //列印數組failed[]="*** failed ***\n";
    hang();                        //進入while中,並列印: ### ERROR ### Please RESET the board ###     
  }
#if defined(CONFIG_CMD_NAND)
       puts("NAND:  ");                                      //列印NAND:
       nand_init();                                               //初始化nand_flah
... ...
}

從上面代碼看出, board_init_r()會來初始化nor,由於新的uboot不支持nor,所以flash_init()初始失敗,然後列印一串錯誤代碼後,等待複位.

由於2440在nand啟動時,會自動裝載nand的前4k內容,所以不支持norflash,因為nor的前4k內容被nand占用.

所以修改上面代碼,避免nand啟動一直卡住,將:

else
{
  puts(failed);                //列印數組failed[]="*** failed ***\n";
  hang();                        //進入while中,並列印: ### ERROR ### Please RESET the board ###     
}

改為:

else
{
  puts("0  KB\r\n");                //列印0 KB
}

 


1.接下來,下章便來修改代碼,使uboot支持讀寫norflash

1.1首先在include/common.h中添加:

#define DEBUG     //調試模式

然後使用nor啟動新的uboot,列印出調試信息:

 

列印出norflash的廠家ID=0xC2,設備ID=0x2249,顯然uboot匹配讀出的ID沒有成功.

搜索JEDEC PROBE欄位,找到位於board_init_r()->flash_init()->flash_detect_legacy():

 

 

如上圖所示,該函數會進入board_init_r()->flash_init()->flash_detect_legacy()->jedec_flash_match(),裡面會通過兩個ID來匹配jedec_table[].

 

1.2接下來向jedec_table[]里添加norflash:MT29LV160DB(位於drivers/mtd/jedec_flash.c)

代碼如下:

     /*MX29LV160DB*/
       {
       .mfr_id         = (u16)MX_MANUFACT,        //廠家ID0x00C200C2 (讀nor,便是0xc2)
       .dev_id         = 0x2249,                          //設備ID
       .name           = "MXIC MX29LV160DB",
       .uaddr          = {
           [1] = MTD_UADDR_0x0555_0x02AA /* 數組[1]表示是16位nor,解鎖地址為:0x555,0x2AA */
        },
       .DevSize        = SIZE_2MiB,
       .CmdSet         = P_ID_AMD_STD,
       .NumEraseRegions= 4,                      //4種不同的扇區規格
       .regions        = {
       ERASEINFO(16*1024, 1),
       ERASEINFO(8*1024, 2),
       ERASEINFO(32*1024, 1),
       ERASEINFO(64*1024, 31),
                          }
           },

 

重新燒寫看列印信息,出現這麼一段ERROR

ERROR:too many flash sectors

說flash的扇區太多了,搜索找到位於drivers/mtd/jedec_flash.c中:

 

顯然是CONFIG_SYS_MAX_FLASH_SECT巨集小於我們flash的扇區,所以列印ERROR。

所以修改CONFIG_SYS_MAX_FLASH_SECT巨集定義(位於include/configs/smdk2440.h),並去掉之前定義的DEBUG調試巨集(位於include/common.h)

1.3然後重新燒寫

輸入flinfo命令(flash info),就能查看flash的信息了:

 

然後通過uboot命令,檢測nor的讀寫是否正確:

protect off all 
erase 80000 +7ffff              
cp.b 30000000 80000 1000             //燒寫在另一個位置
cmp.b 30000000 80000 1000              //比較,是否讀寫正確

2.接下來繼續修改代碼,使uboot支持NandFlash

2410的NandFlash位於drivers/mtd/nand/s3c2410_nand.c

2.1 首先複製s3c2410_nand.c,改為s3c2440_nand.c

Makefile,如下圖所示:

 

 

2.2 在上一章分析過CONFIG_NAND_S3C2410巨集,位於include/configs/smdk2440.h:

 

如上圖所示,其中CONFIG_CMD_NAND巨集:表示uboot是否支持nand,在上章里,我們把它屏蔽了,接下來便取消屏蔽CONFIG_CMD_NAND巨集。

 

2.3繼續添加對CONFIG_NAND_S3C2440巨集的支持,將:

#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE  1
#define CONFIG_SYS_NAND_BASE              0x4E000000
#endif

改為:

#ifdef CONFIG_CMD_NAND

 
#ifdef CONFIG_S3C2410          
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else                                                                   // CONFIG_S3C2440      
#define CONFIG_NAND_S3C2440    
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif

#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_SYS_NAND_BASE            0x4E000000
#endif

由於smdk2410.h中定義的是CONFIG_S3C2410,而smdk2440.h中定義的是CONFIG_S3C2440,所以便會根據上面的#ifdef來動態定義巨集

 

2.4 然後來看看nand的流程(和linux的nand驅動有很多相似的地方):

1)uboot重定位後進入第二階段board_init_r():

void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
  ... ...
#if defined(CONFIG_CMD_NAND)                      //需要定義CONFIG_CMD_NAND巨集
       puts("NAND:  ");
       nand_init();            /* go init the NAND */
#endif
 ... ...
}

 

2)進入nand_init():

void nand_init(void)
{
... ...
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)      //在2.3小節里,該巨集為1
nand_init_chip(i);                     
printf("%lu MiB\n", total_nand_size / 1024);
... ...
}

 

3)進入nand_init()->nand_init_chip(0):

static void nand_init_chip(int i)
{
    struct mtd_info *mtd = &nand_info[i];      //mtd_info屬於軟體的一部分,實現用戶層讀寫等操作
    struct nand_chip *nand = &nand_chip[i];     //屬於底層,保存對nand的硬體相關操作,它是mtd_info結構體的priv私有成員
    ulong base_addr = base_address[i];           //獲取nand寄存器基地址,等於0x4E000000
    int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;

    if (maxchips < 1)
           maxchips = 1;

    mtd->priv = nand;     //設置私有成員nand_chip
    ... ...
    if (board_nand_init(nand))                   //位於s3c2440_nand.c,該函數會設置nand_chip結構體的成員
           return;

    if (nand_scan(mtd, maxchips)) //通過mtd->priv來開啟nand片選,來獲取nand的型號,類型等.並填充mtd結構體下其它的成員.
           return;

    nand_register(i);     //註冊nand,使uboot支持對nand的讀寫操作
}

這個nand_chip結構體和我們之前學的linux下的nand驅動章節里的nand_chip一摸一樣,流程也非常相似.

 由於在2.1小節里,該函數所在的文件s3c2440_nand.c是從s3c2410_nand.c複製過來的,所以接下來便修改s3c2440_nand.c (位於drivers/mtd/nand目錄下)

 

2.5 修改s3c2440_nand.c(參考2410數據手冊和2440數據手冊)

1)首先將所有帶2410字的變數都替換2440

2)修改board_nand_init()

參考以前寫的nand驅動,將

   tacls = 4;
    twrph0 = 8;
    twrph1 = 8;
    cfg = S3C2440_NFCONF_EN;                       //啟動nand控制器
    cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
    writel(cfg, &nand_reg->nfconf); 

改為:

    tacls = 0;                      //10ns    
    twrph0 = 1;                  //20ns
    twrph1 = 0;                  //10ns

    nand_reg->nfconf = (tacls<<12) | (twrph0<<8) | (twrph1<<4); //設置時序
    nand_reg->nfcont=(1<<1)|(1<<0); // bit1:關閉片選(),       bit0:開啟nand flash 控制器

 

2)添加nand_chip結構體成員

nand->select_chip=s3c2440_select_chip;             //設置CE  

然後並寫一個s3c2440_select_chip()函數

/*nand flash  :CE */

static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
        if(chipnr==-1)          //CE Disable
       {
        my_regs->nfcont|=(0x01<<1);               //bit1置1
       }
        else                         //CE Enable
       {
        my_regs->nfcont&=~(0x01<<1);        //bit1置0 
       }           

}

 

3)屏蔽帶硬體ECC的相關操作

將:

#ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2440_nand_enable_hwecc;
nand->ecc.calculate = s3c2440_nand_calculate_ecc;
nand->ecc.correct = s3c2440_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif

改為:

nand->ecc.mode = NAND_ECC_SOFT;               //使用軟體ECC 

 

2.6 修改s3c2440_hwcontrol()函數

改為:

 

static void s3c2440_hwcontrol(struct mtd_info *mtd,int cmd,unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;        
    struct s3c2440_nand *nand = s3c2440_get_base_nand();   //獲取nand寄存器地址
     
    if (ctrl & NAND_CLE)                 // 傳輸的是命令
        nand->nfcmd=cmd;  
    else                                // 傳輸的是地址
        nand->nfaddr=cmd;  
}

 

s3c2440_hwcontrol()函數的ctrl是個標誌位:

  • bit[1]==1: 表示要發送的dat是命令
  • bit[2]==1: 表示要發送的dat是地址
  • bit[0]==1:表示使能nand , ==0:表示禁止nand

(PS:具體可以參考內核的nand_command_lp()函數,它會調用這個cmd_crtl函數來實現功能 )

 

2.7編譯燒寫

如下圖所示,可以看到已支持Nand Flash:

 

 

試驗nand是否能讀寫:

nand erase 0 2000                      //擦除
mw.b 30000000 0x55 2000
nand write 30000000 0 2000        //將0x55寫入nand
nand dump 0 2000        //列印

如下圖所示, 可以看到讀寫nand都沒問題

 

 

下章便來學習:讓uboot支持DM9000網卡,便可以通過網路來傳輸文件


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • AI(Artificial Intelligence)正在不斷的改變著各個行業的形態和人們的生活方式,圖像識別、語音識別、自然語言理解等 AI 技術正在自動駕駛、智能機器人、人臉識別、智能助理等領域中發揮著越來越重要的作用。 那麼當手繪視頻遇到 AI,有 AI 的手繪視頻領域,有 AI 的 UWP ...
  • 前言 在上一篇《【原創】打造基於Dapper的數據訪問層》中,Dapper在應付多表自由關聯、分組查詢、匿名查詢等應用場景時經常要手動寫SQL語句。看著代碼里滿屏的紅色SQL字元串,簡直頭大,於是便萌生重覆造ORM這個輪子的念頭。本ORM在API設計上最大程度地借鑒 EF 的寫法,支持鏈式查詢(點標 ...
  • 第一次用adb,一開始只是想試試看能不能解析出,沒有看網上的現有解析方式。 需要安卓機開啟usb 調試+電腦運行。打開跳一跳的界面 點擊程式 【開始】按鈕即可開始,別的按鈕都是調試用的 主要流程是用abd 截圖傳到電腦開始解析,用顏色計算出起點,然後通過起點計算出終點。然後用adb模擬按壓屏幕。 小 ...
  • 打開vs2017開發者命令提示符 切換至安裝下的指定目錄 執行下麵的命令就可以了 需要註意的是一定要用vs2017的開發人員命令提示符 別用cmd ...
  • 最近有幸閱讀了陳希章花了一年時間為國內開發者貢獻的《Office 365 開發入門指南》。 雖然早期接觸過SharePoint的開發,2007年之後就再也沒有接觸SharePoint的開發,這次閱讀這本書讓我重新認識了Office的系統開發技術,讓我意識到現在的Office 開發也是.NET Cor... ...
  • 1.下載mysql資料庫 鏈接https://dev.mysql.com/downloads/mysql/ 2.解壓到自己喜歡的文件夾下麵,我自己的建在D:\DataBase\mysql-5.7.20-winx64 3.配置環境變數: 4.然後在解壓目錄新建my-default.ini配置文件,配置 ...
  • cp命令的基本用法: cp 源文件 目標文件 如果目標文件不存在 就創建, 如果存在就覆蓋 實現一個cp命令其實就是讀寫文件的操作: 對於源文件: 把內容全部讀取到緩存中,用到的函數read 對於目標文件: 把緩存中的內容全部寫入到目標文件,用到的函數creat 1 /* 2 * Copyright ...
  • Python基礎 對於Python,一切事物都是對象,對象基於類創建 所以,以下這些值都時對象:"zhurui"、22、['北京','上海','深圳'],並且是根據不同的類生成的對象。 一、基本數據類型 數字(int) 如:21、45、56 每一個整數都具備如下功能: 字元串(str) 1、name ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...