freeRTOS操作系统机器人实现
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

171 lines
4.4 KiB

#include "stmflash.h"
#ifdef USE_ONCHIP_FLASH
#include <string.h>
#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