现在的位置: 首页 > 综合 > 正文

u-boot的norflash驱动分析,以及一些调试信息

2014年01月15日 ⁄ 综合 ⁄ 共 8192字 ⁄ 字号 评论关闭

Flash 存储器接口还有两个标准:CFIJEDEC

CFI为公共Flash接口[Common
Flash Interface] 用来帮助程序从Flash芯片中获取操作方式信息,而不用在程序中硬编码FlashID

    JEDEC用来帮助程序读取Flash的制造商ID和设备ID,以确定Flash的大小和算法,如果芯片不支持CFI,就需使用JEDEC了。

    CFI Flash
    自从Intel公司于1988年推出了可快速擦写的非易失性存储器Flash   Memory以来,快速擦写存储器Flash Memory技术就得到了非常迅速的发展。这主要是由于Flash  
Memory具有不需要存储电容器、集成度更高、制造成本低于DRAM、使用方便,读写灵活、访问速度快、断电后不丢失信息等特点。

    虽然Flash  Memory应用越来越广泛,但由于生产Flash  
Memory的半导体制造商众 多,不同厂商Flash  Memory产品的操作命令集和电气参数又千差万别,这给Flash   Memory的开发设计人员和OEM制造商带来许多不便。为了对现有的Flash   Memory的产品进行升级或使用其它公司的Flash 
Memory产品替换,必须对原有的程序代码和硬件结构进行修改。为解决上述原因所引发的问题,迫切需要Flash  
Memory制造商提出一个公共的标准解决方案,在这样的背景下,公共闪存接口(Common
Flash  Interface),简称CFI 诞生了,CFI是一个公开的标准的从Flash   Memory器件中读取数据的接口。它可以使系统软件查询已安装的Flash   Memory器件的各种参数,包括器件阵列结构参数、电气和时间参数以及器件支持的功能等。利用CFI可以不用修改系统软件就可以用新型的和改进的产品代替旧版本的产品。例如:如果新型的Flash  
Memory的擦除时间只有旧版本的一半,系统软件只要通过CFI读取新器件的擦除时间等参数,修改一下定时器的时间参数即可。

JEDEC
    Joint Electron Device Engineering Council 即电子元件工业联合会。JEDEC是由生产厂商们制定的国际性协议,主要为计算机内存制定。工业标准的内存通常指的是符合JEDEC标准的一组内存。

 

u-boot-2009.03为例U-Boot本身支持CFI接口规范的闪存涉及到的文件主要包括drivers/mtd/cfi-flash.ccomrhand/cmd_flash.c

 

假设要使用两片Intel
28F128K18C的兼容CFI标准的NOR型闪存,单片容量为16MB,数据线宽度为16-bit,两片并作一个32MB容量的数据宽度为32-bitBANK来使用。在头文件include/flash.h中没有定义该芯片的相关信息,可以手动添加;这并不是必须的,如果你并不需要使用这些信息的话(例如将CFI驱动所检测到的Device Id与头文件中定义的Device
ID进行比对与验证)

 

/* file : include/flash.h */

 

#define INTEL_ID_28F128K18 0x88068806 /* added by aaron */

 

#define FLASH_28F128K18 0x00BA /*Intel 28F128K18
(128M=8Mx16)*/

 

要使用U-Boot自带的CFI闪存驱动,必须要作的是在include/configs/ xxxxh中添加:

 

#define CFG_FLASH_CFI

 

#define CFG_FLASH_CFI_DRIVER 1

 

/* avoid long time detection, added by aaron ,see
include/flash.h */

 

#define CFG_FLASH_CFI_WIDTH FLASH_CFI_32BIT

 

 

#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks
*/

 

#define CFG_MAX_FLASH_SECT 128 /*max number of sectors on
one chip*/

 

 

/* timeout values are in ticks */

 

#define CFG_FLASH_ERASE_TOUT (25*CFG_HZ) /*Timeout for Flash
Erase */

#define CFG_FLASH_WRITE_TOUT (25*CFG_HZ) /*Timeout for Flash
Write */

 

/* write flash less slowly */

 

#define CFG_FLASH_USE_BUFFER_WRITE 1

 

另外,如果把环境变量保存在FLASH中,还有如下相关定义:

/* NOTE: many default partitioning schemes assume the kernel
starts at

 

* the second sector, not an environment. You have been
warned!

 

*/

 

#define CFG_MONITOR_BASE 0

 

#define CFG_MONITOR_LEN PHYS_FLASH_SECT_SIZE

 

#define CFG_ENV_IS_IN_FLASH 1

 

#define CFG_ENV_ADDR (PHYS_FLASH_1 + PHYS_FLASH_SECT_SIZE)

 

#define CFG_ENV_SECT_SIZE PHYS_FLASH_SECT_SIZE

 

#define CFG_ENV_SIZE (PHYS_FLASH_SECT_SIZE / 16)

 

/* If defined, hardware flash sectors protection is used instead
of

 

* U-Boot software protection. */

 

#define CFG_FLASH_PROTECTION

 

 

 

 

手头有一块板子采用1NOR型闪存 s29gl064N,数据线宽度为16
bit 容量8 MB。下面分析了u-bootflash相关的驱动代码,并在u-boot 下将cfi_flash.c 的调试开关打开,记录了一些调试打印信息。

 

初始化cfi_flash.c/
flash_init ()代码分析

flash_init (void)

{

    flash_get_size
(BANK_BASE(i), i);

       
--->flash_detect_cfi

        --->flash_printqry
(&qry);

       
--->cmdset_amd_init

           
--->cmdset_amd_read_jedec_ids

}

 

u-boot的调试打印

flash detect cfi                           

 

__flash_detect_cfi()函数 先确认模式 8bit x
8 bit 16bit x 8 bit发送 16bit x 16
bit 依次发送'Q' 'R' 'Y'

fwc addr 60000000 cmd f0 f0 8bit x 8 bit    调用了

fwc addr 60000000 cmd ff ff 8bit x 8 bit

fwc addr 60000055 cmd 98 98 8bit x 8 bit

is= cmd 51(Q) addr 60000010 is= 0 51

fwc addr 60000555 cmd 98 98 8bit x 8 bit

is= cmd 51(Q) addr 60000010 is= 0 51

fwc addr 60000000 cmd f0 f0f0 16bit x 8 bit

fwc addr 60000000 cmd ff ffff 16bit x 8 bit

fwc addr 600000aa cmd 98 9898 16bit x 8 bit

is= cmd 51(Q) addr 60000020 is= 0051 5151

fwc addr 60000aaa cmd 98 9898 16bit x 8 bit

is= cmd 51(Q) addr 60000020 is= 0051 5151

fwc addr 60000000 cmd f0 00f0 16bit x 16 bit

fwc addr 60000000 cmd ff 00ff 16bit x 16 bit

fwc addr 600000aa cmd 98 0098 16bit x 16 bit

is= cmd 51(Q) addr 60000020 is= 0051 0051

is= cmd 52(R) addr 60000022 is= 0052 0052

is= cmd 59(Y) addr 60000024 is= 0059 0059

 

device interface is 2

found port 2 chip 2 port 16 bits chip 16 bits

 

函数flash_printqry
(&qry);打印信息

00 : 51 52 59 02 00 40 00 00 00 00 00 27 36 00 00 07  QRY..@.....'6...     

10 : 07 0a 00 03 05 04 00 17 02 00 05 00 01 7f 00 00  ................

20 : 01 00 00 00 00 00 00 00 00 00 00 00 00 55 55 55  .............UUU

 

函数cmdset_amd_init打印信息

fwc addr 60000000 cmd f0 00f0 16bit x 16 bit                             

fwc addr 60000aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60000554 cmd 55 0055 16bit x 16 bit

fwc addr 60000aaa cmd 90 0090 16bit x 16 bit

fwc addr 60000000 cmd f0 00f0 16bit x 16 bit

fwc addr 600000aa cmd 98 0098 16bit x 16 bit

 

manufacturer is 2

manufacturer id is 0x1

device id is 0x227e

device id2 is 0x0

cfi version is 0x3133

size_ratio 1 port 16 bits chip 16 bits

found 1 erase regions

erase region 0: 0x0100007f

erase_region_count = 128 erase_region_size = 65536

fwc addr 60000000 cmd f0 00f0 16bit x 16 bit

 

 

 

flash擦出cfi_flash.c/flash_erase()函数代码分析

int flash_erase (flash_info_t * info, int s_first, int
s_last)

{

    case
CFI_CMDSET_AMD_STANDARD:

    case
CFI_CMDSET_AMD_EXTENDED:

            flash_unlock_seq (info, sect);

            flash_write_cmd (info, sect,

                                    info->addr_unlock1,

                                    AMD_CMD_ERASE_START);

            flash_unlock_seq (info, sect);

            flash_write_cmd (info, sect, 0,

                                     AMD_CMD_ERASE_SECTOR);

}                     

             

u-boot的调试打印

NPU3CR => erase 60600000 +50000

   

.fwc addr 60640aaa cmd aa 00aa 16bit x 16 bit           

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600aaa cmd 80 0080 16bit x 16 bit

fwc addr 60600aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600000 cmd 30 0030 16bit x 16 bit

flash_is_busy: 0

.fwc addr 60610aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60610554 cmd 55 0055 16bit x 16 bit

fwc addr 60610aaa cmd 80 0080 16bit x 16 bit

fwc addr 60610aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60610554 cmd 55 0055 16bit x 16 bit

fwc addr 60610000 cmd 30 0030 16bit x 16 bit

flash_is_busy: 0

.fwc addr 60620aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60620554 cmd 55 0055 16bit x 16 bit

fwc addr 60620aaa cmd 80 0080 16bit x 16 bit

fwc addr 60620aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60620554 cmd 55 0055 16bit x 16 bit

fwc addr 60620000 cmd 30 0030 16bit x 16 bit

flash_is_busy: 0

.fwc addr 60630aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60630554 cmd 55 0055 16bit x 16 bit

fwc addr 60630aaa cmd 80 0080 16bit x 16 bit

fwc addr 60630aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60630554 cmd 55 0055 16bit x 16 bit

fwc addr 60630000 cmd 30 0030 16bit x 16 bit   

flash_is_busy: 0

.fwc addr 60640aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60640554 cmd 55 0055 16bit x 16 bit

fwc addr 60640aaa cmd 80 0080 16bit x 16 bit

fwc addr 60640aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60640554 cmd 55 0055 16bit x 16 bit

fwc addr 60640000 cmd 30 0030 16bit x 16 bit   

. done

Erased 5 sectors

 

 

flash函数分析    

static int flash_write_cfiword (flash_info_t * info, ulong
dest, cfiword_t cword)

{

            switch
(info->vendor) {

            case
CFI_CMDSET_AMD_EXTENDED:

            case
CFI_CMDSET_AMD_STANDARD:

                        flash_unlock_seq
(info, sect);

                        flash_write_cmd
(info, sect, info->addr_unlock1, AMD_CMD_WRITE);

                       

    switch
(info->portwidth) {

            case
FLASH_CFI_8BIT:

                        flash_write8(cword.c,
dstaddr);

                        break;

            case
FLASH_CFI_16BIT:

                        flash_write16(cword.w,
dstaddr);

                        break; 

           

            return
flash_full_status_check (info, sect, info->write_tout, "write");

           

                       

}

 

u-boot的调试打印

Copy to Flash...

fwc addr 60600aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600aaa cmd a0 00a0 16bit x 16 bit

flash_is_busy: 0

fwc addr 60600aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600aaa cmd a0 00a0 16bit x 16 bit

flash_is_busy: 0

fwc addr 60600aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600aaa cmd a0 00a0 16bit x 16 bit

flash_is_busy: 0

fwc addr 60600aaa cmd aa 00aa 16bit x 16 bit

fwc addr 60600554 cmd 55 0055 16bit x 16 bit

fwc addr 60600aaa cmd a0 00a0 16bit x 16 bit

flash_is_busy: 0

...

 

 

另外u-boot flash相关的命令的代码调用顺序如下分析:

 

cmd_flash.c中实现了三个功能:

flinfo命令

cmd_flash.c/do_flinfo

    ---->>
cfi_flash.c/flash_print_info()

   

erase命令

cmd_flash.c/do_flerase

    ---->>
cfi_flash.c/flash_erase()函数。

 

protect命令

cmd_flash.c/do_protect

    ---->>
flash_sect_erase

               
---->cfi_flash.c/flash_real_protect()前提定义了CONFIG_SYS_FLASH_PROTECTION

 

 

cmd_mem.c中实现了cp命令将内存中的内容cpflash   

do_mem_cp()

   
---->common/flash.c/flash_write(char *)env_buffer, flash_sect_addr, len);

       
---->cfi_flash.c/write_buff();

           
---->cfi_flash.c/flash_write_cfiword();

           

cmd_envedit.c    实现了envflash的操作

cmd_envedit.c/do_saveenv()

   
--->_do_setenv()

       
--->env_flash.c/saveenv()

           
--->cfi_flash.c/flash_sect_protect (0, flash_sect_addr, end_addr));

               
cfi_flash.c/flash_sect_erase (flash_sect_addr, end_addr));

               
common/flash.c/flash_write(char *)env_buffer, flash_sect_addr, len);

                   
---->cfi_flash.c/write_buff();

                       
---->cfi_flash.c/flash_write_cfiword();

                   

                    

抱歉!评论已关闭.