| | |
| | | /******************************************************************************* |
| | | * File Name : MCUFlash.c |
| | | * Description : STM32H743 Flash操作驱动 |
| | | * Created on : 2018年5月29日 |
| | | * Description : STM32H743 Flash�������� |
| | | * Created on : 2018��5��29�� |
| | | * Author : HIDO |
| | | *******************************************************************************/ |
| | | |
| | |
| | | /******************************************************************************* |
| | | * 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) |
| | |
| | | #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) |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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) |
| | | { |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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) |
| | | { |
| | |
| | | |
| | | 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) |
| | |
| | | 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) |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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; |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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; |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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) |
| | | { |
| | |
| | | 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) |
| | |
| | | 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; |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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; |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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); |
| | |
| | | |
| | | /******************************************************************************* |
| | | * 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) |
| | | { |