/*******************************************************************************
|
* File Name : MCUFlash.c
|
* Description : STM32H743 Flash��������
|
* Created on : 2018��5��29��
|
* Author : HIDO
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Include Files *
|
*******************************************************************************/
|
#include "MCUFlash.h"
|
#include "stm32h7xx_hal.h"
|
|
/*******************************************************************************
|
* Macro *
|
*******************************************************************************/
|
/* STM32H743��Flash�����Ϣ - ����Ϊ2MB�汾 */
|
#define FLASH_BANK1_START 0x08000000U
|
#define FLASH_BANK1_END 0x080FFFFFU
|
#define FLASH_BANK2_START 0x08100000U
|
#define FLASH_BANK2_END 0x081FFFFFU
|
|
/* STM32H743 ���������� */
|
#define FLASH_SECTOR_0_3_SIZE (128 * 1024) /* 128 KB */
|
#define FLASH_SECTOR_4_7_SIZE (128 * 1024) /* 128 KB */
|
#define FLASH_SECTOR_8_15_SIZE (128 * 1024) /* 128 KB */
|
|
/* Bank 1 �����߽��ַ */
|
#define FLASH_SECTOR0_END (FLASH_BANK1_START + 0x1FFFF)
|
#define FLASH_SECTOR1_END (FLASH_SECTOR0_END + 0x20000)
|
#define FLASH_SECTOR2_END (FLASH_SECTOR1_END + 0x20000)
|
#define FLASH_SECTOR3_END (FLASH_SECTOR2_END + 0x20000)
|
#define FLASH_SECTOR4_END (FLASH_SECTOR3_END + 0x20000)
|
#define FLASH_SECTOR5_END (FLASH_SECTOR4_END + 0x20000)
|
#define FLASH_SECTOR6_END (FLASH_SECTOR5_END + 0x20000)
|
#define FLASH_SECTOR7_END (FLASH_SECTOR6_END + 0x20000)
|
|
/* Bank 2 �����߽��ַ */
|
#define FLASH_SECTOR8_END (FLASH_BANK2_START + 0x1FFFF)
|
#define FLASH_SECTOR9_END (FLASH_SECTOR8_END + 0x20000)
|
#define FLASH_SECTOR10_END (FLASH_SECTOR9_END + 0x20000)
|
#define FLASH_SECTOR11_END (FLASH_SECTOR10_END + 0x20000)
|
#define FLASH_SECTOR12_END (FLASH_SECTOR11_END + 0x20000)
|
#define FLASH_SECTOR13_END (FLASH_SECTOR12_END + 0x20000)
|
#define FLASH_SECTOR14_END (FLASH_SECTOR13_END + 0x20000)
|
#define FLASH_SECTOR15_END (FLASH_SECTOR14_END + 0x20000)
|
|
/*******************************************************************************
|
* Type Definition *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Local Variable *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Local Function Declaration *
|
*******************************************************************************/
|
static uint32_t GetFlashBankFromAddress(uint32_t address);
|
static uint32_t GetFlashSectorFromAddress(uint32_t address);
|
|
/*******************************************************************************
|
* Local Function *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Function Name : GetFlashBankFromAddress
|
* Description : ���ݵ�ַ��ȡFlash Bank
|
* Input : address - ��ַ
|
* Output : ��
|
* Return : Flash Bank��� (FLASH_BANK_1 �� FLASH_BANK_2), 0��ʾ��Ч��ַ
|
*******************************************************************************/
|
static uint32_t GetFlashBankFromAddress(uint32_t address)
|
{
|
if (address >= FLASH_BANK1_START && address <= FLASH_BANK1_END)
|
{
|
return FLASH_BANK_1;
|
}
|
else if (address >= FLASH_BANK2_START && address <= FLASH_BANK2_END)
|
{
|
return FLASH_BANK_2;
|
}
|
else
|
{
|
return 0;
|
}
|
}
|
|
/*******************************************************************************
|
* Function Name : GetFlashSectorFromAddress
|
* Description : ���ݵ�ַ�����������
|
* Input : address - ��ַ
|
* Output : ��
|
* Return : ������� (0-15), 0xFFFFFFFF��ʾ��Ч��ַ
|
*******************************************************************************/
|
static uint32_t GetFlashSectorFromAddress(uint32_t address)
|
{
|
uint32_t bank = GetFlashBankFromAddress(address);
|
|
if (bank == 0)
|
{
|
return 0xFFFFFFFF;
|
}
|
|
if (bank == FLASH_BANK_1)
|
{
|
/* Bank 1 ���� 0-7 */
|
if (address <= FLASH_SECTOR0_END)
|
return FLASH_SECTOR_0;
|
else if (address <= FLASH_SECTOR1_END)
|
return FLASH_SECTOR_1;
|
else if (address <= FLASH_SECTOR2_END)
|
return FLASH_SECTOR_2;
|
else if (address <= FLASH_SECTOR3_END)
|
return FLASH_SECTOR_3;
|
else if (address <= FLASH_SECTOR4_END)
|
return FLASH_SECTOR_4;
|
else if (address <= FLASH_SECTOR5_END)
|
return FLASH_SECTOR_5;
|
else if (address <= FLASH_SECTOR6_END)
|
return FLASH_SECTOR_6;
|
else if (address <= FLASH_SECTOR7_END)
|
return FLASH_SECTOR_7;
|
}
|
else
|
{
|
#if 0
|
/* Bank 2 ���� 8-15 */
|
if (address <= FLASH_SECTOR8_END)
|
return FLASH_SECTOR_8;
|
else if (address <= FLASH_SECTOR9_END)
|
return FLASH_SECTOR_9;
|
else if (address <= FLASH_SECTOR10_END)
|
return FLASH_SECTOR_10;
|
else if (address <= FLASH_SECTOR11_END)
|
return FLASH_SECTOR_11;
|
else if (address <= FLASH_SECTOR12_END)
|
return FLASH_SECTOR_12;
|
else if (address <= FLASH_SECTOR13_END)
|
return FLASH_SECTOR_13;
|
else if (address <= FLASH_SECTOR14_END)
|
return FLASH_SECTOR_14;
|
else if (address <= FLASH_SECTOR15_END)
|
return FLASH_SECTOR_15;
|
#endif
|
}
|
|
return 0xFFFFFFFF;
|
}
|
|
/*******************************************************************************
|
* Global Function *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_Init
|
* Description : Flash��ʼ��
|
* Input : ��
|
* Output : ��
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
* Author : HIDO
|
* Modified Date: : 2018��5��29��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_Init(void)
|
{
|
/* ����Flash */
|
if (HAL_FLASH_Unlock() != HAL_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_DeInit
|
* Description : Flash����ʼ��
|
* Input : ��
|
* Output : ��
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_DeInit(void)
|
{
|
/* ����Flash */
|
if (HAL_FLASH_Lock() != HAL_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_Erase
|
* Description : Flash����
|
* Input : _u32EraseAddr - ������ʼ��ַ
|
* : _u32EraseLen - ��������
|
* Output : ��
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
* Author : HIDO
|
* Modified Date: : 2018��5��29��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_Erase(HIDO_UINT32 _u32EraseAddr, HIDO_UINT32 _u32EraseLen)
|
{
|
FLASH_EraseInitTypeDef stEraseInit;
|
uint32_t u32SectorError = 0;
|
uint32_t u32StartSector, u32EndSector;
|
uint32_t u32CurrentAddr;
|
|
/* ���Flash��־ */
|
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1);
|
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK2);
|
|
/* ��ַ��Χ��� */
|
if (_u32EraseAddr < FLASH_BANK1_START || _u32EraseAddr > FLASH_BANK2_END)
|
{
|
return HIDO_ERR;
|
}
|
|
/* ��ȡ��ʼ�����ͽ������� */
|
u32StartSector = GetFlashSectorFromAddress(_u32EraseAddr);
|
u32CurrentAddr = _u32EraseAddr + _u32EraseLen - 1;
|
if (u32CurrentAddr > FLASH_BANK2_END)
|
{
|
u32CurrentAddr = FLASH_BANK2_END;
|
}
|
u32EndSector = GetFlashSectorFromAddress(u32CurrentAddr);
|
|
if (u32StartSector == 0xFFFFFFFF || u32EndSector == 0xFFFFFFFF)
|
{
|
return HIDO_ERR;
|
}
|
|
/* �������� */
|
stEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
|
stEraseInit.Banks = GetFlashBankFromAddress(_u32EraseAddr);
|
stEraseInit.Sector = u32StartSector;
|
stEraseInit.NbSectors = u32EndSector - u32StartSector + 1;
|
stEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* STM32H7��Ҫ���õ�ѹ��Χ */
|
|
/* ִ�в������� */
|
if (HAL_FLASHEx_Erase(&stEraseInit, &u32SectorError) != HAL_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_Write
|
* Description : Flash�
|
* Input : _u32WriteAddr - д���ַ
|
* : _pu8WriteData - д������ָ��
|
* : _u32WriteLen - д�����ݳ���
|
* Output : ��
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
* Author : HIDO
|
* Modified Date: : 2018��5��29��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_Write(HIDO_UINT32 _u32WriteAddr, HIDO_UINT8 *_pu8WriteData, HIDO_UINT32 _u32WriteLen)
|
{
|
/* 安全版本:以 Flash Word (设备 256bit/32Byte) 为单位写入。
|
* 1. 地址必须 32 字节对齐
|
* 2. 写入长度可以不是 32 的倍数,末尾自动 0xFF 填充
|
* 3. 每个 Flash Word 写之前检查是否已擦除 (全部 0xFF),否则报错
|
* 4. 使用 HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, buffer32B)
|
* 5. 不在此函数中做 Unlock/Lock,保持与原始 Init/DeInit 行为一致
|
*/
|
|
#ifndef MCU_FLASH_WORD_BYTES
|
/* 针对 STM32H743/H74x/H75x 设备 Flash Word = 256bit = 32 字节
|
* 若后续移植到 H7Ax/Bx (128bit),可在编译器宏中重定义为 16 */
|
#define MCU_FLASH_WORD_BYTES 32U
|
#endif
|
|
if (_pu8WriteData == NULL || _u32WriteLen == 0)
|
{
|
return HIDO_ERR;
|
}
|
|
/* 地址边界与对齐校验 */
|
if (_u32WriteAddr < FLASH_BANK1_START || _u32WriteAddr > FLASH_BANK2_END)
|
{
|
return HIDO_ERR;
|
}
|
if ((_u32WriteAddr % MCU_FLASH_WORD_BYTES) != 0)
|
{
|
return HIDO_ERR; /* 需要 32 字节对齐 */
|
}
|
|
HIDO_UINT32 remaining = _u32WriteLen;
|
HIDO_UINT32 addr = _u32WriteAddr;
|
HIDO_UINT8 const *src = _pu8WriteData;
|
HIDO_UINT8 wordBuf[MCU_FLASH_WORD_BYTES];
|
|
while (remaining > 0)
|
{
|
/* 本次写入长度(不超过一个 Flash Word) */
|
HIDO_UINT32 chunk = (remaining >= MCU_FLASH_WORD_BYTES) ? MCU_FLASH_WORD_BYTES : remaining;
|
|
/* 准备缓冲区:复制数据并对末尾填充 0xFF */
|
for (HIDO_UINT32 i = 0; i < MCU_FLASH_WORD_BYTES; i++)
|
{
|
if (i < chunk)
|
{
|
wordBuf[i] = src[i];
|
}
|
else
|
{
|
wordBuf[i] = 0xFF; /* 填充未使用字节,保证位仅向 1->0 转换 */
|
}
|
}
|
|
/* 已擦除校验:当前 Flash 中该 32 字节必须全为 0xFF */
|
for (HIDO_UINT32 i = 0; i < MCU_FLASH_WORD_BYTES; i++)
|
{
|
if (*(volatile HIDO_UINT8 *)(addr + i) != 0xFF)
|
{
|
return HIDO_ERR; /* 未擦除或脏数据,需先调用 MCUFlash_Erase */
|
}
|
}
|
|
/* 编程:HAL_FLASH_Program 会按设备 flash word 粒度写入 */
|
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, (uint32_t)wordBuf) != HAL_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
/* 前进 */
|
remaining -= chunk;
|
src += chunk;
|
addr += MCU_FLASH_WORD_BYTES;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_Read
|
* Description : Flash��ȡ
|
* Input : _u32ReadAddr - ��ȡ��ַ
|
* : _pu8ReadData - ��ȡ���ݻ�����
|
* : _u32ReadLen - ��ȡ���ݳ���
|
* Output : ��
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_Read(HIDO_UINT32 _u32ReadAddr, HIDO_UINT8 *_pu8ReadData, HIDO_UINT32 _u32ReadLen)
|
{
|
HIDO_UINT32 i;
|
|
/* ��ַ��Χ��� */
|
if (_u32ReadAddr < FLASH_BANK1_START || (_u32ReadAddr + _u32ReadLen) > (FLASH_BANK2_END + 1))
|
{
|
return HIDO_ERR;
|
}
|
|
/* ֱ���ڴ��ȡ */
|
for (i = 0; i < _u32ReadLen; i++)
|
{
|
_pu8ReadData[i] = *(volatile HIDO_UINT8 *)(_u32ReadAddr + i);
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : MCUFlash_GetSectorInfo
|
* Description : ��ȡ������Ϣ
|
* Input : address - ��ַ
|
* Output : pBank - �洢Bank��Ϣ
|
* : pSector - �洢������Ϣ
|
* Return : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
|
*******************************************************************************/
|
HIDO_INT32 MCUFlash_GetSectorInfo(HIDO_UINT32 address, uint32_t *pBank, uint32_t *pSector)
|
{
|
if (pBank == NULL || pSector == NULL)
|
{
|
return HIDO_ERR;
|
}
|
|
*pBank = GetFlashBankFromAddress(address);
|
*pSector = GetFlashSectorFromAddress(address);
|
|
if (*pBank == 0 || *pSector == 0xFFFFFFFF)
|
{
|
return HIDO_ERR;
|
}
|
|
return HIDO_OK;
|
}
|