移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash从上面的信息可知,uboot已经识别出NOR Flash空间的大小2MiB,但是还显示错误ERROR: too many flash secto

大家好,欢迎来到IT知识分享网。

5. 移植u-boot-2016.03修改代码支持NOR Flash

从上一节把uboot烧写到NAND启动后,最后打印出Flash: 0 Bytes,如下图所示。我们的Jz2440开发板的NOR Flash是2MB的,那么为什么显示Flash是0Bytes呢?显然,此时的uboot还没支持NOR Flash,所以不是识别开发板的NOR Flash大小。

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

5.1 分析u-boot-2016.03源码之NOR Flash

(1) 我们在source insight中搜索“Flash:”这个字符串出现在哪里,在 common/boardr.c中有 initrflash函数,该函数放在 initsequencer函数指针数组了,被 boardinitr函数调用,initr_flash函数的代码如下:

static int initr_flash(void) { ulong flash_size = 0; bd_t *bd = gd->bd; puts("Flash: "); /* 打印 Flash: */ if (board_flash_wp_on()) /*空函数,返回0*/ printf("Uninitialized - Write Protect On\n"); else flash_size = flash_init(); print_size(flash_size, ""); #ifdef CONFIG_SYS_FLASH_CHECKSUM /* * Compute and print flash CRC if flashchecksum is set to 'y' * * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX */ if (getenv_yesno("flashchecksum") == 1) { printf(" CRC: %08X", crc32(0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)); } #endif /* CONFIG_SYS_FLASH_CHECKSUM */ putc('\n'); /* update start of FLASH memory */ #ifdef CONFIG_SYS_FLASH_BASE bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; #endif /* size of FLASH memory (final value) */ bd->bi_flashsize = flash_size; #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE) /* Make a update of the Memctrl. */ update_flash_size(flash_size); #endif #if defined(CONFIG_OXC) || defined(CONFIG_RMU) /* flash mapped at end of memory map */ bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size; #elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE bd->bi_flashoffset = monitor_flash_len; /* reserved area for monitor */ #endif return 0; } 

从上面的代码可知,显然 initrflash函数通过调用 flashinit函数获取 NOR Flash空间的大小,flashinit函数的代码如下:(该函数在 drivers/mtd/cfiflash.c)

unsigned long flash_init (void) { unsigned long size = 0; int i; #ifdef CONFIG_SYS_FLASH_PROTECTION /*CONFIG_SYS_FLASH_PROTECTION 没定义*/ /* read environment from EEPROM */ char s[64]; getenv_f("unlock", s, sizeof(s)); #endif #ifdef CONFIG_CFI_FLASH /* for driver model */ /*CONFIG_CFI_FLASH 没定义*/ cfi_flash_init_dm(); #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_TEST /*CONFIG_SYS_FLASH_QUIET_TEST没定义*/ printf ("## 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_PROTECTION /*CONFIG_SYS_FLASH_PROTECTION没定义*/ else if (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_MTD /*CONFIG_FLASH_CFI_MTD 没定义*/ cfi_mtd_init(); #endif return (size); } 

上面的程序有一个if判断语句:

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

从字面意思看出flashdetectlegacy为旧的检测flash,flashgetsize就应该为新的检测flash机制,先看一下旧的,没看出什么,再看flashgetsize,发现有很多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,在 include/common.h中有:

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

那么我们就把#define DEBUG给加上,在jz2440.h中定义如下:

#define DEBUG 

重新编译u-boot烧写到NOR Flash,并设置为NOR Flash启动,启动后后串口有如下结果输出:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

从打印的这句话:JEDEC PROBE: ID c2 2249 0 可知厂家ID是c2,设备ID是2249,查看NOR Flash(MX29LV160DBT)的数据手册有:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

从数据手册可知,MX29LV160DBT的设备厂家ID是C2,设备ID是2249,与uboot读出的厂家ID、设备ID相符。所以,现在的uboot是可以正常读出NOR Flash的厂家ID、设备ID的。

(2) 根据打印信息,在源码中搜索字符串“JEDEC PROBE:”在drivers/mtd/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; else unmap_physmem((void *)info->start[0], MAP_NOCACHE); 

从上面的代码可知厂家ID、设备ID是如何打印的;同时还需要通过jedec_flash_match函数进行匹配,jedec_flash_match函数代码如下:(在drivers/mtd/jedec_flash.c)

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_flash_match发现一个数组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), } }, #endif ...... 

5.2 修改代码支持NOR Flash

(1) 在amdflashinfo 这个结构体数组里的内容,定义了许多类型的flash,每一个定义就是一个flash芯片。我们在里面自己定义我们的芯片结构项:

{ .mfr_id = (u16)0x00C2,/*厂家ID*/ .dev_id = 0x2249, /*设备ID*/ .name = "MXIC MX29LV160DB", .uaddr = { [1] = MTD_UADDR_0x0555_0x02AA /* x16 *//*NOR FLASH看到的解锁地址*/ }, .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), } }, 

然后,重新编译u-boot,烧写到NOR Flash并启动运行,打印信息有如下:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

从上面的信息可知,uboot已经识别出NOR Flash空间的大小2MiB,但是还显示错误ERROR: too many flash sectors (2) 从源码中搜索错误ERROR: too many flash sectors,发现在drivers/mtd/cfi_flash.c有如下代码:

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

跳转到CONFIG_SYS_MAX_FLASH_SECT这个定义(在jz2440.h中),有:

#define CONFIG_SYS_MAX_FLASH_SECT (19) 

从下图的NOR Flash的数据手册可知,Secter总共有35个;因此,把CONFIG_SYS_MAX_FLASH_SECT宏定义改为::

#define CONFIG_SYS_MAX_FLASH_SECT (35) 
移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

此外,在jz2440.h中把Debug调试信息去掉:

/*#define DEBUG */ 

注:jz2440.h中注释不能使用 双斜杠”//” 注释,否则,编译的时候会自动在uboot顶层目录下的链接脚本u-boot.lds添加”//#define DEBUG”,所下图所示:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

然后编译时会产生如下错误:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

重新编译u-boot,烧写到NOR Flash并启动运行,打印信息如下:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

从上图可知,已经可以清晰看到uboot识别出NOR Flash空间大小:Flash: 2 MiB,而且错误ERROR: too many flash sectors也消失了。

5.3 测试

(1) 先解除写保护,在串口中输入:protect off all (2) 输入:flinfo;打印正常:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

(3) 输入:erase 80000 8ffff

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

(4) 输入:cp.b 80000 10000

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

从上图可知,NOR Flash 写成功。

(5) 测试norflash写功能的完整性: 在串口输入以下命令:

protect off all //关闭写保护 erase 80000 8ffff cp.b  80000 10000 md.b 80000 //显示0x80000地址的内容 md.b  cmp.b  80000 10000 //比较0x地址的内容与0x80000地址的内容,比较数据长度0x10000字节 

结果如下图:

移植u-boot-2016.03到Jz2440之修改代码支持NOR Flash

由上图可知,NOR Flash读写测试成功。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/49983.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信