Currently I am trying to write a short string on the flash memory of the microcontroller I am using. The goal would be that the program writes the firmware version at a specific address so that the bootloader can read this and check if there is an update. The driver example provided by NXP seems to work (I can write and read the variable). However, when I place this code on my program I get error 103 kStatus_FTFx_AccessError
when running FLASH_Erase
and the next functions. Which to my understanding means that the address I set is not correct.
This is my memory map (linker file):
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00002000
m_text (RX) : ORIGIN = 0x00005000, LENGTH = 0x001FFBF0
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x00030000
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00030000
}
The function I am running:
#include "FlashStorage.h"
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "clock_config.h"
#include "fsl_flash.h"
#if defined(FSL_FEATURE_HAS_L1CACHE) && FSL_FEATURE_HAS_L1CACHE
#include "fsl_cache.h"
#endif /* FSL_FEATURE_HAS_L1CACHE */
#include "pin_mux.h"
#define BUFFER_LEN 4
/*! @brief Flash driver Structure */
static flash_config_t s_flashDriver;
/*! @brief Flash cache driver Structure */
static ftfx_cache_config_t s_cacheDriver;
/*! @brief Buffer for program */
static uint32_t s_buffer[BUFFER_LEN];
/*! @brief Buffer for readback */
static uint32_t s_buffer_rbc[BUFFER_LEN];
/***********************************************************************/
/* LOCAL FUNCTION PROTOTYPES */
/***********************************************************************/
/***********************************************************************/
/* GLOBAL FUNCTIONS */
/***********************************************************************/
void FLASH_WriteFlashMemory(void)
{
ftfx_security_state_t securityStatus = kFTFx_SecurityStateNotSecure; /* Return protection status */
status_t result; /* Return code from each flash driver function */
uint32_t destAdrss; /* Address of the target location */
uint32_t i, failAddr, failDat;
uint32_t pflashBlockBase = 0;
uint32_t pflashTotalSize = 0;
uint32_t pflashSectorSize = 0;
memset(&s_flashDriver, 0, sizeof(flash_config_t));
memset(&s_cacheDriver, 0, sizeof(ftfx_cache_config_t));
result = FLASH_Init(&s_flashDriver);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Setup flash cache driver structure for device and initialize variables. */
result = FTFx_CACHE_Init(&s_cacheDriver);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Get flash properties*/
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0BlockBaseAddr, &pflashBlockBase);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0TotalSize, &pflashTotalSize);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0SectorSize, &pflashSectorSize);
/* Check security status. */
result = FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Test pflash basic opeation only if flash is unsecure. */
if (kFTFx_SecurityStateNotSecure == securityStatus)
{
/* Pre-preparation work about flash Cache/Prefetch/Speculation. */
FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver, true);
/* Debug message for user. */
/* Erase several sectors on upper pflash block where there is no code */
PRINTF("\r\n Erase a sector of flash");
/* In case of the protected sectors at the end of the pFlash just select
the block from the end of pFlash to be used for operations
SECTOR_INDEX_FROM_END = 1 means the last sector,
SECTOR_INDEX_FROM_END = 2 means (the last sector - 1) ...
in case of FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP it is
SECTOR_INDEX_FROM_END = 1 means the last 2 sectors with width of 2 sectors,
SECTOR_INDEX_FROM_END = 2 means the last 4 sectors back
with width of 2 sectors ...
*/
#ifndef SECTOR_INDEX_FROM_END
#define SECTOR_INDEX_FROM_END 1U
#endif
destAdrss = 0x2400 ;
result = FLASH_Erase(&s_flashDriver, destAdrss, pflashSectorSize, kFTFx_ApiEraseKey);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Verify sector if it's been erased. */
result = FLASH_VerifyErase(&s_flashDriver, destAdrss, pflashSectorSize, kFTFx_MarginValueUser);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Print message for user. */
PRINTF("\r\n Successfully Erased Sector 0x%x -> 0x%x\r\n", destAdrss, (destAdrss + pflashSectorSize));
/* Print message for user. */
PRINTF("\r\n Program a buffer to a sector of flash ");
/* Prepare user buffer. */
for (i = 0; i < BUFFER_LEN; i++)
{
s_buffer[i] = 3;
}
/* Program user buffer into flash*/
result = FLASH_Program(&s_flashDriver, destAdrss, (uint8_t *)s_buffer, sizeof(s_buffer));
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Verify programming by Program Check command with user margin levels */
result = FLASH_VerifyProgram(&s_flashDriver, destAdrss, sizeof(s_buffer), (const uint8_t *)s_buffer, kFTFx_MarginValueUser,
&failAddr, &failDat);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
}
for (uint32_t i = 0; i < BUFFER_LEN; i++)
{
s_buffer_rbc[i] = *(volatile uint32_t *)(destAdrss + i * 4);
if (s_buffer_rbc[i] != s_buffer[i])
{
// error_trap();
}
PRINTF("\r\n VALUES: %d, %d, %d, %d ",s_buffer_rbc[0], s_buffer_rbc[1], s_buffer_rbc[2], s_buffer_rbc[3] );
}
/* Post-preparation work about flash Cache/Prefetch/Speculation. */
FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver, false);
#if defined(FSL_FEATURE_HAS_L1CACHE) && FSL_FEATURE_HAS_L1CACHE
L1CACHE_InvalidateCodeCache();
#endif /* FSL_FEATURE_HAS_L1CACHE */
#if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT
/* Clean the D-Cache before reading the flash data*/
SCB_CleanInvalidateDCache();
#endif
}
else
{
PRINTF("\r\n Erase/Program operation will not be executed, as Flash is SECURE!");
}
}
How can I prepare the memory to be suitable to be written? Or what would be a suitable address on where to write? I don't seem to understand why the memory address I am using is incorrect since it is not used in the memory map.
HW and compiler:
- Microcontroller: K66F Development board by NXP.
- Kinetis design studio IDE.
- GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc)
static const char __attribute__((section (".BootInfoSection"))) versionstr[16] = "01.01.01" ;
– Clifford