yincheng.zhong
9 天以前 d10f581eb749a8338e697a418d630db2cb01843f
STM32H743/HAL/MCUFlash.c
@@ -1,7 +1,7 @@
/*******************************************************************************
 * File Name         : MCUFlash.c
 * Description       : STM32H743 Flash操作驱动
 * Created on        : 2018年5月29日
 * Description       : STM32H743 Flash��������
 * Created on        : 2018��5��29��
 * Author            : HIDO
 *******************************************************************************/
@@ -14,18 +14,18 @@
/*******************************************************************************
 *                                  Macro                                      *
 *******************************************************************************/
/* STM32H743的Flash相关信息 - 修正为2MB版本 */
/* STM32H743��Flash�����Ϣ - ����Ϊ2MB�汾 */
#define FLASH_BANK1_START 0x08000000U
#define FLASH_BANK1_END 0x080FFFFFU
#define FLASH_BANK2_START 0x08100000U
#define FLASH_BANK2_END 0x081FFFFFU
/* STM32H743 扇区大小定义 */
/* 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 扇区边界地址 */
/* 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)
@@ -35,7 +35,7 @@
#define FLASH_SECTOR6_END (FLASH_SECTOR5_END + 0x20000)
#define FLASH_SECTOR7_END (FLASH_SECTOR6_END + 0x20000)
/* Bank 2 扇区边界地址 */
/* 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)
@@ -65,10 +65,10 @@
/*******************************************************************************
 * Function Name     : GetFlashBankFromAddress
 * Description       : 根据地址获取Flash Bank
 * Input             : address - 地址
 * Output            : 无
 * Return            : Flash Bank编号 (FLASH_BANK_1 或 FLASH_BANK_2), 0表示无效地址
 * Description       : ���ݵ�ַ��ȡFlash Bank
 * Input             : address - ��ַ
 * Output            : ��
 * Return            : Flash Bank��� (FLASH_BANK_1 �� FLASH_BANK_2), 0��ʾ��Ч��ַ
 *******************************************************************************/
static uint32_t GetFlashBankFromAddress(uint32_t address)
{
@@ -88,10 +88,10 @@
/*******************************************************************************
 * Function Name     : GetFlashSectorFromAddress
 * Description       : 根据地址计算扇区编号
 * Input             : address - 地址
 * Output            : 无
 * Return            : 扇区编号 (0-15), 0xFFFFFFFF表示无效地址
 * Description       : ���ݵ�ַ�����������
 * Input             : address - ��ַ
 * Output            : ��
 * Return            : ������� (0-15), 0xFFFFFFFF��ʾ��Ч��ַ
 *******************************************************************************/
static uint32_t GetFlashSectorFromAddress(uint32_t address)
{
@@ -104,7 +104,7 @@
    if (bank == FLASH_BANK_1)
    {
        /* Bank 1 扇区 0-7 */
        /* Bank 1 ���� 0-7 */
        if (address <= FLASH_SECTOR0_END)
            return FLASH_SECTOR_0;
        else if (address <= FLASH_SECTOR1_END)
@@ -125,7 +125,7 @@
    else
    {
#if 0
        /* Bank 2 扇区 8-15 */
        /* Bank 2 ���� 8-15 */
        if (address <= FLASH_SECTOR8_END)
            return FLASH_SECTOR_8;
        else if (address <= FLASH_SECTOR9_END)
@@ -154,16 +154,16 @@
/*******************************************************************************
 * Function Name     : MCUFlash_Init
 * Description       : Flash初始化
 * Input             : 无
 * Output            : 无
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * Description       : Flash��ʼ��
 * Input             : ��
 * Output            : ��
 * Return            : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
 * Author            : HIDO
 * Modified Date:    : 2018年5月29日
 * Modified Date:    : 2018��5��29��
 *******************************************************************************/
HIDO_INT32 MCUFlash_Init(void)
{
    /* 解锁Flash */
    /* ����Flash */
    if (HAL_FLASH_Unlock() != HAL_OK)
    {
        return HIDO_ERR;
@@ -174,14 +174,14 @@
/*******************************************************************************
 * Function Name     : MCUFlash_DeInit
 * Description       : Flash反初始化
 * Input             : 无
 * Output            : 无
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * Description       : Flash����ʼ��
 * Input             : ��
 * Output            : ��
 * Return            : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
 *******************************************************************************/
HIDO_INT32 MCUFlash_DeInit(void)
{
    /* 锁定Flash */
    /* ����Flash */
    if (HAL_FLASH_Lock() != HAL_OK)
    {
        return HIDO_ERR;
@@ -192,13 +192,13 @@
/*******************************************************************************
 * Function Name     : MCUFlash_Erase
 * Description       : Flash擦除
 * Input             : _u32EraseAddr - 擦除起始地址
 *                   : _u32EraseLen - 擦除长度
 * Output            : 无
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * Description       : Flash����
 * Input             : _u32EraseAddr - ������ʼ��ַ
 *                   : _u32EraseLen - ��������
 * Output            : ��
 * Return            : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
 * Author            : HIDO
 * Modified Date:    : 2018年5月29日
 * Modified Date:    : 2018��5��29��
 *******************************************************************************/
HIDO_INT32 MCUFlash_Erase(HIDO_UINT32 _u32EraseAddr, HIDO_UINT32 _u32EraseLen)
{
@@ -207,17 +207,17 @@
    uint32_t u32StartSector, u32EndSector;
    uint32_t u32CurrentAddr;
    /* 清除Flash标志 */
    /* ���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)
@@ -231,14 +231,14 @@
        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需要设置电压范围 */
    stEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* STM32H7��Ҫ���õ�ѹ��Χ */
    /* 执行擦除操作 */
    /* ִ�в������� */
    if (HAL_FLASHEx_Erase(&stEraseInit, &u32SectorError) != HAL_OK)
    {
        return HIDO_ERR;
@@ -249,55 +249,88 @@
/*******************************************************************************
 * Function Name     : MCUFlash_Write
 * Description       : Flash写入
 * Input             : _u32WriteAddr - 写入地址
 *                   : _pu8WriteData - 写入数据指针
 *                   : _u32WriteLen - 写入数据长度
 * Output            : 无
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * Description       : Flashд��
 * Input             : _u32WriteAddr - д���ַ
 *                   : _pu8WriteData - д������ָ��
 *                   : _u32WriteLen - д�����ݳ���
 * Output            : ��
 * Return            : HIDO_OK - �ɹ�, HIDO_ERR - ʧ��
 * Author            : HIDO
 * Modified Date:    : 2018年5月29日
 * Modified Date:    : 2018��5��29��
 *******************************************************************************/
HIDO_INT32 MCUFlash_Write(HIDO_UINT32 _u32WriteAddr, HIDO_UINT8 *_pu8WriteData, HIDO_UINT32 _u32WriteLen)
{
    HIDO_UINT32 i = 0;
    uint32_t u32TmpValue = 0;
    /* 安全版本:以 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 行为一致
     */
    /* 地址对齐检查 - STM32H7推荐8字节对齐 */
    if (_u32WriteAddr % 4 != 0)
#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;
    }
    /* STM32H7推荐使用64位编程 */
    while (_u32WriteLen >= 4)
    /* 地址边界与对齐校验 */
    if (_u32WriteAddr < FLASH_BANK1_START || _u32WriteAddr > FLASH_BANK2_END)
    {
        /* 直接使用64位数据 */
        u32TmpValue = *(uint32_t *)_pu8WriteData;
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _u32WriteAddr, (uint32_t)&u32TmpValue) != HAL_OK)
        {
            return HIDO_ERR;
        }
        _u32WriteAddr += 4;
        _pu8WriteData += 4;
        _u32WriteLen -= 4;
        return HIDO_ERR;
    }
    if ((_u32WriteAddr % MCU_FLASH_WORD_BYTES) != 0)
    {
        return HIDO_ERR; /* 需要 32 字节对齐 */
    }
    /* 处理剩余数据(少于8字节) */
    if (_u32WriteLen > 0)
    HIDO_UINT32 remaining = _u32WriteLen;
    HIDO_UINT32 addr = _u32WriteAddr;
    HIDO_UINT8 const *src = _pu8WriteData;
    HIDO_UINT8 wordBuf[MCU_FLASH_WORD_BYTES];
    while (remaining > 0)
    {
        u32TmpValue = 0xFFFFFFFF;
        for (i = 0; i < _u32WriteLen; i++)
        /* 本次写入长度(不超过一个 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++)
        {
            ((HIDO_UINT8 *)&u32TmpValue)[i] = _pu8WriteData[i];
            if (i < chunk)
            {
                wordBuf[i] = src[i];
            }
            else
            {
                wordBuf[i] = 0xFF; /* 填充未使用字节,保证位仅向 1->0 转换 */
            }
        }
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _u32WriteAddr, (uint32_t)&u32TmpValue) != HAL_OK)
        /* 已擦除校验:当前 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;
@@ -305,24 +338,24 @@
/*******************************************************************************
 * Function Name     : MCUFlash_Read
 * Description       : Flash读取
 * Input             : _u32ReadAddr - 读取地址
 *                   : _pu8ReadData - 读取数据缓冲区
 *                   : _u32ReadLen - 读取数据长度
 * Output            : 无
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * 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);
@@ -333,11 +366,11 @@
/*******************************************************************************
 * Function Name     : MCUFlash_GetSectorInfo
 * Description       : 获取扇区信息
 * Input             : address - 地址
 * Output            : pBank - 存储Bank信息
 *                   : pSector - 存储扇区信息
 * Return            : HIDO_OK - 成功, HIDO_ERR - 失败
 * 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)
{