高杉LEGAL 2018-02-05


如上图所示,MCU通过SPI2与外部flash芯片进行相连接。

定义SPI2中所使用的SPI端口号

spi2中通信功能初始化
查看flash芯片的datasheet,mx25芯片支持按照页来写,按照扇区来擦除。page_program为 0x02 ,sector_erase为0x20。并且在向每个页中写数据前,必须先保证此页所在的扇区已经进行擦除操作。并且每一页最大写256byte ,一个扇区的大小为4Kbyte
依据芯片写指令 0x06
void spi_flash_write_page(uint8_t* pBuffer,uint32_t write_address,uint16_t num_byte_to_write) //向页中写入数据,其中write_address必须为256的整数据部,即一页的开始位置,
{
uint16_t i=0;
// debug_out("SpiPage:0x%08x Len:%d\r\n", write_address, num_byte_to_write);
spi_flash_wait_busy(); //忙等待
spi_flash_write_enable();
spi_flash_wait_busy();
spi2_cs_low();
spi2_read_write_byte(MX25_PAGE_PROGRAM);
spi2_read_write_byte((uint8_t) ( ((write_address) >> 16 )&0xFF) );
spi2_read_write_byte((uint8_t) ( ((write_address) >> 8 )&0xFF) );
spi2_read_write_byte((uint8_t) ( (write_address)&0xff ) );
for(i=0;i<num_byte_to_write;i++)
{
spi2_read_write_byte(pBuffer[i]);
}
spi2_cs_high();
spi_flash_wait_busy();
}void spi_flash_erase_sector(uint32_t addr) //addr地起为4K的倍数,清除一个扇区
{
spi_flash_wait_busy();
spi_flash_write_enable();
spi_flash_wait_busy();
//½øÐвÁ³ý²Ù×÷
spi2_cs_low();
spi2_read_write_byte(MX25_SECTOR_ERASE);
spi2_read_write_byte((uint8_t) ( ((addr) >> )&0xFF) );
spi2_read_write_byte((uint8_t) ( ((addr) >> )&0xFF) );
spi2_read_write_byte((uint8_t) ( (addr)&0xff ) );
spi2_cs_high();
spi_flash_wait_busy();
}从指定地址,写入指定长度数据。也是从一个扇区的开始处进行写,计算出一共需要写入多少页,同时如果为一个扇区的开始处,记得需要进行扇区擦除操作。
void spi_flash_write(uint8_t* pBuffer,uint32_t address,uint16_t buffer_len)
{
uint16_t pageCount = ;
uint16_t pageIndex = ;
uint16_t length = ;
uint16_t i=;
pageCount = buffer_len / SPI_FLASH_PAGE_SIZE;
if( ( buffer_len % SPI_FLASH_PAGE_SIZE ) != )
{
pageCount += ;
}
while( pageIndex < pageCount )
{
length = buffer_len - ( pageIndex * SPI_FLASH_PAGE_SIZE ) ;
length = length > SPI_FLASH_PAGE_SIZE ? SPI_FLASH_PAGE_SIZE : length;
if( ( ( address + pageIndex * SPI_FLASH_PAGE_SIZE ) % SPI_FLASH_SECTOR_SIZE ) == )
{
spi_flash_erase_sector( address + pageIndex * SPI_FLASH_PAGE_SIZE );
}
spi_flash_write_page(pBuffer + pageIndex * SPI_FLASH_PAGE_SIZE, address + pageIndex * SPI_FLASH_PAGE_SIZE, length );
pageIndex ++;
}
}读数据相对于写数据来说,显得比较简单的多,从指定地址开始读,读取指定的长度
void spi_flash_read(uint8_t* pBuffer,uint32_t read_address,uint16_t num_byte_to_read)
{
uint16_t i=0;
spi_flash_wait_busy();
spi2_cs_low();
spi2_read_write_byte(MX25_READ_DATA);
spi2_read_write_byte((uint8_t) ( ((read_address) >> 16 )&0xFF) );
spi2_read_write_byte((uint8_t) ( ((read_address) >> 8 )&0xFF) );
spi2_read_write_byte((uint8_t) ( (read_address)&0xff ) );
for(i=0;i<num_byte_to_read;i++)
{
pBuffer[i]=spi2_read_write_byte(0xFF);
}
spi2_cs_high();
}至此整个驱动编写完成。