cancel
Showing results for 
Search instead for 
Did you mean: 

Internal flash storage issue on STM32G0B1

Shaunus
Associate

Good day,

I am writing firmware for a custom board using the STM32G0B1KET6 and am experiencing issues related to writing a serial number to the internal flash.

As far as I can tell, this MCU has 512 KB of flash split into 2 banks of 128 pages (each page is 2 KB). I am attempting to write to the last page of the first bank (Page 127 @ 0x803F800).

I have modified the linker file to reduce the flash area used by my application code like so:

MEMORY
{
  RAM    (xrw)  : ORIGIN = 0x20000000,  LENGTH = 144K
  FLASH  (rx)   : ORIGIN = 0x8000000,   LENGTH = 64K
}

Here is my flash writing function. 

uint8_t Flash_Write(uint32_t startAddress, uint64_t data)
{
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_BSY1);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_BSY2);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CFGBSY);

	if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) == 1)
	{
		return 0;
	}

	HAL_StatusTypeDef status;
	uint32_t err;

    status = HAL_FLASH_Unlock();
    if (status != HAL_OK)
    {
        // Handle error
        printf("Failed to unlock flash.\r\n");
        return 0;
    }

    // Erase page first
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;

    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page      = (startAddress - FLASH_BASE) / FLASH_PAGE_SIZE;
    EraseInitStruct.NbPages   = 1;
    EraseInitStruct.Banks 	  = FLASH_BANK_1;

    status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    if (status != HAL_OK)
    {
    	err = HAL_FLASH_GetError();
    	printf("Failed to erase flash. Err: %lu\r\n",err);
        HAL_FLASH_Lock();
        return 0;
    }

    // Write data
	if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddress, data) != HAL_OK)
	{
		// Handle error
		err = HAL_FLASH_GetError();
		printf("Flash programming error. Err: %lu\r\n",err);
		HAL_FLASH_Lock();
		return 0;
	}

    HAL_FLASH_Lock();
    return 1;
}

void cmSetUID(void)
{
	uint64_t UID;
	uint8_t retry = 0;

	UID = atoi((char*)&DebugRxBuf[DebugRxPtr]);

	while(Flash_Write(0x0803F800,UID) == 0)
	{
		if(retry > 10)
		{
			printf("UID Set: FAILED\r\n");
			return;
		}
		else
		{
			//HAL_Delay(10);
			retry++;
		}
	}

	printf("UID Set: %lu\r\n",(uint32_t)UID);
}

void cmReadUID(void)
{
	uint64_t UID;
	UID = Flash_Read(0x0803F800);

	printf("UID Read: %lu\r\n",(uint32_t)UID);
}

For some reason the PGSERR and PGAERR flags are always set when the board is programmed or this function is entered, which is why I am manually clearing them to prevent failure at the HAL_FLASHEx_Erase function.

The issue that I am having relates to the CFGBSY flag, which is sometimes set on boot or after a successful write (but not always), and I cannot clear the flag as it is set/cleared by hardware. For some reason the CFGBSY flag will eventually go low after successive calls to the Flash_Write function even though the function returns if the flag is set.

Shaunus_0-1758113387876.png

Shaunus_1-1758114807711.png

If anyone has any ideas on why my flags are acting up I would greatly appreciate it.

Regards,

Shaun

 

1 REPLY 1
TDK
Super User

> For some reason the PGSERR and PGAERR flags are always set

Issue #1. This can be caused if something writes only half of a flash page.

> CFGBSY flag, which is sometimes set on boot or after a successful write

If CFGBSY is high, there's a pending erase or write operation. Is PG high? Probably a pending write operation. Solution is to wait for CFGBSY to drop.

 

Could be an issue with how your board is getting programmed prior to debugging. Maybe debugger is only writing half of a page. Ensure the HEX/ELF/BIN file (whichever is used to flash) is a multiple of 8 bytes.

If you feel a post has answered your question, please click "Accept as Solution".