#include "stmflash.h" #ifdef USE_ONCHIP_FLASH #include #ifndef STM32_FLASH_SIZE #define STM32_FLASH_SIZE 256 #endif extern void Flow_control_before(void); extern void Flow_control_after(void); const uint32_t FLASH_SECTOR_SIZE_MAP[] = { 16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, // 0-3 64 * 1024, // 4 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, // 5-8 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024 // 9-11 }; #define TOTAL_SECTORS (sizeof(FLASH_SECTOR_SIZE_MAP) / sizeof(FLASH_SECTOR_SIZE_MAP[0])) static uint8_t STMFLASH_GetSectorNumber(uint32_t Address) { if (Address < FLASH_BASE) return 0xFF; uint32_t offset = Address - FLASH_BASE; uint32_t current_addr = 0; for (uint8_t i = 0; i < TOTAL_SECTORS; i++) { if (offset < current_addr + FLASH_SECTOR_SIZE_MAP[i]) return i; current_addr += FLASH_SECTOR_SIZE_MAP[i]; if (current_addr >= (STM32_FLASH_SIZE * 1024)) break; } return 0xFF; } /* static uint32_t STMFLASH_GetSectorStartAddr(uint8_t Sector_Num) { if (Sector_Num >= TOTAL_SECTORS) return 0; uint32_t addr = FLASH_BASE; for (uint8_t i = 0; i < Sector_Num; i++) addr += FLASH_SECTOR_SIZE_MAP[i]; return addr; } static uint32_t STMFLASH_GetSectorSize(uint8_t Sector_Num) { if (Sector_Num >= TOTAL_SECTORS) return 0; return FLASH_SECTOR_SIZE_MAP[Sector_Num]; }*/ static uint8_t STMFLASH_CheckBlank(uint32_t StartAddr, uint32_t NumToCheck) { volatile uint8_t *p = (volatile uint8_t *)StartAddr; for (uint32_t i = 0; i < NumToCheck; i++) { if (p[i] != 0xFF) return 0; // 有数据 } return 1; // 空白 } /** * @brief 读取单字节 */ uint8_t STMFLASH_ReadByte(uint32_t faddr) { return *(volatile uint8_t *)faddr; } /** * @brief 读取多个字节 * @param ReadAddr: 起始地址 * @param pBuffer: 数据缓冲区 (uint8_t*) * @param NumToRead: 读取字节数 */ void STMFLASH_Read(uint32_t ReadAddr, uint8_t *pBuffer, uint32_t NumToRead) { volatile uint8_t *p = (volatile uint8_t *)ReadAddr; for (uint32_t i = 0; i < NumToRead; i++) { pBuffer[i] = p[i]; } } /** * @brief 底层写入 (无检查) - 支持字节写入 * @note 调用前必须确保扇区已擦除! */ HAL_StatusTypeDef STMFLASH_Write_NoCheck(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumToWrite) { HAL_StatusTypeDef status = HAL_OK; // F4 支持字节写入,但地址最好是偶数。如果是奇数地址,HAL 库通常也能处理,但性能稍差。 // 这里直接使用 HAL_FLASH_Program 的 BYTE 模式 for (uint32_t i = 0; i < NumToWrite; i++) { __disable_irq(); // 使用 FLASH_TYPEPROGRAM_BYTE 进行 8 位写入 status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, WriteAddr, pBuffer[i]); __enable_irq(); if (status != HAL_OK) break; WriteAddr++; } return status; } HAL_StatusTypeDef STMFLASH_EraseSector(uint8_t Sector_Num) { FLASH_EraseInitTypeDef EraseInitStruct; uint32_t SectorError = 0; if (Sector_Num >= TOTAL_SECTORS) return HAL_ERROR; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.Sector = Sector_Num; EraseInitStruct.NbSectors = 1; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; HAL_FLASH_Unlock(); HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); HAL_FLASH_Lock(); return status; } HAL_StatusTypeDef STMFLASH_EraseByAddress(uint32_t Address) { uint8_t sectorNum = STMFLASH_GetSectorNumber(Address); if (sectorNum == 0xFF) return HAL_ERROR; return STMFLASH_EraseSector(sectorNum); } HAL_StatusTypeDef STMFLASH_Write(uint32_t WriteAddr, uint8_t *pBuffer, uint32_t NumToWrite) { if (NumToWrite == 0) return HAL_OK; if (WriteAddr < FLASH_BASE) return HAL_ERROR; uint32_t endAddr = WriteAddr + NumToWrite; if (endAddr > (FLASH_BASE + (STM32_FLASH_SIZE * 1024))) return HAL_ERROR; // 检查是否为空 if (!STMFLASH_CheckBlank(WriteAddr, NumToWrite)) { return HAL_ERROR; // 区域未擦除,拒绝写入 } Flow_control_before(); HAL_FLASH_Unlock(); HAL_StatusTypeDef status = STMFLASH_Write_NoCheck(WriteAddr, pBuffer, NumToWrite); HAL_FLASH_Lock(); Flow_control_after(); return status; } #endif