打印
[STM32G0]

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

[复制链接]
957|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2023-6-13 08:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32G0芯片对Flash操作容易出错,经常出现擦除失败或编程失败的情况,故有此记录。
STM32G0芯片LL库没有对Flash的操作需要自己实现,可借鉴HAL库。
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);


————————————————
版权声明:本文为CSDN博主「凌盛羽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Ceosat/article/details/127027399

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1944

主题

15669

帖子

12

粉丝