Writing a value on the flash memory in C

1

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)
c
embedded
nxp-microcontroller
asked on Stack Overflow Nov 20, 2019 by Asan • edited Nov 26, 2019 by Asan

1 Answer

0

This could be because your erase/program function is running from flash. The controller doesn't allow the flash to be erased/programmed when executing from flash. As a solution, you can copy the flash routine to RAM and execute from there.

To make sure if that is the case, please have a look at your map file and check the address of flash routines.

answered on Stack Overflow Dec 12, 2019 by Ummer K K

User contributions licensed under CC BY-SA 3.0