STM32 闪存擦除失败,并出现“编程大小错误”和“编程对齐错误”

问题描述 投票:0回答:1

我正在使用 stm32g070,我正在尝试擦除数据并将其编程到闪存中。这是我的代码:

/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();

/* Fill EraseInit structure*/
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page        = 62u;
    EraseInitStruct.NbPages     = 1;

__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | \ FLASH_FLAG_PGAERR | FLASH_FLAG_SIZERR | FLASH_FLAG_PGSERR);

//Clear the page
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {

        /*Error occurred while page erase.*/
        return HAL_FLASH_GetError ();
    }

根据参考手册 0454(来自 STM32G070),此代码返回 HAL_FLASH_GetError() 中的值 96,对应于 0b0110 0000、位 5 (PGA ERR) 和位 6 (SIZ ERR)。有人可以帮助我吗?

我尝试理解为什么会出现这些错误,以及这是否与 HAL 层的问题有关。

stm32 stm32cubeide
1个回答
0
投票

我建议采用裸机方法。

#define FLASH_SECTORSIZE    2048

static void FLASH_Unlock(void)
{
    FLASH -> KEYR = FLASH_UNLOCK_KEY1;
    FLASH -> KEYR = FLASH_UNLOCK_KEY2;
}

static int FLASH_WaitForNotBSY(unsigned maxtime)
{
    unsigned result = GERR_SUCCESS;
    while(FLASH -> SR & FLASH_SR_BSY)
    {
        for(volatile unsigned i = 0; i < 500; i++);
        if(!--maxtime) {result = GERR_TIMEOUT; break;}
    }
    return result;
}

static void FLASH_Lock(void)
{
    FLASH_WaitForNotBSY(10);
    FLASH -> CR |= FLASH_CR_LOCK;
}


#define FLASH_ERRORMASK     (FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_SIZERR | \
                            FLASH_SR_PGSERR | FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_RDERR | FLASH_SR_OPTVERR)
static void FLASH_CLEAR_ERRORS(void)
{
    FLASH -> SR = FLASH_ERRORMASK;
}


static int FLASH_ErasePage(uint32_t address)
{
    int result = !!(address % 2048);
    if(!result)
    {
        if(GERR_SUCCEEDED(result = FLASH_WaitForNotBSY(10)))
        {
            FLASH_CLEAR_ERRORS();
            FLASH -> CR &= ~FLASH_CR_PNB_Msk;
            FLASH -> CR |= ((address / FLASH_SECTORSIZE) << FLASH_CR_PNB_Pos) | FLASH_CR_PER;
            FLASH -> CR |= FLASH_CR_STRT;
            if(!(result = FLASH_WaitForNotBSY(10)))
            {
                result = FLASH -> SR & FLASH_ERRORMASK;
            }
        }
    }
    FLASH -> CR &= ~FLASH_CR_PER;
    return result;
}

static int FLASH_WriteData(uint32_t address, const void *data, size_t size)
{
    int result = GERR_SUCCESS;
    const unsigned char *ucdata = data;
    size_t dataChunk;
    volatile uint32_t *writePtr = (uint32_t *)address;
    union
    {
        uint64_t u64;
        uint32_t u32[sizeof(uint64_t) / sizeof(uint32_t)];
        uint8_t  u8[sizeof(uint64_t)];
    } __attribute__((aligned(8))) dataUnion;

    if(!(result = FLASH_WaitForNotBSY(10)))
    {
        FLASH_CLEAR_ERRORS();
        FLASH -> CR |= FLASH_CR_PG;
        while(size)
        {
            dataUnion.u64 = 0;
            if(size >= sizeof(uint64_t)) dataChunk = sizeof(uint64_t);
            else dataChunk = size;
            memcpy(dataUnion.u8, ucdata, dataChunk);
            *writePtr++ = dataUnion.u32[0];
            *writePtr++ = dataUnion.u32[1];
            if(GERR_FAILED(result = FLASH_WaitForNotBSY(10)) || (result = (FLASH -> SR & FLASH_ERRORMASK)))
            {
                break;
            }
            while(!(FLASH -> SR | FLASH_SR_EOP));
            FLASH -> SR = FLASH_SR_EOP;
            size -= dataChunk;
            ucdata += dataChunk;
        }
    }

    FLASH -> CR &= ~FLASH_CR_PG;

    return result;
}

它来自另一个STM,但在编程过程中具有相同的64位(它计算8位ECC,因此您始终需要写入64位)。您的微控制器中可能不存在某些错误位,因此请检查。其余的应该按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.