SPI Flash的擦写注意事项


从规格书上看,SPI flash一般支持3种擦写方式:按sector擦写,按block擦写,整片chip擦写。

以KH25L3255E为例,

•      Serial Peripheral Interface compatible -- Mode 0 and Mode 3
•      33,554,432 x 1 bit structure or 16,777,216 x 2 bits (two I/O mode) structure or 8,388,608 x 4 bits (four I/O
mode) structure
•      1024 Equal Sectors with 4K bytes each
     - Any Sector can be erased individually
•     128 Equal Blocks with 32K bytes each
     - Any Block can be erased individually
•     64 Equal Blocks with 64K bytes each
     - Any Block can be erased individually
•     Power Supply Operation
- 2.7 to 3.6 volt for read, erase, and program operations
• Latch-up protected to 100mA from -1V to Vcc +1V

由此可以看出,KH25L3255E的sector大小是4K,block大小是32K/64K.因此,可以一次性擦除4K/32K/64K.

三种擦写方式的性能比较:
- Fast erase time: 30ms (typ.)/sector (4K-byte per sector) ; 0.25s(typ.) /block (64K-byte per block); 10s(typ.) /    
chip
从上述数据看,擦除同样大小的情况下,执行时间 sector>block>chip
按sector擦写,擦完64K需要0.48s,而按block一次性擦写64K只需要0.25s;按block擦写,擦完整片chip需要16s,而按chip擦写只需要10s;按sector擦写完整片chip需要30s。


从linux/drivers/mtd/devices/m25p80.c看,m25p_probe函数在选择擦写单位时,是倾向于选择小单位的,会优先选择4K,如下:
    /* prefer "small sector" erase if possible */
    if (info->flags & SECT_4K) {
        flash->erase_opcode = OPCODE_BE_4K;
        flash->mtd.erasesize = 4096;
    } else {
        flash->erase_opcode = OPCODE_SE;
        flash->mtd.erasesize = info->sector_size;
    }

这在在用户空间体现在,使用mtd工具或者ioctl读取erasesize时读到的是sector(4K),如下:
 
# mtd_debug info /dev/mtd0
mtd.type = MTD_NORFLASH
mtd.flags = MTD_CAP_NORFLASH
mtd.size = 2883584 (2M)
mtd.erasesize = 4096 (4K)
mtd.writesize = 1
mtd.oobsize = 0
regions = 0

# mtdinfo /dev/mtd0
mtd0
Name:                           flash0.bolt
Type:                           nor
Eraseblock size:                4096 bytes, 4.0 KiB
Amount of eraseblocks:          704 (2883584 bytes, 2.8 MiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:0
Bad blocks are allowed:         false
Device is writable:             true


若想要将erasesize改成block大小,需要修改驱动,例如,将上述m25p80.c中的配置成SECT_4K的相关地方改成0,驱动就会使用block大小。
另外,需要注意的是,m25p80.c中“sector”和“block”的概念搞反了,里面的“block”才是规格书中的sector,一般是4K,请见OPCODE_BE_4K和OPCODE_SE两个宏定义处。


mtd.erasesize的大小会对应用上有一些影响,比较重要的一点是在制作某些嵌入式文件系统的镜像文件时,需要设置擦除单位,如果设置的擦除单位和驱动中的不符,会导致文件系统无法正常工作。
另外,porting层设置spi的擦写单位时,也需要注意当前实际的erasesize。

案例(解决方法就是修改驱动将spi-mtd的erasesize改成block大小,使其和jffs2的擦写单位一致):
http://bbs.csdn.net/topics/390299487/
《制作JFFS2时的erase_block与SPI FLASH中的erase_sector的关系?》

如题, 在制作JFFS2时 需要用到-e 参数(./mkfs.jffs2 -b --pad=524288  -s 256 -e 65536 -d userfs/ -o usrjffs2.img)help命令中,对其的解释为: -e, --eraseblock=SIZE   Use erase block size SIZE (default: 64KiB)。

在SPI FLASH(winbond 8M)的datasheet中写到:其erase_sector只能为4KB,erase_block可为32/64kB,

目前在SPI的驱动中,设置block_size为 64KB, erase_sector为 4KB。

问题来了!

将制作好的512K FLASH挂载到系统上后,会报如下错误:
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00022034: 0x5771 instead
Further such events for this erase block will not be printed
Node at 0x00022f60 with length 0x000000f6 would run over the end of the erase block
Perhaps the file system was created with the wrong erase size?
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00023000: 0x69c2 instead
进入系统后,发现jffs2中的文件有缺失。


根据报错提示以及网上资料, 原因应该为: 制作JFFS2时的erase_block 与系统的不符~.

但系统这块的block_size(这个应该也就是erase_block的大小吧?)已经是设置成64KB的了。

更改SPI驱动中,erase_sector的大小为64KB,则JFFS2报错问题解决, 但由于该SPI FLASH的
erase_sector是固定死的4K,贸然使用64KB(32KB同样)会造成再擦写FLASH时,极大概率出现某
一erase_secotr大小的块中数据为空的情况,即系统不能启动。

另,在制作JFFS2时,将-e参数设置为4096,以配合FLASH的erase_sector, 但悲催的是mkfs.jffs2
所支持-e 最小为8KB。

请问现在这个报错问题应该如何解决???

一点细节: 尝试添加了 -s 参数,其大小为FLASH page的大小256B,但问题依旧。

当JFFS2中文件较少时,不知为何就不会出现上方的报错。

=================================================

还有一个要注意的问题是,在涉及到spi-flash的erasesize的软件设计时,需要注意bootloader/app中的erasesize是否一致。
例如,7252 bolt中spi的默认erasesize是64K,而app中的erasesize是4K.因此,数据的存储的对齐地址一定要注意要保持一致,不能单纯的使用erasesize对齐,例如,
存储17K的DATA1和3K的DATA2,若按着erasesize对齐,在bolt中 [0, 64K]分给DATA1,[64K, 128K]分给DATA2,而在应用程序中,[0, 20K]分给了DATA1,[20K, 24K]分给了
DATA2. 如此便不一致了。

你可能感兴趣的:(Linux,Flash存储)