日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

移植uboot之修改代码支持NorFlash记录

發布時間:2023/12/10 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 移植uboot之修改代码支持NorFlash记录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習交流加

  • 個人qq:
    1126137994
  • 個人微信:
    liu1126137994
  • 學習交流資源分享qq群:
    962535112

今天我們的任務是修改uboot源碼支持NorFlash。
上兩篇關于uboot移植的文章,我們修改了uboot源代碼,支持了串口的輸出,以及nand啟動(點擊連接可以查看上兩面文章的相關內容移植uboot支持串口輸出,移植uboot支持NAND啟動)
同時分享一個很好的書:Linux設備驅動開發詳解-宋寶華

(注:寫到后面發現沒有告訴大家用的flash芯片的型號,我們用的flash芯片的型號是:MX29LV160DB,芯片手冊大家可以自行到網上下載,從中可以查看芯片的廠家ID和設備ID等信息)
我們移植uboot,都是一步一步調試而來,所以會比較繁瑣,但是我覺得記錄這些,是一件很有意義的事,雖然很麻煩,但是對將來,會有莫大的影響!!!
上次移植支持NAND后,串口啟動界面如下:

我們在source insight中搜索“Flash:”這個字符串出現在哪里,在Board.c中的board_init_r函數中,有這樣幾行代碼:

#if !defined(CONFIG_SYS_NO_FLASH)puts("Flash: ");flash_size = flash_init();if (flash_size > 0) { # ifdef CONFIG_SYS_FLASH_CHECKSUMchar *s = getenv("flashchecksum");print_size(flash_size, "");/** Compute and print flash CRC if flashchecksum is set to 'y'** NOTE: Maybe we should add some WATCHDOG_RESET()? XXX*/if (s && (*s == 'y')) {printf(" CRC: %08X", crc32(0,(const unsigned char *) CONFIG_SYS_FLASH_BASE,flash_size));}putc('\n'); # else /* !CONFIG_SYS_FLASH_CHECKSUM */print_size(flash_size, "\n"); # endif /* CONFIG_SYS_FLASH_CHECKSUM */} else {puts("0 KB\n\r");puts(failed);hang();} #endif

課件代碼是執行到了這兩行:

puts(failed);hang();

查看hang()這個函數為:
void hang(void)
{
puts("### ERROR ### Please RESET the board ###\n");
for (;?;
}
很明顯,代碼進入了一個死循環,所以無法啟動uboot了。
回過頭看上面的board_init_r函數里的flash_size = flash_init();,應該是flash的一個初始化,初始化后成功后才執行下面的if語句,很明顯我們這里沒有初始化成功。進入flash_init。查看代碼如下(在drivers/mtd/Cfi_flash.c中):

unsigned long flash_init (void) {unsigned long size = 0;int i;#ifdef CONFIG_SYS_FLASH_PROTECTION/* read environment from EEPROM */char s[64];getenv_f("unlock", s, sizeof(s)); #endif/* Init: no FLASHes known */for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {flash_info[i].flash_id = FLASH_UNKNOWN;/* Optionally write flash configuration register */cfi_flash_set_config_reg(cfi_flash_bank_addr(i),cfi_flash_config_reg(i));if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))flash_get_size(cfi_flash_bank_addr(i), i);size += flash_info[i].size;if (flash_info[i].flash_id == FLASH_UNKNOWN) { #ifndef CONFIG_SYS_FLASH_QUIET_TESTprintf ("## Unknown flash on Bank %d ""- Size = 0x%08lx = %ld MB\n",i+1, flash_info[i].size,flash_info[i].size >> 20); #endif /* CONFIG_SYS_FLASH_QUIET_TEST */} #ifdef CONFIG_SYS_FLASH_PROTECTIONelse if ((s != NULL) && (strcmp(s, "yes") == 0)) {/** Only the U-Boot image and it's environment* is protected, all other sectors are* unprotected (unlocked) if flash hardware* protection is used (CONFIG_SYS_FLASH_PROTECTION)* and the environment variable "unlock" is* set to "yes".*/if (flash_info[i].legacy_unlock) {int k;/** Disable legacy_unlock temporarily,* since flash_real_protect would* relock all other sectors again* otherwise.*/flash_info[i].legacy_unlock = 0;/** Legacy unlocking (e.g. Intel J3) ->* unlock only one sector. This will* unlock all sectors.*/flash_real_protect (&flash_info[i], 0, 0);flash_info[i].legacy_unlock = 1;/** Manually mark other sectors as* unlocked (unprotected)*/for (k = 1; k < flash_info[i].sector_count; k++)flash_info[i].protect[k] = 0;} else {/** No legancy unlocking -> unlock all sectors*/flash_protect (FLAG_PROTECT_CLEAR,flash_info[i].start[0],flash_info[i].start[0]+ flash_info[i].size - 1,&flash_info[i]);}} #endif /* CONFIG_SYS_FLASH_PROTECTION */}flash_protect_default(); #ifdef CONFIG_FLASH_CFI_MTDcfi_mtd_init(); #endifreturn (size); }

里面有一個if判斷語句:

if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))flash_get_size(cfi_flash_bank_addr(i), i);

從字面意思看出flash_detect_legacy為舊的檢測flash,flash_get_size就應該為新的檢測flash機制,先看一下舊的,沒看出什么,再看flash_get_size,發現有很多debug調試信息,有這么多調試信息,那就應該用起來:
在flash_get_size中的debug信息

debug ("manufacturer is %d\n", info->vendor);debug ("manufacturer id is 0x%x\n", info->manufacturer_id);debug ("device id is 0x%x\n", info->device_id);debug ("device id2 is 0x%x\n", info->device_id2);debug ("cfi version is 0x%04x\n", info->cfi_version);

搜索debug 查到:
在include/common.h中有下面的代碼

#define debug(fmt, args...) \debug_cond(_DEBUG, fmt, ##args)

很明顯應該是用的_DEBUG,搜索_DEBUG,有:

#ifdef DEBUG #define _DEBUG 1 #else #define _DEBUG 0 #endif

好,那么我們就把#define _DEBUG 1給加上,在Cfi_flash.c中定義如下兩行:

#define DEBUG 1 (不確定是哪個就都定義,反正也不會出錯) #define _DEBUG 1

重新編譯uboot燒寫啟動看一下:

打印的這句話:JEDEC PROBE: ID c2 2249 0
告訴我們讀到的廠家ID,設備ID,我們查看datasheet,發現這個讀到的ID是沒有錯的,廠家ID是c2,設備ID是2249,

根據打印信息,在源碼中搜索字符串“JEDEC PROBE:”在Cfi_flash.c中的flash_detect_legacy函數中有如下代碼片段:

debug("JEDEC PROBE: ID %x %x %x\n",info->manufacturer_id,info->device_id,info->device_id2);if (jedec_flash_match(info, info->start[0]))break;elseunmap_physmem((void *)info->start[0],MAP_NOCACHE);

看出設備ID時如何打印的,下面的jedec_flash_match還需要進行一下匹配,我們去jedec_flash_match函數里看看是實現的什么內容(在drivers/mtd/jeder_flash.c中):

/*-----------------------------------------------------------------------* match jedec ids against table. If a match is found, fill flash_info entry*/ int jedec_flash_match(flash_info_t *info, ulong base) {int ret = 0;int i;ulong mask = 0xFFFF;if (info->chipwidth == 1)mask = 0xFF;for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&(jedec_table[i].dev_id & mask) == (info->device_id & mask)) {fill_info(info, &jedec_table[i], base);ret = 1;break;}}return ret; }

發現一個數組jedec_table,匹配設備的ID用的應該就是這個數組里的內容了,查看數組如下:

static const struct amd_flash_info jedec_table[] = { #ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8{.mfr_id = (u16)SST_MANUFACT,.dev_id = SST39LF020,.name = "SST 39LF020",.uaddr = {[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */},.DevSize = SIZE_256KiB,.CmdSet = P_ID_AMD_STD,.NumEraseRegions= 1,.regions = {ERASEINFO(0x01000,64),}},。。。。。。。。。。(還有很多跟上面相同的類型的內容,我這里給省略了)

這個結構體里的內容,定義了許多類型的flash,每一個定義就是一個flash芯片。我們在里面自己定義我們的芯片結構項。

/* jz2440使用的是MX29LV160DB芯片 */{.mfr_id = (u16)MX_MANUFACT, /*廠家ID*/.dev_id = 0x2249, /*設備ID*/.name = "MXIC MX29LV160DB",.uaddr = { /*NOR FLASH看到的解鎖地址*/[0] = MTD_UADDR_0x0555_0x02AA /* x16 */},.DevSize = SIZE_2MiB, /* 總大小 */.CmdSet = P_ID_AMD_STD,.NumEraseRegions= 4, /* 擦除區域的數目 */.regions = { /* 這些內容涉及芯片手冊的閱讀,之后的文章會單獨寫關于硬件的操作 */ERASEINFO(16*1024, 1), ERASEINFO(8*1024, 2),ERASEINFO(32*1024, 1),ERASEINFO(64*1024, 31),}},

里面涉及到 的硬件操作,我會在之后的講解NOR FLASH 驅動時,講解如何操作這個芯片里面涉及到,在這里,我們移植uboot,只需要這樣做就可以,暫時不需要追根究底(無底洞啊!!!)。

然后就是最開始忘記了一件事,就是把board.中的board_init_r中的兩行代碼(自己回頭看上面的代碼)屏蔽掉:

//puts(failed);//hang();

然后重新編譯uboot,燒寫啟動運行:

哈哈哈!!!!先慶祝一下,終于啟動進去了,雖然還沒有完善,但是得一步一步來嘛!
顯示有錯誤:ERROR: too many flash sectors,在源碼中搜索這個錯誤找到(Cfi_flash.c中):

if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {printf("ERROR: too many flash sectors\n");break;}

跳轉到CONFIG_SYS_MAX_FLASH_SECT這個定義(在smdk2440.h中),有:

#define CONFIG_SYS_MAX_FLASH_SECT (19)

將19改為128吧:

#define CONFIG_SYS_MAX_FLASH_SECT (128)

然后再把我們之前加的Debug調試信息去掉,因為我們已經不需要那些打印信息了,去掉的話會看起來簡潔一些,去掉下面的兩個宏定義:

//#define DEBUG 1 //#define _DEBUG 1

重新編譯燒寫,看啟動界面:

這次啟動界面比較簡潔,而且上面出現的錯誤也沒有了!!!
那我們現在來測試一下NORFLASH能否擦除與讀寫。
串口中輸入:protect off all,先解除寫保護
輸入:flinfo,打印輸出正常:

輸入:erase 80000 8ffff

輸入:cp.b 30000000 80000 10000 (把內存中30000000位置的內容拷貝到flash80000地址)

到了這里,出現了一些問題,無法將內存的代碼拷貝過來,無法寫flash。。。。。。。。。啊,天哪,感覺又得花時間去看了!!!

放到下一篇博客吧,這篇已經寫了很多了!!!

想獲得各種學習資源以及交流學習的加我:
qq:1126137994
微信:liu1126137994
可以共同交流關于嵌入式,操作系統,C++語言,C語言,數據結構等技術問題!

總結

以上是生活随笔為你收集整理的移植uboot之修改代码支持NorFlash记录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: www.国产在线视频 | 男男肉耽高h彩漫 | 嫩草视频在线播放 | 日韩一级影视 | 国产福利一区二区 | 四虎毛片| 伊人青青草视频 | 人妻熟女aⅴ一区二区三区汇编 | 欧美特级黄色录像 | 粉嫩小泬无遮挡久久久久久 | 免费久久一级欧美特大黄 | 交做爰xxxⅹ性爽 | 稀缺呦国内精品呦 | 又大又粗又爽18禁免费看 | 视频一区在线播放 | 国产亚洲成av人片在线观看桃 | 激情欧美一区二区三区 | 亚洲国产97| 国产成人自拍视频在线观看 | 久久最新 | 日本免费在线播放 | 永久免费未网 | 不卡av在线免费观看 | 亚洲制服一区二区 | 欧美在线综合 | 青青草在线免费 | 肉色超薄丝袜脚交69xx | 激情五月五月婷婷 | 亚洲激情视频 | 国产福利视频在线观看 | 观看av免费| 久久艹免费视频 | 国产精品一二三四 | 国产免费观看一区 | 亚洲精品97久久 | 一卡二卡在线观看 | 一本色道久久综合精品婷婷 | 欧美一区二区三区爽爽爽 | 蜜臀av性久久久久蜜臀av麻豆 | 国产女人精品 | 成年视频在线观看 | 黄色污污视频网站 | 九一九色国产 | 99色99| 熟妇人妻久久中文字幕 | 美女黄视频大全 | 久久久免费av | 香蕉久久夜色精品升级完成 | 一本色道久久88综合日韩精品 | 国产sm调教视频 | 北条麻妃一区二区三区在线观看 | 先锋av资源在线 | 丰满大乳奶做爰ⅹxx视频 | 91蝌蚪在线观看 | 黄色一级视频免费 | 成年人黄色网址 | 午夜久草| 免费麻豆av | 欧美性爱精品一区 | 九一精品国产 | av免费大片 | 亚洲一区二区三区四区五区六区 | 久久精品视频在线免费观看 | 一区二区三区毛片 | 在线视频麻豆 | 亚洲国产成人精品91久久久 | 精品视频在线免费看 | 中国zzji女人高潮免费 | 成人黄色小视频 | 人妻少妇偷人精品视频 | 爱av导航 | 自拍偷拍综合 | 欧美日韩欧美日韩在线观看视频 | 中文字幕有码在线 | 波多野结衣一区二区三区在线观看 | 久久精品—区二区三区舞蹈 | 91蜜桃婷婷狠狠久久综合9色 | 亚洲爱爱av | 天天操天天干天天爱 | 日本美女a级片 | 国产精品无码成人网站视频 | 伊人96| 国产成人精品视频一区二区 | 国产美女福利 | 无码人妻精品一区二区蜜桃网站 | 日韩视频中文字幕 | 欧美成人乱码一二三四区免费 | 日本黄网站色大片免费观看 | 久操久热| 久久久久久久久艹 | 精品视频在线观看免费 | 91玖玖| 人与动物av| 久久天 | 亚洲一区精品在线观看 | 肉色超薄丝袜脚交69xx | 国产一区二区精华 | 乱码一区二区三区 | 亚洲国产高清国产精品 |