本节主要介绍串行SPI flash驱动的移植。eCos中,flash支持比较完善,移植flash驱动也不是件难事。虽说如此,在本次移植spi接口flash时,还是遇到了一些意外问题,而且正是由于这个意外问题,让我解决了在移植STM32 ADC驱动时遇到的一个棘手问题:
只要我在eCos图形配置工具中打开了ADC的任何一个通道,则不能生成正常的bin格式映像文件(生成的bin文件超大,大小达到了不可思议的1.2GB大小,但可生成正常的srec格式映像文件);如果不打开ADC任何一个通道,则可以输出正常的bin格式文件。虽然这个问题后面用暴力解决了,但问题原因没有搞清楚,所以一直悬在心里。
选择SPI flash驱动模板
最新eCos代码支持3种系列类型SPI flash,分别是:at25dfxxx、m25pxx和sst25xx。为简化移植,根据使用的SPI FLASH芯片,从这3个系列中选择一个在命令、SPI时序、存储结构等参数上比较接近的SPI FLASH驱动作为模板,然后在此基础上进行修改。我板子上使用的SPI FLASH为MX25L1606E,16M bits大小,它与m25pxx系列非常接近,如下图所示。故选用m25pxx SPI FLASH驱动作为模板,在此基础上进行一些简单修改。
驱动模板修改
MX25L1606E与m25pxx SPI FLASH存在的区别:
- Sector erase对应的命令不一样;
- 相同大小的flash,每个sector包含的page数量、总sector数不一样;
- 当然,jedec id肯定是不一样;
- MX25L1606E似乎为了做兼容,兼容更多其它flash使用的命令;
针对上面的区别,修改m25pxx.c文件:
修改Sector erase命令的定义,即修改宏M25PXX_CMD_SE对应的值为0x20:
typedef enum m25pxx_cmd { M25PXX_CMD_WREN = 0x06, // Write enable. M25PXX_CMD_WDRI = 0x04, // Write disable. M25PXX_CMD_RDID = 0x9F, // Read identification. M25PXX_CMD_RDSR = 0x05, // Read status register. M25PXX_CMD_WRSR = 0x01, // Write status register. M25PXX_CMD_READ = 0x03, // Read data. M25PXX_CMD_FREAD = 0x0B, // Read data (fast transaction). M25PXX_CMD_PP = 0x02, // Page program. M25PXX_CMD_SE = 0x20, //0xD8, // Sector erase. // Modified for MX25L1606E by reille 2013.05.26 M25PXX_CMD_BE = 0xC7, // Bulk erase. M25PXX_CMD_RES = 0xAB, // Read electronic signature. } m25pxx_cmd;
修改flash对应的每个sector包含的page数量、总sector数以及jedec id,即修改m25pxx_supported_devices数据中对应flash大小的flash参数:
{ // Support for Numonyx 16 MBit devices. sector_size : 16, // 256, // Modified for MX25L1606E by reille 2013.05.26 sector_count : 512, // 32, // Modified for MX25L1606E by reille 2013.05.26 jedec_id : 0x00C22015, // 0x00202015 // Modified for MX25L1606E by reille 2013.05.26 },
添加flash驱动实例
上面只是完成了SPI FLASH驱动,只有驱动是不行的,还要在target模板中建立一个SPI FLASH驱动实例。
打开ecos/packages/hal/cortexm/stm32/stm32f10xxx/current/src/stm32f0xxx_flash.c文件(stm32f10xxx是我使用的target,所以实际中要修改为你使用的target),在这个文件中添加一个SPI FLASH驱动实例:
// Add SPI FLASH | added by reille 2013.05.26 #ifdef CYGPKG_DEVS_FLASH_SPI_M25PXX #include <cyg/io/m25pxx.h> //----------------------------------------------------------------------------- // Set up the SPI intertface on the ST STM32F10XXX board for the STM32. The // M25PXX device is connected to SPI bus 1. SPI1 should be set up in configtool // so that chip select 1 corresponds to GPIO number 18 (PB2) and 50MHz I/O is // enabled. If the data area is in external RAM, SPI1 must be configured with // bounce buffers of at least 256 bytes and the M25PXX read data block size // should be set to the same size as the bounce buffers. #ifdef CYGPKG_HAL_CORTEXM_STM32_STM32F10XXX #include <cyg/io/spi_stm32.h> CYG_DEVS_SPI_CORTEXM_STM32_DEVICE ( m25pxx_spi_device, 1, 0, false, 0, 0, 25000000, 1, 1, 1 ); #endif //----------------------------------------------------------------------------- // Instantiate the M25Pxx device driver. CYG_DEVS_FLASH_SPI_M25PXX_DRIVER ( m25pxx_flash_device, 0x65000000, &m25pxx_spi_device ); #endif /* CYGPKG_DEVS_FLASH_SPI_M25PXX */
特别注意上面的英文注释,这个需要使用图形配置工具配置相应的参数,见下面所述。
另外,在 stm32f0xxx_flash.c文件,我们可以看到,这里还定义了NOR FLASH实例。
STM32 SPI驱动和SPI FLASH驱动配置
根据添加驱动实例时的注释信息,当程序在外部RAM中运行时,需要配置STM32 SPI驱动的Bounce buffer size和SPI FLASH驱动的Maximum read block size,如下图所示:
上述弄好后,重新编译得到映像文件。
生成bin格式映像文件问题
非常奇怪,这时生成的bin格式映像文件异常,大小只有4KB大小,这让我联想到了当初移植STM32 ADC驱动出现的问题,详见:stm32移植ecos #17,ADC驱动和应用编程(上)和stm32移植ecos #18,ADC驱动和应用编程(下)。
为解决这个问题,当初花了不少时间,但都没能解决。本次,还写了一封E-mail到eCos的discuss邮件列表,寻求帮助,遗憾的是,没有人给我解答。不得以,自己想办法解决它,而且也解决了,请看下节。
{ // Support for Numonyx 16 MBit devices.
2
sector_size : 16, // 256, // Modified for MX25L1606E by reille 2013.05.26
3
sector_count : 512, // 32, // Modified for MX25L1606E by reille 2013.05.26
4
jedec_id : 0x00C22015, // 0x00202015 // Modified for MX25L1606E by reille 2013.05.26
5
},
,16Mbit, 是也就是2MB, 根据你改的, 这里分成512个扇区, 每个扇区16xxx, 这里是16的单位是什么?Byte还是bit, 还是其他?
16*512等于8192, 。。。这就好像不对了
看下struct m25pxx_params结构体的定义,其中,16表示每个sector对应的page数量,每个page大小由宏M25PXX_PAGE_SIZE决定,也就是256字节,因此,total size = 512 * (16 * 256) = 2097152 bytes
This artclie is a home run, pure and simple!