十三、u-boot 调试-- NOR FLASH 支持

13.1 问题现象

  

  在烧写进去的u-boot 中 Flash 并没有显示实际大小,需要进行修改。

13.2 问题定位过程

13.2.1 关键字搜索 Flash:

  此关键字在 Board_r.c (common) 文件中的 initr_flash 函数,此函数用 CONFIG_MTD_NOR_FLASH 宏控制,去掉不相关的代码:

 1 #if defined(CONFIG_MTD_NOR_FLASH)   //味ㄒ錍ONFIG_SYS_NOR_FLASH这个宏就执行此函数
 2 static int initr_flash(void)
 3 {
 4     ulong flash_size = 0;   //定义存储 flash 大小的变量
 5     bd_t *bd = gd->bd;      //定义板信息结构体
 6
 7     puts("Flash: ");        //输出字符串 Flash:
 8
 9     if (board_flash_wp_on())    //此为空函数,返回0值,直接执行 else后面的语句,此函数也可以自己实现
10         printf("Uninitialized - Write Protect On\n");
11     else
12         flash_size = flash_init();  //flash初始化
13
14     print_size(flash_size, "");     //打印flash_size的大小
15     putc(‘\n‘);         //换行
16
17     /* update start of FLASH memory    */
18 #ifdef CONFIG_SYS_FLASH_BASE
19     bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;  //bd->bi_flashstart = 0 从0地址开始执行
20 #endif
21     /* size of FLASH memory (final value) */
22     bd->bi_flashsize = flash_size;  //flash 的大小
23
24 #if defined(CONFIG_OXC) || defined(CONFIG_RMU)
25     /* flash mapped at end of memory map */
26     bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size;
27 #elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
28     bd->bi_flashoffset = monitor_flash_len;    /* reserved area for monitor */
29 #endif
30     return 0;
31 }
32 #endif

红色字体部分代码已经很明显的显示了打印过程。

  首先是,flash_init 初始化flash ,然后调用 print_size 打印处 flash 的大小。flash_init 函数执行完后,会返回 flash_size 变量,即为 flash 的大小。

13.2.2 flash_init  

  Cfi_flash.c (drivers\mtd)

  

 1 unsigned long flash_init(void)
 2 {
 3     unsigned long size = 0;
 4     int i;
 5
 6     /* Init: no FLASHes known */
 7     /* #define CONFIG_SYS_MAX_FLASH_BANKS    1 */
 8     /* include/configs/jz2440.h中有定义,为 1 */
 9     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
10         flash_info[i].flash_id = FLASH_UNKNOWN;
11
12         /* Optionally write flash configuration register */
13         cfi_flash_set_config_reg(cfi_flash_bank_addr(i),
14                      cfi_flash_config_reg(i));
15
16         /* 检测 flash
17          * flash_detect_legacy 是旧的检测策略
18          */
19         if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))
20             flash_get_size(cfi_flash_bank_addr(i), i);
21         size += flash_info[i].size;
22         if (flash_info[i].flash_id == FLASH_UNKNOWN) {
23 #ifndef CONFIG_SYS_FLASH_QUIET_TEST
24             printf("## Unknown flash on Bank %d ", i + 1);
25             printf("- Size = 0x%08lx = %ld MB\n",
26                    flash_info[i].size,
27                    flash_info[i].size >> 20);
28 #endif /* CONFIG_SYS_FLASH_QUIET_TEST */
29         }
30     }
31
32     flash_protect_default();    //flash的默认保护
33
34     return (size);
35 }

  分析到当前,已经可以看见一些端倪了,size 变量是在 检测到flash 之后,才有正确的值,当前我们无法保证是否检测到了 flash。

  当前我们可以开一下 debug 宏进行调试。

13.2.3 flash_detect_legacy

  源码位置:Cfi_flash.c (drivers\mtd)

  1 #ifdef CONFIG_FLASH_CFI_LEGACY        // include/configs/jz2440.h 中有定义
  2 /* 读取flash 的产品信息 */
  3 static void flash_read_jedec_ids (flash_info_t * info)
  4 {
  5     info->manufacturer_id = 0;
  6     info->device_id       = 0;
  7     info->device_id2      = 0;
  8
  9     switch (info->vendor) {
 10     case CFI_CMDSET_INTEL_PROG_REGIONS:
 11     case CFI_CMDSET_INTEL_STANDARD:
 12     case CFI_CMDSET_INTEL_EXTENDED:
 13         cmdset_intel_read_jedec_ids(info);
 14         break;
 15     case CFI_CMDSET_AMD_STANDARD:
 16     case CFI_CMDSET_AMD_EXTENDED:
 17         cmdset_amd_read_jedec_ids(info);
 18         break;
 19     default:
 20         break;
 21     }
 22 }
 23
 24 /*-----------------------------------------------------------------------
 25  * Call board code to request info about non-CFI flash.
 26  * board_flash_get_legacy needs to fill in at least:
 27  * info->portwidth, info->chipwidth and info->interface for Jedec probing.
 28  */
 29 static int flash_detect_legacy(phys_addr_t base, int banknum)
 30 {
 31     flash_info_t *info = &flash_info[banknum];
 32
 33     /*  获得旧的 flash 信息,返回值为 0
 34      *     info->portwidth = FLASH_CFI_16BIT;  0x02
 35      *    info->chipwidth = FLASH_CFI_BY16;    0x02
 36      *    info->interface = FLASH_CFI_X16;    0x01
 37      */
 38     if (board_flash_get_legacy(base, banknum, info)) {
 39         /* board code may have filled info completely. If not, we
 40            use JEDEC ID probing. */
 41         if (!info->vendor) {
 42             int modes[] = {
 43                 CFI_CMDSET_AMD_STANDARD,
 44                 CFI_CMDSET_INTEL_STANDARD
 45             };
 46             int i;
 47
 48             for (i = 0; i < ARRAY_SIZE(modes); i++) {
 49                 info->vendor = modes[i];
 50                 /* 映射物理地址 */
 51                 info->start[0] =
 52                     (ulong)map_physmem(base,
 53                                info->portwidth,
 54                                MAP_NOCACHE);
 55                 /* if中的语句不执行,前面已经设置 info->portwidth = FLASH_CFI_16BIT;*/
 56                 if (info->portwidth == FLASH_CFI_8BIT
 57                     && info->interface == FLASH_CFI_X8X16) {
 58                     info->addr_unlock1 = 0x2AAA;
 59                     info->addr_unlock2 = 0x5555;
 60                 } else {/* 执行else 中的语句,发送  0x5555 0x2aaa命令 */
 61                     info->addr_unlock1 = 0x5555;
 62                     info->addr_unlock2 = 0x2AAA;
 63                 }
 64                 flash_read_jedec_ids(info);
 65                 debug("JEDEC PROBE: ID %x %x %x\n",
 66                         info->manufacturer_id,
 67                         info->device_id,
 68                         info->device_id2);
 69                 /* 适配flash */
 70                 if (jedec_flash_match(info, info->start[0]))
 71                     break;
 72                 else
 73                     unmap_physmem((void *)info->start[0],
 74                               info->portwidth);
 75             }
 76         }
 77
 78         switch(info->vendor) {
 79         case CFI_CMDSET_INTEL_PROG_REGIONS:
 80         case CFI_CMDSET_INTEL_STANDARD:
 81         case CFI_CMDSET_INTEL_EXTENDED:
 82             info->cmd_reset = FLASH_CMD_RESET;
 83             break;
 84         case CFI_CMDSET_AMD_STANDARD:
 85         case CFI_CMDSET_AMD_EXTENDED:
 86         case CFI_CMDSET_AMD_LEGACY:
 87             info->cmd_reset = AMD_CMD_RESET;
 88             break;
 89         }
 90         info->flash_id = FLASH_MAN_CFI;
 91         return 1;
 92     }
 93     return 0; /* use CFI */
 94 }
 95 #else
 96 static inline int flash_detect_legacy(phys_addr_t base, int banknum)
 97 {
 98     return 0; /* use CFI */
 99 }
100 #endif

  当前我们可以开一下 debug 宏进行调试。

13.2.3 debug 调试

  当前我们可以开一下 debug 宏进行调试。

  在include/common.h的顶端加入debug 宏。 #define DEBUG 然后重新编译开机

  

  这里打印了两个 JEDEC PROBE,一个是在 flash_detect_legacy 中打印,还有是什么暂且不知道。  

  芯片手册的COMMAND OPERATIONS有如下几行:

  

  

  上面这张图说明了如何去读ID,黄色部分为地址。即在555地址发出aa,在2AA地址发出55命令,在555地址发出90命令,则可以在00地址读出厂家ID c2。

  2249 正好对应我们的设备ID号,看来是已经识别出来了 nor flash.

  JEDEC PROBE在 flash_detect_legacy(Cfi_flash.c (drivers\mtd) )的debug 打印函数中,之后执行jedec_flash_match(info, info->start[0])去匹配。

  在jedec_flash_match 会去匹配jedec_table数组,如果有,则返回1,没有则返回0。

13.2.4 jedec_flash_match

  代码中会去与 jedec_table 表去匹配。

 1 /*-----------------------------------------------------------------------
 2  * match jedec ids against table. If a match is found, fill flash_info entry
 3  */
 4 int jedec_flash_match(flash_info_t *info, ulong base)
 5 {
 6     int ret = 0;
 7     int i;
 8     ulong mask = 0xFFFF;
 9     if (info->chipwidth == 1)
10         mask = 0xFF;
11
12     for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
13         if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&
14             (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
15             fill_info(info, &jedec_table[i], base);
16             ret = 1;
17             break;
18         }
19     }
20     return ret;
21 }

13.2.5 jedec_table

  Jedec_flash.c (drivers\mtd)

  

  这个表中定义了 flash 的所有信息,如果可以匹配到我们的 flash 则会显示信息,提取处 flash 大小值。

  查看 jedec_table (Jedec_flash.c (drivers\mtd) ),是否有 c2 2249 0  这些项。搜索后没有,则需要添加进设备信息。

  厂家ID添加(Flash.h (include) ),已在头文件中存在。   

  

  搜索:

  

  分别在两个地方引用了MX_MANUFACT的ID。

  最上面的一个需要定义宏 CONFIG_SYS_FLASH_LEGACY_512Kx8 才可以引用

  下面一个需要定义宏 CONFIG_SYS_FLASH_LEGACY_512Kx16 才能使用。CONFIG_SYS_FLASH_LEGACY_512Kx16 在jz2440中有定义。

  两个可以匹配,但是dev_id 无匹配,仍需要添加。这两个宏也和我们的芯片不匹配,板子上所使用的芯片为 1M X 16的。

13.3 代码修改

13.3.1 添加设备

  Jedec_flash.c (drivers\mtd)

  

  在 jedec_table 的最后添加

 1 #ifdef CONFIG_SYS_FLASH_LEGACY_1Mx16
 2     /* JZ2440使用 */
 3     {
 4         .mfr_id        = (u16)MX_MANUFACT,        /* 厂家ID */
 5         .dev_id        = MX29LV160DB,            /* 设备ID */
 6         .name        = "MXIC MX29LV160DB",    /* 芯片名称 */
 7         .uaddr        = {                        /* norflash看到的解锁地址,norflash可以像内存一样读,但写必须先解锁 */
 8             [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
 9         },
10         .DevSize    = SIZE_2MiB,            /* 总空间大小 */
11         .CmdSet        = P_ID_AMD_STD,/* 命令集 */
12         .NumEraseRegions= 4,                /* norflash的擦除块 */
13         .regions    = {
14             ERASEINFO(0x04000, 1),
15             ERASEINFO(0x02000, 2),
16             ERASEINFO(0x08000, 1),
17             ERASEINFO(0x10000, 31),
18         }
19     },
20 #endif

13.3.2 修改扇区大小

  include/config/jz2440.h 中

  

13.3.3 调试 

  编译烧写测试,结果如下:

  

  上面报了一个错:ERROR: too many flash sectors

  搜索关键字定位到Jedec_flash.c (drivers\mtd)的fill_info函数,有如下打印调试信息:

  

  定位CONFIG_SYS_MAX_FLASH_SECT(flash的最大扇区),Jz2440.h (include\configs)

  

  这里扇区定义的是19个,但是我们的norflash的扇区有 1+ 2 + 1 + 31 = 35个,改成随机的128,或者改成35也可以,最大扇区定义:

  

  

  执行命令:flinfo

  

  取消写保护:protect off all

  

  擦除80000--90000之间的区域:erase 80000 8ffff

  

  拷贝DRAM中的数据进norflash:cp.b 30000000 80000 10000

  

  DRAM 30000000处的数据:md.b 30000000

  

  norflash 80000处的数据:md.b 80000

  

  比较两者之间的数据:cmp.b 30000000 80000 10000

  

  移植完成。

原文地址:https://www.cnblogs.com/kele-dad/p/8999684.html

时间: 2024-10-18 22:55:32

十三、u-boot 调试-- NOR FLASH 支持的相关文章

让Flash支持Stage3D

如要需要支持Stage3D,采用GPU来渲染,需要设置wmode="direct",在FB中,对于web和air设置方法不同: 1.web: 需要在web的html模板中,添加参数: var params = {}; params.wmode = "direct"; 2.air: 需要在bin-dubeg---->xxx-app.xml中,添加参数: <renderMode>direct</renderMode><depthAnd

Spring Boot项目如何同时支持HTTP和HTTPS协议

本文首发于个人网站:Spring Boot项目如何同时支持HTTP和HTTPS协议 如今,企业级应用程序的常见场景是同时支持HTTP和HTTPS两种协议,这篇文章考虑如何让Spring Boot应用程序同时支持HTTP和HTTPS两种协议. 准备 为了使用HTTPS连接器,需要生成一份Certificate keystore,用于加密和机密浏览器的SSL沟通. 如果你使用Unix或者Mac OS,可以通过下列命令:keytool -genkey -alias tomcat -keyalg RSA

java-cef系列视频第三集:添加flash支持

上一集我们介绍了如何搭建java-cef调试环境. 本视频介绍如何给java-cef客户端添加flashplayer支持 本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 中国大陆许可协议进行许可.

Provisioning Services 7.8 入门系列教程之十三 使用 Boot Device Management(BDM)

续Provisioning Services 7.8 入门系列教程之十二 实现高可用性 可以使用 Boot Device Management 实用程序将 IP 和引导信息(引导设备)交付给目标设备,此方法可以取代传统的 DHCP.PXE 和 TFTP 方法. 如果使用此方法,当目标设备启动时, 将直接从引导设备获取引导信息. 使用这些信息,目标设备可以找到相应的 Provisioning Server.与之通信并从该服务器引导. 对用户进行身份验证后,Provisioning Server 将

Spring boot之添加JSP支持

大纲 (1) 创建Maven web project: (2) 在pom.xml文件添加依赖 (3) 配置application.properties支持jsp (4) 编写测试Controller (5) 编写JSP页面 (6) 编写启动类App.java 创建Maven web project 使用Eclipse新建一个Maven Web Project ,项目取名为: spring-boot-jsp 在pom.xml文件添加依赖 <!-- spring boot parent节点,引入这个

Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器

概要 之前的两篇文章,讲述了Spring Security 结合 OAuth2 .JWT 的使用,这一节要求对 OAuth2.JWT 有了解,若不清楚,先移步到下面两篇提前了解下. Spring Boot Security 整合 OAuth2 设计安全API接口服务 Spring Boot Security 整合 JWT 实现 无状态的分布式API接口 这一篇我们来实现 支持 JWT令牌 的授权服务器. 优点 使用 OAuth2 是向认证服务器申请令牌,客户端拿这令牌访问资源服务服务器,资源服务

spring boot 加入mail邮件支持

一.添加依赖 <!-- 邮件整合 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> 二.添加mail.properties配置文件 #设置邮箱主机 spring.mail.host=smtp.qq.com #设置用户名 spr

spring boot 调试 - 热部署

命令行方式: mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" 需要在idea 中edit configuration->+ -> remote->debug rum main方法: debug run 热部署 在pom里添加: <build> <plugins> <p

spring boot 中添加mongodb支持

1.添加maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> 2.application.properties配置文件中配置mongodb访问参数 spring.data.mongodb.host=localhost