#include "stmflash.h" // 读取指定地址的半字(16位数据) // faddr:读地址 // 返回值:对应数据. u32 STMFLASH_ReadWord(u32 faddr) { return *(vu32 *)faddr; } // 获取某个地址所在的flash扇区 // addr:flash地址 // 返回值:0~11,即addr所在的扇区 uint16_t STMFLASH_GetFlashSector(u32 addr) { if (addr < ADDR_FLASH_SECTOR_1) return FLASH_Sector_0; else if (addr < ADDR_FLASH_SECTOR_2) return FLASH_Sector_1; else if (addr < ADDR_FLASH_SECTOR_3) return FLASH_Sector_2; else if (addr < ADDR_FLASH_SECTOR_4) return FLASH_Sector_3; else if (addr < ADDR_FLASH_SECTOR_5) return FLASH_Sector_4; else if (addr < ADDR_FLASH_SECTOR_6) return FLASH_Sector_5; else if (addr < ADDR_FLASH_SECTOR_7) return FLASH_Sector_6; else if (addr < ADDR_FLASH_SECTOR_8) return FLASH_Sector_7; else if (addr < ADDR_FLASH_SECTOR_9) return FLASH_Sector_8; else if (addr < ADDR_FLASH_SECTOR_10) return FLASH_Sector_9; else if (addr < ADDR_FLASH_SECTOR_11) return FLASH_Sector_10; return FLASH_Sector_11; } // 从指定地址开始写入指定长度的数据 // 特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数 // 写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以 // 写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里 // 没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写. // 该函数对OTP区域也有效!可以用来写OTP区! // OTP区域地址范围:0X1FFF7800~0X1FFF7A0F // WriteAddr:起始地址(此地址必须为4的倍数!!) // pBuffer:数据指针 // NumToWrite:字(32位)数(就是要写入的32位数据的个数.) void STMFLASH_Write(u32 WriteAddr, u32 *pBuffer, u32 NumToWrite) { FLASH_Status status = FLASH_COMPLETE; u32 addrx = 0; u32 endaddr = 0; if (WriteAddr < STM32_FLASH_BASE || WriteAddr % 4) return; // 非法地址 drv_flash_Init(); // 解锁 FLASH_DataCacheCmd(DISABLE); // FLASH擦除期间,必须禁止数据缓存 addrx = WriteAddr; // 写入的起始地址 endaddr = WriteAddr + NumToWrite * 4; // 写入的结束地址 if (addrx < 0X1FFF0000) // 只有主存储区,才需要执行擦除操作!! { while (addrx < endaddr) // 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) { if (STMFLASH_ReadWord(addrx) != 0XFFFFFFFF) // 有非0XFFFFFFFF的地方,要擦除这个扇区 { status = FLASH_EraseSector(STMFLASH_GetFlashSector(addrx), VoltageRange_3); // VCC=2.7~3.6V之间!! if (status != FLASH_COMPLETE) break; // 发生错误了 } else addrx += 4; } } if (status == FLASH_COMPLETE) { while (WriteAddr < endaddr) // 写数据 { if (FLASH_ProgramWord(WriteAddr, *pBuffer) != FLASH_COMPLETE) // 写入数据 { break; // 写入异常 } WriteAddr += 4; pBuffer++; } } FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 } // 从指定地址开始读出指定长度的数据 // ReadAddr:起始地址 // pBuffer:数据指针 // NumToRead:字(4位)数 void STMFLASH_Read(u32 ReadAddr, u32 *pBuffer, u32 NumToRead) { u32 i; for (i = 0; i < NumToRead; i++) { pBuffer[i] = STMFLASH_ReadWord(ReadAddr); // 读取4个字节. ReadAddr += 4; // 偏移4个字节. } } void drv_flash_Init(void) { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); }