#include #include "type.h" //#include "stm32f4xx_spi.h" //#include "stm32f4xx_gpio.h" //#include "stm32f4xx_hal.h" #include "stm32f4xx_spi.h" #include "stm32f4xx_gpio.h" #include "config.h" #include "os_task.h" #include "delay.h" #include "flash.h" #include "sys_config.h" #if USE_SPI_FLASH #define SST25_SECTOR_PER_SIZE (4096) //一个扇区为4kB #define SST25_TOTAL_SIZE (4*1024*1024*2/8) //总大小为4Mb 512*2KB 128个扇区 #define SST25_TOTAL_SECTOR_NUM (SST25_TOTAL_SIZE/SST25_SECTOR_PER_SIZE) #define FLASH_SPI SPI1 #define SST25_SELECT() do{GPIO_ResetBits(GPIOA,GPIO_Pin_4);}while(0) #define SST25_DESELECT() do{GPIO_SetBits(GPIOA,GPIO_Pin_4);}while(0) #define SST25_READDATA 0x03 #define SST25_FASTREADDATA 0x0B #define SST25_4KBYTE_BLOCKERASE 0x20 #define SST25_32KBYTE_BLOCKERASE 0x52 #define SST25_64KBYTE_BLOCKERASE 0xD8 #define SST25_CHIPERASE 0xC7 #define SST25_BYTEPORGRAM 0x02 #define SST25_AAI_WORDPROGRAM 0xAD #define SST25_READSTATUSREG 0x05 #define SST25_ENABLEWRITESTATUSREG 0x50 #define SST25_WRITESTATUSREG 0x01 #define SST25_WRITEENABLE 0x06 #define SST25_WRITEDISABLE 0x04 #define SST25_DEVICEID 0x90 #define SST25_JEDECDEVICEID 0x9F #define SST25_EBSY 0x70 #define SST25_DBSY 0x80 //extern SPI_HandleTypeDef hspi1; static uint8 spi1_read_byte(void) { while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(FLASH_SPI,0xff); while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET); return (SPI_I2S_ReceiveData(FLASH_SPI)); } static void spi1_write_byte(uint8 byte) { while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(FLASH_SPI, byte); while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET); (void)SPI_I2S_ReceiveData(FLASH_SPI); } /****************************************** 写一个命令 ******************************************/ void sst25_write_cmd(uint8 cmd) { SST25_SELECT(); spi1_write_byte(cmd); SST25_DESELECT(); } /****************************************** 写一个命令一个数据 ******************************************/ void sst25_write_cmd_data(uint8 cmd,uint8 data) { SST25_SELECT(); spi1_write_byte(cmd); spi1_write_byte(data); SST25_DESELECT(); } /****************************************** 写一个命令三个数据 ******************************************/ void sst25_write_cmd_data3(uint8 cmd, uint8* data) { SST25_SELECT(); spi1_write_byte(cmd); spi1_write_byte(*data++); spi1_write_byte(*data++); spi1_write_byte(*data); SST25_DESELECT(); } /****************************************** 写一个命令返回一个数据 ******************************************/ uint8 sst25_read_data(uint8 cmd) { uint8 temp; SST25_SELECT(); spi1_write_byte(cmd); temp = spi1_read_byte(); SST25_DESELECT(); return temp; } /****************************************** 写一个命令,三个地址 返回多个数据 ******************************************/ void sst25_read_datas(uint8 cmd,uint8 *addr,uint8 *data,uint32 no) { uint16 i; SST25_SELECT(); spi1_write_byte(cmd); spi1_write_byte(*addr++); spi1_write_byte(*addr++); spi1_write_byte(*addr); for(i=0;i>16)&0xff); ad[1] = ((addr>>8)&0xff); ad[2] = (addr&0xff); sst25_writesr(0x02); sst25_wren(); SST25_SELECT(); spi1_write_byte(SST25_4KBYTE_BLOCKERASE); spi1_write_byte(ad[0]); spi1_write_byte(ad[1]); spi1_write_byte(ad[2]); SST25_DESELECT(); sst25_wait_busy(); } /****************************************** SST25 写入一个字节 ******************************************/ void sst25_byte_write(uint32 addr,uint8 byte) { sst25_writesr(0x02); sst25_wren(); SST25_SELECT(); spi1_write_byte(SST25_BYTEPORGRAM); spi1_write_byte((addr>>16)&0xff); spi1_write_byte((addr>>8)&0xff); spi1_write_byte(addr&0xff); spi1_write_byte(byte); SST25_DESELECT(); sst25_wait_busy(); } /****************************************** SST25 写入多个字节 ******************************************/ void sst25_datas_write(uint32 addr,uint8 *buf,uint32 no) { uint32 cnt; if(no == 0) return; sst25_writesr(0x02); sst25_wren(); if(no == 1) { sst25_byte_write(addr,*buf); } else { cnt = no; SST25_SELECT(); spi1_write_byte(SST25_AAI_WORDPROGRAM); spi1_write_byte((addr>>16)&0xff); spi1_write_byte((addr>>8)&0xff); spi1_write_byte(addr&0xff); spi1_write_byte(*buf++); spi1_write_byte(*buf++); SST25_DESELECT(); cnt-=2; sst25_wait_busy(); for(;cnt>1;cnt-=2) { SST25_SELECT(); spi1_write_byte(SST25_AAI_WORDPROGRAM); spi1_write_byte(*buf++); spi1_write_byte(*buf++); SST25_DESELECT(); sst25_wait_busy(); } sst25_wrdi(); if(cnt == 1) { sst25_wren(); sst25_byte_write(addr+no-1,*buf); } } sst25_wpen(); } /****************************************** SST25 高速读 ******************************************/ void sst25_readh(uint32 addr,uint8 *buf,uint32 no) { uint16 i; SST25_SELECT(); spi1_write_byte(SST25_FASTREADDATA); spi1_write_byte((uint8)(addr>>16)&0xff); spi1_write_byte((uint8)(addr>>8)&0xff); spi1_write_byte((uint8)addr&0xff); spi1_write_byte(0xff); for(i=0;i>16)&0xff; ad[1] = (addr>>8)&0xff; ad[2] = addr&0xff; sst25_read_datas(SST25_READDATA,ad,buf,no); } void flash_write_byte(uint8 byte,uint32 addr) { uint32 secpos; secpos = addr/SST25_SECTOR_PER_SIZE; if(secpos>=SST25_TOTAL_SECTOR_NUM) return; sst25_sector_erase(secpos); sst25_byte_write(addr,byte); } void flash_write_buf(uint8 *buf,uint32 num,uint32 addr) { uint32 secpos; secpos = addr/SST25_SECTOR_PER_SIZE; if(secpos >= SST25_TOTAL_SECTOR_NUM) return; if(addr+num>SST25_TOTAL_SIZE) num = SST25_TOTAL_SIZE - addr; sst25_datas_write(addr, buf, num); } void flash_erase_sector(uint32 start_address,uint32 num) { uint32 secpos,secoff,secremain; uint16 secnum=0; int32 i = 0; secpos = start_address/SST25_SECTOR_PER_SIZE; if(secpos >= SST25_TOTAL_SECTOR_NUM) return; if(start_address+num>SST25_TOTAL_SIZE) num = SST25_TOTAL_SIZE - start_address; secoff = start_address%SST25_SECTOR_PER_SIZE; secremain = SST25_SECTOR_PER_SIZE-secoff; if(num < secremain) { secnum = 1; } else { secnum = 1; i = num -secremain; do { secnum++; i = i - SST25_SECTOR_PER_SIZE; }while(i>0); } for(i=0;i= SST25_TOTAL_SIZE) return; sst25_readl(addr,buf,len); } #endif