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