STM32 Flash Erase Fails with "Programming Size Error" and "Programming Alignment Error"

173 views Asked by At

I'm using a stm32g070 and i'm trying to erase and program a data into the Flash. This is my code:

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

This code return the valor 96 in the HAL_FLASH_GetError() that correspond to 0b0110 0000, bit 5 (PGA ERR) and bit 6 (SIZ ERR) according to the Reference Manual 0454 (From STM32G070). Can anybody help me?

I try to understand why these errors are occurring and whether this is related to problems with the HAL layer.

1

There are 1 answers

0
0___________ On

I would suggest bare metal approach.

#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;
}

It is from another STM but having the same 64bits at the time programming procedure (it calculates 8 bits ECC so you need always to write 64 bits). Some error bits might not exist in your micro so check. The rest should work as expected.