Writing to Internal Flash of STM32Fxxx

In the previous guide (here), we took a look how to read from the internal flash of STM32F411. In this guide, we shall see how to write to the internal flash storage of STM32F411.

In this guide, we shall cover the following:

  • Steps required to write to internal flash.
  • Developing the driver.
  • Code.
  • Results.

1. Steps required to write to internal flash:

The steps as following:

  • Unlock the flash.
  • Set the parallelism for the write operation.
  • Set the PG flag in FLASH->CR register.
  • Wait for busy flag to be idle.
  • Disable the PG bit in FLASH->CR.
  • Lock the flash.

2. Developing the driver:

Before writing to the internal flash. First, it needs to be unlocked by following these two steps:

Hence the to unlock the flash as following:

void flash_unlock(void)
{
	
	/*Check if the Lock is active*/
	if(FLASH->CR & FLASH_CR_LOCK)
	{
		FLASH->KEYR = 0x45670123U;
		FLASH->KEYR = 0xCDEF89ABU;
  }
}

It is recommended to check the lock status before unlocking the flash.

To lock the flash, set lock bit FLASH->CR register to 1 as following:

void flash_lock(void)
{
	FLASH->CR |= FLASH_CR_LOCK;
}

To write the to flash the following:

void flash_write32(uint32_t addrs, uint32_t *wr32, uint32_t len)
{
	//Write data in 16-bit at a time
	uint32_t tempAddrs = addrs;
	
	/*Set the parallelism to 32-bit (x32)*/
	FLASH->CR |=FLASH_CR_PSIZE_1;
	
	for(uint32_t i=0; i<len; i++)
	{
		//Set PG bit
		FLASH->CR |= FLASH_CR_PG;
		*(__IO uint32_t*) tempAddrs = wr32[i];
		tempAddrs+=4;
	
		//Wait for BSY flag to be idle
		while(((FLASH->SR)&(FLASH_SR_BSY)));
	
	}
		//Wait for BSY flag to be idle
		while(((FLASH->SR)&(FLASH_SR_BSY)));
		//Disable PG bit
		FLASH->CR &=~ FLASH_CR_PG;
}

Steps:

Store the passed address to temporary local variable (uint32_t tempAddrs = addrs).

Set the parallelism to 32-bit:

	/*Set the parallelism to 32-bit (x32)*/
	FLASH->CR |=FLASH_CR_PSIZE_1;

Within for loop:

Set the PG to 1:

		//Set PG bit
		FLASH->CR |= FLASH_CR_PG;

Write to the address and increment the address by 4:

		*(__IO uint32_t*) tempAddrs = wr32[i];
		tempAddrs+=4;

wait for flash to be idle by checking busy flag in FLASH->SR register:

		//Wait for BSY flag to be idle
		while(((FLASH->SR)&(FLASH_SR_BSY)));

Outside the for loop:

wait again for flash to be free:

	//Wait for BSY flag to be idle
	while(((FLASH->SR)&(FLASH_SR_BSY)));

disable PG bit:

	//Disable PG bit
	FLASH->CR &=~ FLASH_CR_PG;

Thats all for the driver:

in main.c file:

#include "stdio.h"
#include "delay.h"
#include "flash.h"
#include "uart.h"

uint32_t flash_data[4];
uint32_t data_write_flash[4]={0xdeadbeef, 0xbabababa,0xdadadada,0x12345678};

uint32_t address=0x08008000;

int main(void)
{
	uart2_tx_init(115200,16000000);

	systick_init_ms(16000000);

	flash_unlock();

	flash_write32(address, data_write_flash, 4);

	flash_lock();

	flash_read32(address,flash_data,4);

	printf("Written data at address 0x%x:\r\n",address);

	for (int i=0;i<4;i++)
	{
		printf("%d -> 0x%x\r\n",i,flash_data[i]);
	}

	while(1)
	{



	}
}

3. Code:

You may download the source code from here:

4. Results:

We have successfully wrote 4 words to the flash and read them back.

Happy coding 🙂

Add Comment

Your email address will not be published. Required fields are marked *