/******************************************************************************* * 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) { HIDO_UINT32 i = 0; uint32_t u32TmpValue = 0; /* µØÖ·¶ÔÆë¼ì²é - STM32H7ÍÆ¼ö8×Ö½Ú¶ÔÆë */ if (_u32WriteAddr % 4 != 0) { return HIDO_ERR; } /* STM32H7ÍÆ¼öʹÓÃ64λ±à³Ì */ while (_u32WriteLen >= 4) { /* Ö±½ÓʹÓÃ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; } /* ´¦ÀíÊ£ÓàÊý¾Ý£¨ÉÙÓÚ8×Ö½Ú£© */ if (_u32WriteLen > 0) { u32TmpValue = 0xFFFFFFFF; for (i = 0; i < _u32WriteLen; i++) { ((HIDO_UINT8 *)&u32TmpValue)[i] = _pu8WriteData[i]; } if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _u32WriteAddr, (uint32_t)&u32TmpValue) != HAL_OK) { return HIDO_ERR; } } 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; }