SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Copying Information to EEPROM with Cortex M0+
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

Copying Information to EEPROM with Cortex M0+

Neil Salmon
Last updated: October 5, 2023 9:58 am
Neil Salmon 8 Min Read
Share
SHARE

The Cortex-M0+ is an ultra-low power 32-bit ARM Cortex-M processor optimized for cost-sensitive and power-constrained embedded applications. One of its key features is the embedded flash memory or EEPROM that allows you to store and retrieve information even when the power is turned off.

Contents
PrerequisitesEEPROM Organization in Cortex M0+Steps to Copy Data to EEPROM1. Include Header Files2. Define Flash Base Address and Registers3. Define Data to be Written4. Unlock Flash for Write Access5. Erase Target Sector6. Write Data Page by Page7. Verify Data8. Lock FlashExample CodeSummary

Copying data to the EEPROM with Cortex M0+ can be useful for storing configuration parameters, sensor calibration values, device identifiers, and other permanent data you may need for your application. This article will provide a step-by-step guide on how to write a program to copy information into the EEPROM using the Cortex M0+ processor and its peripherals.

Prerequisites

Before we dive into the programming, let’s go over some prerequisites:

  • A development board with a Cortex M0+ MCU like the STM32F0 Discovery kit
  • A C compiler for ARM Cortex-M like GCC
  • Basic knowledge of C programming
  • Understanding of microcontroller peripherals like GPIO, USART, SPI, I2C etc
  • Basics of embedded programming and toolchain setup

EEPROM Organization in Cortex M0+

The embedded flash memory in Cortex M0+ is organized into pages and sectors. A page is typically 1 KB while a sector can span multiple pages (16-256 KB). The smallest unit that can be erased is a sector. Before writing to a sector, it needs to be erased first.

The processor uses memory mapped I/O to access the flash memory. There are register mappings for flash memory control, status registers, address registers, data registers etc. By manipulating these registers, we can erase, program and access the embedded flash memory.

Steps to Copy Data to EEPROM

Here are the typical steps involved in copying information to the EEPROM with Cortex M0+:

  1. Include required header files like cmsis_gcc.h
  2. Define EEPROM base address and registers
  3. Define data to be written to EEPROM
  4. Unlock the Flash module for write access
  5. Erase the target sector
  6. Check that sector erase completed successfully
  7. Write data to the EEPROM page-by-page
  8. Verify data was written properly
  9. Lock the Flash module

1. Include Header Files

We need to include the CMSIS header file that contains definitions for the processor core, peripherals and device specific configuration.


#include "cmsis_gcc.h"

2. Define Flash Base Address and Registers

Define the base address for the flash memory module along with offsets to the various registers we need to access like control, status, address and data registers.


#define FLASH_BASE 0x08000000

#define FLASH_ACR *(volatile unsigned long*)(FLASH_BASE + 0x00)
#define FLASH_PECR *(volatile unsigned long*)(FLASH_BASE + 0x04)
#define FLASH_PDKEYR *(volatile unsigned long*)(FLASH_BASE + 0x08) 
#define FLASH_PEKEYR *(volatile unsigned long*)(FLASH_BASE + 0x0C)
#define FLASH_PRGKEYR *(volatile unsigned long*)(FLASH_BASE + 0x10)
#define FLASH_OPTKEYR *(volatile unsigned long*)(FLASH_BASE + 0x14)
#define FLASH_SR *(volatile unsigned long*)(FLASH_BASE + 0x18)
#define FLASH_OPTR *(volatile unsigned long*)(FLASH_BASE + 0x20)

3. Define Data to be Written

Next, we define a constant array that will hold the actual data we want to write to the EEPROM.


const uint32_t data_to_write[] = {0x12345678, 0x23456789, 0xABCDEF01}; 

4. Unlock Flash for Write Access

The flash control registers are locked by default. We need to write the correct unlock sequence to the FLASH_PEKEYR and FLASH_PRGKEYR registers to enable writes.


FLASH_PEKEYR = 0x89ABCDEF; // Unlock PECR register
FLASH_PECR |= 1; // Enable FPRG access

FLASH_PRGKEYR = 0x8C9DAEBF; // Unlock program memory
FLASH_PRGKEYR = 0x8C9DAEBF; // Unlock again

5. Erase Target Sector

Before writing, we need to erase the target sector to 0xFFs. This is done by setting the MER and SER bits in the FLASH_PECR register along with the sector number.


FLASH_PECR |= FLASH_PECR_ERASE; // Set sector erase bit 
FLASH_PECR |= 0x1 << 3; // Sector number
FLASH_PECR |= FLASH_PECR_STRT; // Trigger erase

// wait until erase completes
while(FLASH_SR & FLASH_SR_BSY) {}

// check for errors
if(FLASH_SR & FLASH_SR_EOP) {
  // Erase completed successfully
} else {
  // Error occurred 
}  

6. Write Data Page by Page

The programming is done on a page level granularity. So we write the data page by page inside a loop.


uint32_t *address = (uint32_t*)0x08010000; // Start address 

for(int i=0; i<sizeof(data_to_write); i+=4) {

  // Write 32-bit word to current address 
  *address++ = data_to_write[i/4];

  // wait until write completes
  while(FLASH_SR & FLASH_SR_BSY) {}

  // check for errors 
  if(FLASH_SR & FLASH_SR_EOP) {
    // programming completed successfully 
  } else {
    // error occurred
  }
}  

7. Verify Data

Once the programming is done, we should always verify that the data was written correctly by reading it back and comparing it.


address = (uint32_t*)0x08010000;

for(int i=0; i<sizeof(data_to_write); i+=4) {

  if(*address != data_to_write[i/4]) {
    // data mismatch found
  }

  address++; 
}

8. Lock Flash

Finally, we lock the flash control registers by writing the lock sequence.

 
FLASH_PECR |= 0x01;
FLASH_PRGKEYR = 0x8C9DAEBF; // Lock program memory  

Example Code

Here is an example program to demonstrate all the steps:


#include "cmsis_gcc.h"

#define FLASH_BASE 0x08000000

#define FLASH_ACR *(volatile unsigned long*)(FLASH_BASE + 0x00)
#define FLASH_PECR *(volatile unsigned long*)(FLASH_BASE + 0x04)
#define FLASH_PDKEYR *(volatile unsigned long*)(FLASH_BASE + 0x08)
#define FLASH_PEKEYR *(volatile unsigned long*)(FLASH_BASE + 0x0C)  
#define FLASH_PRGKEYR *(volatile unsigned long*)(FLASH_BASE + 0x10)
#define FLASH_OPTKEYR *(volatile unsigned long*)(FLASH_BASE + 0x14)
#define FLASH_SR *(volatile unsigned long*)(FLASH_BASE + 0x18)
#define FLASH_OPTR *(volatile unsigned long*)(FLASH_BASE + 0x20)

const uint32_t data_to_write[] = {0x12345678, 0x23456789, 0xABCDEF01};

int main(void) {

  // Unlock sequence
  FLASH_PEKEYR = 0x89ABCDEF;
  FLASH_PECR |= 1; 
  FLASH_PRGKEYR = 0x8C9DAEBF;
  FLASH_PRGKEYR = 0x8C9DAEBF;

  // Sector erase
  FLASH_PECR |= FLASH_PECR_ERASE;
  FLASH_PECR |= 0x1 << 3; // Sector 0
  FLASH_PECR |= FLASH_PECR_STRT;

  while(FLASH_SR & FLASH_SR_BSY) {}

  if(FLASH_SR & FLASH_SR_EOP) {
    // Erase done  
  } else {
    // Error
  }

  // Write data 
  uint32_t *address = (uint32_t*)0x08010000;

  for(int i=0; i<sizeof(data_to_write); i+=4) {
    *address++ = data_to_write[i/4];

    while(FLASH_SR & FLASH_SR_BSY) {}

    if(FLASH_SR & FLASH_SR_EOP) {
      // Write done
    } else {
      // Error
    }
  }

  // Verify data
  address = (uint32_t*)0x08010000;

  for(int i=0; i<sizeof(data_to_write); i+=4) {
    if(*address != data_to_write[i/4]) {
      // Data mismatch
    }
    address++;
  }

  // Lock sequence
  FLASH_PECR |= 0x01; 
  FLASH_PRGKEYR = 0x8C9DAEBF; 

  return 0;
}

Summary

In this article, we went through the steps needed to copy information into the embedded EEPROM or flash memory on a Cortex M0+ microcontroller. The key steps are:

  1. Unlock flash control registers
  2. Erase target sector
  3. Write data page by page
  4. Verify data
  5. Lock flash registers

By following these steps and manipulating the flash memory mapped registers, you can easily store permanent data on Cortex M0+ devices. The program memory can be used for storing firmware code whereas the embedded EEPROM is ideal for non-volatile data.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article SWD-Port of the Cortex-M0: Cannot connect to MEM-AP on Cortex-M0 Designstart Eval
Next Article Program FPGA Block RAM connected to Cortex-M0 using JTAG: is it possible?
Leave a comment Leave a comment

Leave a Reply Cancel reply

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

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

What are branch instructions in ARM Cortex M3?

The ARM Cortex-M3 is a 32-bit processor core licensed by…

10 Min Read

Changing Processor Modes on ARM with CPSR Writes

The ARM processor has several different processor modes that allow…

11 Min Read

FreeRTOS Context Switch

A context switch is a fundamental part of multitasking real-time…

5 Min Read

Arm Programming Software

Arm processors power technology that's transforming the world – from…

11 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account