In this article, we will learn how to use Internal Flash of NXP MCXA Microcontroller. Internal Flash is mainly used for program flash but can also be used for storing configuration or various fixed settings which will vary certain features of the board. It can also be helpful to store data like board serial number, firmware, hardware version to track the product life cycle.
In certain use cases adding external EEPROM or Flash memory is not viable from PCB size or cost point of view, in those situations also internal flash comes very handy.
You can follow other blogs of NXP MCXA Microcontroller Programming Tutorial.

Memory Layout of NXP MCXA Microcontroller
Currently available NXP MCXA Microcontroller has max 128KB Flash Memory and the memory is divided into sector which is 8KB which further divides into Page of 128 Bytes and which further devices into 16 bytes Phrase.
There is a limitation that you can write or erase minimum is 1 phrase which is 16 bytes. So, your application logic should take care of this.
The example code is provided by NXP. You can open MCUxpresso goto File, New, Import SDK examples, select the MCXA and and look for flashiap in driver examples.

When I ran the code, it did not work and then we had to take help from NXP support and figured the code has issues. They provided a solution which needs System_Init() needs modification. You can see the NXP support thread here.
The example given is pretty simple. There are three API given for Internal Flash programming, one is for Erase, other is for Program or Flash and the third one if for Verify. Let is go through each one by one.
you need to create a flash driver structure and initialize it.
/*! @brief Flash driver Structure */
static flash_config_t s_flashDriver;
memset(&s_flashDriver, 0, sizeof(flash_config_t));
Then, you have to initialize the Flash.
Don’t worry about error_trap(); this is the function you can create to handle in case Flash API returns error.
if (FLASH_API->flash_init(&s_flashDriver) != kStatus_Success)
{
error_trap();
}
flash_get_property function can be used to get the Flash attributes like Sectorsize, page size, total size, etc.
uint32_t pflashBlockBase = 0U;
uint32_t pflashTotalSize = 0U;
uint32_t pflashSectorSize = 0U;
uint32_t PflashPageSize = 0U;
/* Get flash properties kFLASH_ApiEraseKey */
FLASH_API->flash_get_property(&s_flashDriver, kFLASH_PropertyPflashBlockBaseAddr, &pflashBlockBase);
FLASH_API->flash_get_property(&s_flashDriver, kFLASH_PropertyPflashSectorSize, &pflashSectorSize);
FLASH_API->flash_get_property(&s_flashDriver, kFLASH_PropertyPflashTotalSize, &pflashTotalSize);
FLASH_API->flash_get_property(&s_flashDriver, kFLASH_PropertyPflashPageSize, &PflashPageSize);
Once the initialization is successful, you need to erase the Flash sector/page or Phrase size, only then you can write the data.
Below api erases one sector size that 8KB but you can chose to erase onlye page or phrase depending on your requiremnt.
You should keep your address to be at the last so that it doesn’t interfere with your main application program space.
That is why destAdrss is defined as:
destAdrss = pflashBlockBase + (pflashTotalSize – (1* pflashSectorSize));
above defines the starting address as start of the last sector of the total flash memory.
if you want to keep address as start of last page you can do like below:
destAdrss = pflashBlockBase + (pflashTotalSize – (1* PflashPageSize));
status = FLASH_API->flash_erase_sector(&s_flashDriver, destAdrss, pflashSectorSize, kFLASH_ApiEraseKey);
if (status != kStatus_Success)
{
error_trap();
}
We can also verify if erase was successful by calling verify erase function
/* Verify if the given flash range is successfully erased. */
PRINTF("\r\n check if erase was successful or not");
status = FLASH_API->flash_verify_erase_sector(&s_flashDriver, destAdrss, pflashSectorSize);
if (status == kStatus_Success)
{
PRINTF("\r\n Erase Sector Successful: 0x%x -> 0x%x\r\n", destAdrss, (destAdrss + pflashSectorSize));
}
else
{
error_trap();
}
Once the Flash area is erased, you can write data to it. The function provided is flash_program_page() but you can write phrase size(16 bytes) data also by changing the size variable in the function input.
You will need buffer with a specified length to be passed to the API. See the code below to understand.
#define BUFFER_LEN 128
static uint32_t s_buffer[BUFFER_LEN];
// Fill the buffer with data
for (i = 0; i < BUFFER_LEN; i++)
{
s_buffer[i] = i;
}
/* Start programming specified flash region */
PRINTF("\r\n Programming Flash");
status = FLASH_API->flash_program_page(&s_flashDriver, destAdrss, (uint8_t *)s_buffer, sizeof(s_buffer));
if (status != kStatus_Success)
{
error_trap();
}
To verify if the Flash was successful, you can either read back and manually compare the bytes or use the verify function.
failedAddress & failedData are passed to get the start address and data where verify fails.
/* Verify if the given flash region is successfully programmed with given data */
PRINTF("\r\nVerify the data Flashed");
status = FLASH_API->flash_verify_program(&s_flashDriver, destAdrss, sizeof(s_buffer), (const uint8_t *)s_buffer,
&failedAddress, &failedData);
if (status != kStatus_Success)
{
error_trap();
}
That’s all in the Internal Flash Programming. I hope you were able to follow the blog and learned how to use Internal Flash of NXP MCXA Microcontroller.
My next blog in the series will be on how to use SPI Master on NXP MCXA Microcontrollers.
Enjoy learning NXP MCXA Microcontroller!
I am running an Embedded Design House, CAPUF Embedded Pvt. Ltd, located in Bangalore, India. At CAPUF Embedded, we help companies build embedded products with ourย ย hardwareย and firmware design services.
We also help in design optimizations for power consumption, cost, mass manufacturing, and performance. Additionally, we develop PCB testing jigs and provide cloud-based monitoring solutions.