STM32G030Cx HAL库Flash擦除或编程操作出错的解决办法

例程说明

  1. STM32G0芯片对Flash操作容易出错,经常出现擦除失败或编程失败的情况,故有此记录。
  2. STM32G0芯片LL库没有对Flash的操作需要自己实现,可借鉴HAL库。
  3. STM32G0芯片对Flash的编程必须是双字(64位)。

一、宏定义及变量


#define FLASH_BASE                          (0x08000000UL)  /* FLASH base address */
#define FLASH_PAGE_SIZE                     (0x00000800UL)  /* FLASH Page Size, 2 KBytes */
#define SYS_ARGS_STORE_START_ADDER          (0x0800F800UL)  /* Store parameter start adress */

#define SYS_ARGS_TAB_SIZE             (20)
u64 SYS_ARGS_TAB[SYS_ARGS_TAB_SIZE] = {0};

#if ( SYS_ARGS_TAB_SIZE > (FLASH_PAGE_SIZE >> 3) )
    #error "System Argument Over Flash Page Size..."
#endif

二、获取页


/* 获取页 */
static u32 ulGetPage(u32 startAddr)
{
	return (startAddr - FLASH_BASE) / FLASH_PAGE_SIZE;;
}

三、写数据(双字)


/* 写数据(双字)*/
u8 vFlash_WriteData_DoubleWord(u32 startAddr, u64 * pDat, u16 num)
{
    FLASH_EraseInitTypeDef EraseInitStruct = {0};
    u32 Address = 0, PageError = 0;
    u8 i = 0, tryCount = 0;
    u8 res = 0;


    dprintf("Start Flash Erase Write...\r\n");
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page 	  = ulGetPage(startAddr);
    EraseInitStruct.NbPages	  = 1;
    EraseInitStruct.Banks	  = FLASH_BANK_1;

FLASH_UNLOCK_TRY:
    /* 忙状态 */
    if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) != 0x00U)
    {
        *(u32 *)(startAddr + 600) = 12323;/* 制造错误 */
        FLASH->SR = FLASH_SR_CLEAR;/* 清除所有错误标志 */
    }

    /* 解锁 */
    if(HAL_FLASH_Unlock() != HAL_OK)
    {
        tryCount++;
        if (tryCount < 5)
        {
            /* 等待 */
            FLASH_WaitForLastOperation(50);

            /* 再次尝试解锁 */
            goto FLASH_UNLOCK_TRY;
        }
        else
        {
            dprintf("Flash Unlock Fail...\r\n");
            return 1;
        }
    }

    tryCount = 0;



FLASH_ERASE_TRY:
    /* 等待 */
    FLASH_WaitForLastOperation(50);

    /* 擦除 */
    HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    if(PageError != 0xFFFFFFFF) 
    {
        tryCount++;
        if (tryCount < 5)
        {
            /* 再次尝试擦除 */
            goto FLASH_ERASE_TRY;
        }
        else
        {
            dprintf("Flash Erase Fail...\r\n");
            res = 2;
            goto FLASH_ERROR_EXIT;
        }
    }


    for (i = 0; i < num; ++i)
    {
        while(tryCount < 5)
        {
            /* 等待 */
        	FLASH_WaitForLastOperation(50);

            /* 双字编程 */
            if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr, *(pDat + i)) == HAL_OK)
            {
                startAddr += 8;
                tryCount   = 0;
                break;
            }
            else
            {
                tryCount++;
            }
        }
    }


    if (tryCount)
    {
        dprintf("Write Flash Fail...\r\n");
        res = 3;
    }
    else
    {
        dprintf("Write Flash OK...\r\n");
    }


FLASH_ERROR_EXIT:
    HAL_FLASH_Lock();
    oPrintf("Exit Flash Opration...\r\n");
    return res;
}

四、调用验证


/* 调用验证 */
vFlash_WriteData_DoubleWord(SYS_ARGS_STORE_START_ADDER, SYS_ARGS_TAB, SYS_ARGS_TAB_SIZE);

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值