u-boot移植(十)---代码修改---支持nor flash

发布时间:2023-07-03  

一、问题定位

  

  开发板重启后打印了2个提醒和一个错误,caches的提醒先不看,看看flash和nand下面的提醒,bad CRC,Using default enviroment,我们可以定位Using default enviroment定位到

代码位置,如下:  

  Env_common.c (common) 

  

  传入的参数应该是 !badCRC,再次定位函数set_default_env 看是在哪里调用此函数:

  

  

  

  

  

  基本上文件都在common文件夹下,有common中的调用和 dataflash,nand,sf,ubi。暂且不知道是哪个,要看看u-boot.dis中哪里调用了这个函数,再来定位了。

  通过u-boot.dis 可以知道,在几个函数中调用了 set_default_env 这个函数:


    • env_import:Env_common.c (common) 

    • env_relocate:Env_common.c (common)

    • do_env_default:Cmd_nvedit.c (common) 

二、代码分析

  搜索 Flash: 查看结果:

  

  与此相匹配的为 board_r.c 文件中。

  定位到 board_r.c(common)中的 initr_flash 函数。  

  此函数定义在第二阶段代码 board_init_r 函数中的 init_sequence_r 链表中:

  

2.1 initr_flash

  initr_flash 函数的代码解读如下:

 1 #if !defined(CONFIG_SYS_NO_FLASH)    //未定义CONFIG_SYS_NO_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 Onn");

11     else

12         flash_size = flash_init();    //flash初始化

13 

14     print_size(flash_size, "");        //打印flash_size的大小

15 #ifdef CONFIG_SYS_FLASH_CHECKSUM    //此宏在 include/configs/jz2440.h 未定义 里面的一段代码不执行

16     /*

17     * Compute and print flash CRC if flashchecksum is set to 'y'

18     *

19     * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX

20     */

21     if (getenv_yesno("flashchecksum") == 1) {

22         printf("  CRC: %08X", crc32(0,

23             (const unsigned char *) CONFIG_SYS_FLASH_BASE,

24             flash_size));

25     }

26 #endif /* CONFIG_SYS_FLASH_CHECKSUM */

27     putc('n');                        //换行

28 

29     /* update start of FLASH memory    */

30     /* CONFIG_SYS_FLASH_BASE 在 include/configs/jz2440.h中有定义

31      * #define CONFIG_SYS_FLASH_BASE    PHYS_FLASH_1

32      * #define PHYS_FLASH_1        0x00000000             // Flash Bank #0 

33      * 这里定义的宏的大小为0 则我们的CONFIG_SYS_FLASH_BASE 页的基地址为0

34      */

35 #ifdef CONFIG_SYS_FLASH_BASE        

36     bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;    //bd->bi_flashstart = 0 从0地址开始执行

37 #endif

38     /* size of FLASH memory (final value) */

39     bd->bi_flashsize = flash_size;            //flash 的大小

40 

41 #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE)

42     /* Make a update of the Memctrl. */

43     update_flash_size(flash_size);            //更新flash 的大小

44 #endif

45 

46 

47 #if defined(CONFIG_OXC) || defined(CONFIG_RMU)    //未定义,不执行

48     /* flash mapped at end of memory map */

49     bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size;

50     /* #define CONFIG_SYS_MONITOR_BASE    CONFIG_SYS_FLASH_BASE

51      * 从这里可以看出CONFIG_SYS_MONITOR_BASE与CONFIG_SYS_FLASH_BASE相等,

52      * 则执行宏内语句

53      */

54 #elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE

55     bd->bi_flashoffset = monitor_flash_len;    /* reserved area for monitor */

56 #endif

57     return 0;

58 }

59 #endif


  标记红色的语句就是我们在执行的语句。可以看出在flash 初始化后就打印出了 flash空间大小。


  定位到 flash_init 中


2.2 flash_init  

  文件路径:Cfi_flash.c (driversmtd)


  先去掉不必要的宏,代码精简一下。


 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         /* 检测 flash

16          * flash_detect_legacy 是旧的检测策略

17          */

18         if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))

19             flash_get_size(cfi_flash_bank_addr(i), i);

20         size += flash_info[i].size;

21         if (flash_info[i].flash_id == FLASH_UNKNOWN) {

22         }

23     }

24 

25     flash_protect_default();    //flash的默认保护

26     return (size);

27 }


  在第18行,看到 flash 检测,这里检测的是 flash 的信息和大小。可以进去看看源码


2.2.1 flash_detect_legacy

  源码位置:Cfi_flash.c (driversmtd) 


  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命令 */

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>