/******************************************************************************* * 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; }