/******************************************************************************* * Function Name : P25Q40H FLASH -- 4M bit == 512K*8bit * Description : Flash驱动程序 *******************************************************************************/ #include "includes.h" /******************************************************************************* * Function Name : Flash_Init * Description : P25Q40H Flash初始化 * Input : None * Return : None *******************************************************************************/ void Flash_Init(void) { #if (USE_CORE_TYPE == 1) //使用C1F核心板 //设置SPI0 GPIO //GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeOut_PP_5mA); //WP //GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_20mA); //CS GPIOA_ModeCfg(GPIO_Pin_13|GPIO_Pin_14, GPIO_ModeOut_PP_5mA); //SCK,MOSI GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU); //MISO //SPI 主机模式 //SPI0_MasterDefInit( ); //Flash_WP_H; //硬件写保护引脚拉高 Flash_CS_H; #elif (USE_CORE_TYPE == 2) //使用C1核心板 //设置SPI0 GPIO GPIOA_ModeCfg(GPIO_Pin_3, GPIO_ModeOut_PP_5mA); //WP GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_20mA); //CS GPIOA_ModeCfg(GPIO_Pin_13|GPIO_Pin_14, GPIO_ModeOut_PP_5mA); //SCK,MOSI GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU); //MISO //SPI 主机模式 //SPI0_MasterDefInit( ); Flash_WP_H; //硬件写保护引脚拉高 Flash_CS_H; #endif //USE_CORE_TYPE == CORE_TYPE_C1F } /******************************************************************************* * Function Name : Flash_ReadSR * Description : P25Q40H Flash读取状态寄存器 * Input : None * Return : P25Q40H Flash状态寄存器值 BIT7 6 5 4 3 2 1 0 SPR0 BP4 BP3 BP2 BP1 BP0 WEL WIP SPR:默认0,状态寄存器保护位,配合WP使用 BP4,BP3,BP2,BP1,BP0:FLASH区域写保护设置 WEL:写使能锁定 BUSY:忙标记位(1,忙;0,空闲) 默认:0x00 *******************************************************************************/ uint8_t Flash_ReadSR(void) { uint8_t byte = 0; Flash_CS_L; SPI0_MasterSendByte(P24Q40H_ReadStatusReg); //发送读取状态寄存器命令 byte = SPI0_MasterRecvByte(); Flash_CS_H; return byte; } /******************************************************************************* * Function Name : Flash_WriteSR * Description : P25Q40H Flash写状态寄存器 * Input : sr_val:写入状态寄存器的值 BIT7 6 5 4 3 2 1 0 SPR0 BP4 BP3 BP2 BP1 BP0 WEL WIP 只有SPR0,BP3,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! * Return : None *******************************************************************************/ void Flash_WriteSR(uint8_t sr_val) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_WriteStatusReg); SPI0_MasterSendByte(sr_val); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_Write_Enable * Description : P25Q40H 写使能 -- 将WEL置位 * Input : None * Return : None *******************************************************************************/ void Flash_Write_Enable(void) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_WriteEnable); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_Write_Disable * Description : P25Q40H 写禁止 -- 将WEL清零 * Input : None * Return : None *******************************************************************************/ void Flash_Write_Disable(void) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_WriteDisable); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_ReadID * Description : P25Q40H Flash 读取芯片ID * Input : None * Return : 返回值如下: 0x8512:表示芯片型号为P25Q40H 0x8511:表示芯片型号为P25Q20H 0x8510:表示芯片型号为P25Q10H 0x8509:表示芯片型号为P25Q05H *******************************************************************************/ uint16_t Flash_ReadID(void) { uint16_t temp=0; Flash_CS_L; SPI0_MasterSendByte(P24Q40H_ReadManufactureID); SPI0_MasterRecvByte(); SPI0_MasterRecvByte(); SPI0_MasterRecvByte(); temp |= SPI0_MasterRecvByte(); temp |= SPI0_MasterRecvByte()<<8; Flash_CS_H; return temp; } /******************************************************************************* * Function Name : Flash_Wait_Busy * Description : 等待空闲 * Input : None * Return : 1:等待超时,处于繁忙状态 0:空闲状态 *******************************************************************************/ uint8_t Flash_Wait_Busy(void) { uint8_t temp=0; uint16_t i=0; temp = Flash_ReadSR(); while((temp&0x01)==0x01) { DelayUs(100); temp = Flash_ReadSR(); i++; if(i>3000) return 1; }; return 0; } /******************************************************************************* * Function Name : Flash_PowerDown * Description : Flash 进入掉电模式 * Input : None * Return : None *******************************************************************************/ void Flash_PowerDown(void) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_PowerDown); DelayUs(3); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_PowerDown * Description : Flash 唤醒掉电模式 * Input : None * Return : None *******************************************************************************/ void Flash_Wakeup(void) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_ReleasePowerDown); DelayUs(3); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_Erase_Chip * Description : 擦除整个芯片 * Input : None * Return : None *******************************************************************************/ void Flash_Erase_Chip(void) { Flash_Write_Enable(); Flash_Wait_Busy(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_ChipErase); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Erase_Block * Description : 擦除块 * Input : BLK_ID:块号(0~31) 2M * Return : None *******************************************************************************/ void Flash_Erase_Block(uint32_t BLK_ID) { BLK_ID*=0x10000; //64K Flash_Write_Enable(); Flash_Wait_Busy(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_BlockErase); SPI0_MasterSendByte((uint8_t)((BLK_ID)>>16)); SPI0_MasterSendByte((uint8_t)((BLK_ID)>>8)); SPI0_MasterSendByte((uint8_t)BLK_ID); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Erase_Sector * Description : 擦除扇区 * Input : DST_Addr:扇区号(0~511) 2M * Return : None *******************************************************************************/ void Flash_Erase_Sector(uint32_t DST_ID) { DST_ID*=4096; Flash_Write_Enable(); Flash_Wait_Busy(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_SectorErase); SPI0_MasterSendByte((uint8_t)((DST_ID)>>16)); SPI0_MasterSendByte((uint8_t)((DST_ID)>>8)); SPI0_MasterSendByte((uint8_t)DST_ID); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Erase_Page * Description : 擦除页区 * Input : Page_ID:页号(0~8191) * Return : None *******************************************************************************/ void Flash_Erase_Page(uint32_t Page_ID) { Page_ID*=256; Flash_Write_Enable(); Flash_Wait_Busy(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_PageErase); SPI0_MasterSendByte((uint8_t)((Page_ID)>>16)); SPI0_MasterSendByte((uint8_t)((Page_ID)>>8)); SPI0_MasterSendByte((uint8_t)Page_ID); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Erase_Page * Description : 擦除页区 * Input : Page_addr:地址 * Return : None *******************************************************************************/ void Flash_Erase_Pageaddr(uint32_t Page_addr) { Flash_Write_Enable(); Flash_Wait_Busy(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_PageErase); SPI0_MasterSendByte((uint8_t)((Page_addr)>>16)); SPI0_MasterSendByte((uint8_t)((Page_addr)>>8)); SPI0_MasterSendByte((uint8_t)Page_addr); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Read * Description : P25Q40H Flash 指定地址开始读取指定长度的数据 * Input : pBuffer:数据存储区 NumByteToRead:要读取的字节数(最大65535) ReadAddr:读取起始地址(24bit) * Return : None *******************************************************************************/ void Flash_Read(uint8_t* pBuffer,uint16_t NumByteToRead,uint32_t ReadAddr) { Flash_CS_L; SPI0_MasterSendByte(P24Q40H_ReadData); SPI0_MasterSendByte((uint8_t)((ReadAddr)>>16)); SPI0_MasterSendByte((uint8_t)((ReadAddr)>>8)); SPI0_MasterSendByte((uint8_t)ReadAddr); SPI0_MasterRecv(pBuffer,NumByteToRead); Flash_CS_H; } /******************************************************************************* * Function Name : Flash_Write_Page * Description : P25Q40H Flash 指定地址开始写指定长度的数据 * Input : pBuffer:数据存储区 NumByteToRead:要写的字节数(最大256),该数不应该超过该页的剩余字节数!!! ReadAddr:读取起始地址(24bit) * Return : None *******************************************************************************/ void Flash_Write_Page(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr) { Flash_Write_Enable(); Flash_CS_L; SPI0_MasterSendByte(P24Q40H_PageProgram); SPI0_MasterSendByte((uint8_t)((writeAddr)>>16)); SPI0_MasterSendByte((uint8_t)((writeAddr)>>8)); SPI0_MasterSendByte((uint8_t)writeAddr); SPI0_MasterTrans(pBuffer,NumByteToWrite); Flash_CS_H; Flash_Wait_Busy(); } /******************************************************************************* * Function Name : Flash_Write_NoCheck * Description : 无检验写P25Q40H FLASH 注意:必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! 具有自动换页功能 在指定地址开始写入指定长度的数据,但是要确保地址不越界! * Input : pBuffer:数据存储区 NumByteToRead:要写的字节数(最大65535) ReadAddr:读取起始地址(24bit) * Return : None *******************************************************************************/ void Flash_Write_NoCheck(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t writeAddr) { uint16_t pageremain; pageremain=256-writeAddr%256; //单页剩余的字节数 if(NumByteToWrite<=pageremain) pageremain=NumByteToWrite;//不大于256个字节 while(1) { Flash_Write_Page(pBuffer,pageremain,writeAddr); if(pageremain == NumByteToWrite) break; //写入完成 else { pBuffer+=pageremain; writeAddr+=pageremain; NumByteToWrite-=pageremain; if(NumByteToWrite>256) pageremain=256; else pageremain=NumByteToWrite; } }; } /* 由于本项目空间的本地SRAM空间有限,因此为较少SRAM的开销将数据BUFF从4096改为256 以下两个一个是以扇区为单位进行擦除,另一个是以页为单位进行擦除 */ #if 1 /******************************************************************************* * Function Name : Flash_Write * Description : 无检验写P25Q40H FLASH 注意:必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! 具有自动换页功能 在指定地址开始写入指定长度的数据,但是要确保地址不越界! * Input : pBuffer:数据存储区 NumByteToRead:要写的字节数(最大65535) ReadAddr:读取起始地址(24bit) * Return : None *******************************************************************************/ uint8_t Temp_Flash_Buff[4200]; void Flash_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t WriteAddr) { uint32_t secpos; uint16_t secoff,secremain,i; uint8_t* Write_Buff; if(NumByteToWrite <= 256*2) { Write_Buff = Temp_Flash_Buff; secpos = WriteAddr/256; //页区地址 secoff = WriteAddr%256; //在扇区内的偏移 secremain = 256 - secoff; //扇区剩余空间 if(NumByteToWrite<=secremain) secremain = NumByteToWrite; //当前页区剩余空间可以存放 while(1) { WDT_Feed(); Flash_Read(Write_Buff,256,secpos*256); //读取整个扇区的内容 for(i=0;i 256) secremain = 256; //下一个页区还是写不完 else secremain = NumByteToWrite; //下一个页区可以写完 } } } else { Write_Buff = Temp_Flash_Buff; secpos = WriteAddr/4096; //扇区地址 secoff = WriteAddr%4096; //在扇区内的偏移 secremain = 4096 - secoff; //扇区剩余空间 if(NumByteToWrite<=secremain) secremain = NumByteToWrite; //当前扇区剩余空间可以存放 while(1) { WDT_Feed(); Flash_Read(Write_Buff,2048,secpos*4096); //读取整个扇区的内容 Flash_Read(Write_Buff+2048,2048,secpos*4096+2048); //读取整个扇区的内容 for(i=0;i 4096) secremain = 4096; //下一个扇区还是写不完 else secremain = NumByteToWrite; //下一个扇区可以写完 } } } } #else /******************************************************************************* * Function Name : Flash_Write * Description : 无检验写P25Q40H FLASH 注意:必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! 具有自动换页功能 在指定地址开始写入指定长度的数据,但是要确保地址不越界! * Input : pBuffer:数据存储区 NumByteToRead:要写的字节数(最大65535) ReadAddr:读取起始地址(24bit) * Return : None *******************************************************************************/ uint8_t Flash_Buffer[256]; void Flash_Write(uint8_t* pBuffer,uint16_t NumByteToWrite,uint32_t WriteAddr) { uint32_t secpos; uint16_t secoff,secremain,i; uint8_t* Write_Buff; Write_Buff = Flash_Buffer; secpos = WriteAddr/256; //页区地址 secoff = WriteAddr%256; //在页区内的偏移 secremain = 256 - secoff; //页区剩余空间 if(NumByteToWrite<=secremain) secremain = NumByteToWrite; //当前页区剩余空间可以存放 while(1) { WDT_Feed(); Flash_Read(Write_Buff,256,secpos*256); //读取整个页区的内容 for(i=0;i 256) secremain = 256; //下一个页区还是写不完 else secremain = NumByteToWrite; //下一个页区可以写完 } }; } #endif /******************************************************************************* * Function Name : Flash_APPDATA_Erase * Description : Flash APP区数据全部擦除 APP代码中空间为218K * Input : *******************************************************************************/ void Flash_APPDATA_Erase(void) { /*APP固定区域:0x08000 ~ 0x3FFFF*/ /*擦除代码区全片区域 32K*/ for(uint8_t i =8;i<16;i++) { WDT_Feed(); Flash_Erase_Sector(i); } /*擦除代码区全片区域 192K*/ for(uint8_t i =1;i<4;i++) { WDT_Feed(); Flash_Erase_Block(i); } } /******************************************************************************* * Function Name : Flash_LOGICDATA_Erase * Description : Flash LOGIC区数据全部擦除 LOGIC代码中空间为448K * Input : *******************************************************************************/ void Flash_LOGICDATA_Erase(void) { /*LOGIC固定区域:0x90000 ~ 0xFFFFF */ /*擦除逻辑文件区域 448K*/ for(uint8_t i =9;i<16;i++) { WDT_Feed(); Flash_Erase_Block(i); } }