Configuration Data: Using the Internal FLASH instead of an external EEPROM

Many applications need to store persistent (non-volatile) data at runtime: configuration data, error logs, sensor data, calibration values, etc. The question is: where to store that data? If it is only a few kBytes, an SD card or similar is an overkill. Adding an external EEPROM? Sure, that works, but adds an extra part to the design. Some microcontroller have internal EEPROM. But what if not? Why not using the microprocessor internal flash memory?

Internal FLASH vs. external EEPROM

Internal FLASH vs. external EEPROM

Internal FLASH or external EEPROM?

Modern microcontroller have plenty of FLASH memory (128 kByte and more), and typically not everything is used. So instead adding an extra external EEPROM device to the design, I can consider to use the internal microcontroller FLASH program memory.

Points to consider using the internal FLASH:

  • The FLASH memory is typically organized in pages (1 KByte, 2 KByte, 4 KByte, etc). Usually the full page needs to be erased first before being programmed. This takes both time and energy, which is critical if I want to do this while the microcontroller is shutting down because of a power loss.
  • Many FLASH programming algorithms need the microcontroller interrupt switched off, so increases the interrupt latency time.
  • The internal FLASH memory erase-program cycles are typically lower than the one for EEPROM. The internal FLASH typically has 10k-100k cycles, while external EEPROM can have 500k-1M cycles.

Typically I’m using the internal FLASH memory when there are only a few write cycles (e.g. ideal for product configuration data which is written only once), and only for smaller amount of data (few KBytes) in order not to impact the interrupt latency time. If I need to write large amount of data, or I’m concerned about erase-write cycles, then I typically use an external EEPROM, see “Driver for Microchip 24xx Serial EEPROM“.

There are devices which have internal EEPROM too: these devices are an alternative to external EEPROM, and typically have the same advantages and disadvantages.

What do I need?

In order to use the internal program memory for my data at runtime, I need

  1. Reserve/allocate a chunk of memory so it does not get used by the Linker for the constant data/program at runtime
  2. A library/function with the FLASH programming algorithm implemented I can use from my application.

Programming the internal FLASH with Processor Expert Component

Using Processor Expert makes things really easy, so I’m showing here the steps how I can program the FLASH with it. In my example I’m using the Freescale FRDM-KL25Z board, but steps and settings are very similar for any other architecture supported by Processor Expert.

IntFLASH Component

I add the IntFLASH (Internal FLASH) component to my project. It offers many functions to program the flash memory:

IntFLASH Processor Expert Component

IntFLASH Processor Expert Component

There are functions to write a 8bit (SetByteFlash()), 16bit (SetWordFLASH()) or 32bit (SetLongFlash()) values. I prefer to use the SetBlockFlash() as with it I can write any size of data. These functions make the ‘flash programming applets’ which are needed to correctly erase and program the FLASH memory.

The component properties offers settings to configure how the programming shall be handled. Typically I use these settings:

IntFlash Settings

IntFlash Settings

  • Safe write (with save & erase) write method: the component will make a backup of the FLASH page before erasing the page. This needs a buffer of the size of the FLASH page. I have the buffer type implemented by the method. Alternatively I could provide a buffer from the application memory.
  • Interrupts service/event disabled: I’m ok to use polled mode to wait for the programming finished.
  • Wait in RAM: on many processors, the program FLASH memory bus is not accessible while the FLASH is programmed. With this setting the code waiting for the programming completed will run in RAM.

There are other settings explained in the help of the component (see “Getting Help on Processor Expert Components“).

An important information is provided by the code generated by the IntFLASH component: how big a flash page or sector is on my microcontroller. This is a define in the generated header file:

AREA_SECTOR_SIZE with the flash block size

AREA_SECTOR_SIZE with the flash block size

So for my above example, it means that a flash block is 1 KByte (0x400). So an erase operation will erase that full block, and that when I allocate my data blocks below, it has to be aligned on that boundary and size.

Reserving Memory for my Data

I need to tell the linker that I’m going to use part of the FLASH memory for my data storage. Otherwise the linker might place data or program code in the area where I want to store my non-volatile data. Traditionally I change the linker file and reserve a section of memory so it is not used by the linker at link time.

For Processor Expert, I do this in the ‘Build options’ tab of the CPU component where I find the ROM/RAM areas generated in the linker file:

Build Options Tab of CPU component

Build Options Tab of CPU component

For my KL25Z microcontroller, the FLASH memory (MemoryArea2) starts from 0x410 and has a size of 0x1FBF0:

Default KL25Z 128KByte FLASH Area

Default KL25Z 128KByte FLASH Area

From above, I know that the FLASH block size is 0x400 (1 KByte), and I do not need more than one page, so I reduce the m_text size by 0x400 (0x1FBF0 ==> 0x1F7F0) and a new memory area with size 0x400 starting at address 0x1FC00:

Added NVM_Config Section

Added NVM_Config Section

 Programming the FLASH from the Application

The last part is to use it from the application. Typically I have a header file like the one below where I have the addresses defined:

/**
 * \file
 * \brief Interface for the Non-Volatile-Memory
 * \author Erich Styger
 *
 * This provides an interface to store and retrieve data from the on-chip memory.
 */

#ifndef CONFIGNVM_H_
#define CONFIGNVM_H_

#define NVMC_FLASH_START_ADDR    0x1FC00 /* NVRM_Config, start address of configuration data in flash */
#define NVMC_FLASH_ERASED_UINT8  0xFF
#define NVMC_FLASH_ERASED_UINT16 0xFFFF

#define NVMC_REFLECTANCE_DATA_START_ADDR  (NVMC_FLASH_START_ADDR)
#define NVMC_REFLECTANCE_DATA_SIZE        (8*2*2) /* maximum of 8 sensors (min and max) values with 16 bits */
#define NVMC_REFLECTANCE_END_ADDR         (NVMC_REFLECTANCE_DATA_START_ADDR+NVMC_REFLECTANCE_DATA_SIZE)

#define NVMC_SUMO_DATA_START_ADDR         (NVMC_REFLECTANCE_END_ADDR)
#define NVMC_SUMO_DATA_SIZE               (4) /* 4 bytes of data */
#define NVMC_SUMO_END_ADDR                (NVMC_SUMO_DATA_START_ADDR+NVMC_SUMO_DATA_SIZE)

uint8_t NVMC_SaveReflectanceData(void *data, uint16_t dataSize);
void *NVMC_GetReflectanceData(void);

uint8_t NVMC_SaveSumoData(void *data, uint16_t dataSize);
void *NVMC_GetSumoData(void);

#endif /* CONFIGNVM_H_ */

In that header file I have the addresses defined (based on the start address), plus getter and setter routines.

❗ Be careful about alignment. E.g. on many devices the addresses have to be aligned to 4 bytes for 32bit accesses.

The implementation then looks like this:

/**
 * \file
 * \brief Implementation of Non-Volatile-Memory storage
 * \author Erich Styger
 *
 * This provides an implementation to store and retrieve data from the on-chip memory.
 */

#include "NVM_Config.h"
#include "IFsh1.h"

static bool isErased(uint8_t *ptr, int nofBytes) {
  while (nofBytes>0) {
    if (*ptr!=0xFF) {
      return FALSE; /* byte not erased */
    }
    ptr++;
    nofBytes--;
  }
  return TRUE;
}

uint8_t NVMC_SaveReflectanceData(void *data, uint16_t dataSize) {
  if (dataSize>NVMC_REFLECTANCE_DATA_SIZE) {
    return ERR_OVERFLOW;
  }
  return IFsh1_SetBlockFlash(data, (IFsh1_TAddress)(NVMC_REFLECTANCE_DATA_START_ADDR), dataSize);  
}

void *NVMC_GetReflectanceData(void) {
  if (isErased((uint8_t*)NVMC_REFLECTANCE_DATA_START_ADDR, NVMC_REFLECTANCE_DATA_SIZE)) {
    return NULL;
  }
  return (void*)NVMC_REFLECTANCE_DATA_START_ADDR;
}

uint8_t NVMC_SaveSumoData(void *data, uint16_t dataSize) {
  if (dataSize>NVMC_SUMO_DATA_SIZE) {
    return ERR_OVERFLOW;
  }
  return IFsh1_SetBlockFlash(data, (IFsh1_TAddress)(NVMC_SUMO_DATA_START_ADDR), dataSize);  
}

void *NVMC_GetSumoData(void) {
  if (isErased((uint8_t*)NVMC_SUMO_DATA_START_ADDR, NVMC_SUMO_DATA_SIZE)) {
    return NULL;
  }
  return (void*)NVMC_SUMO_DATA_START_ADDR;
}

There are many ways how this can be implemented, but the above way worked very well for me. The getter functions return NULL in case the FLASH has been erased which is the case if the debugger has programmed the application. That way I know if there is already configuration data present or not.

For example, in my Sumo robot I could have a sudden reset or power loss. When the robot restarts, I want it to read the last configuration data from FLASH. In this example I only need a bit (but can be used for other data too). I store the configuration data at runtime into FLASH with NVMC_SaveSumoData():

static void SUMO_ChangeRunSumo(bool runIt) {
  if (runIt != SUMO_doRunSumo) {
    /* value changed */
  #if PL_HAS_CONFIG_NVM
    uint16_t val;
    
    if (runIt) {
      val = 1; /* enable */
    } else {
      val = 0; /* disable */
    }
    (void)NVMC_SaveSumoData(&val, sizeof(val));
  #endif  
    SUMO_doRunSumo = runIt;
  }
}

Then, if the robot starts, it checks the data in FLASH:

static portTASK_FUNCTION(SumoTask, pvParameters) {
#if PL_HAS_CONFIG_NVM
  void *p;
  uint16_t val;

  p = NVMC_GetSumoData();
  if (p!=NULL) {
    val = *(uint16_t*)p;
    if (val==1) {
      SUMO_doRunSumo = TRUE;
    } else {
      SUMO_doRunSumo = FALSE;
    }
  } else {
    SUMO_doRunSumo = FALSE;
  }
#endif  
  (void)pvParameters; /* not used */
  SUMO_State = SUMO_STATE_IDLE; /* init state */
  for(;;) {
...

Summary

Instead of an external EEPROM, the microcontroller internal FLASH can be used to store and read data. With this, no external parts are needed, and usually there is plenty of room left on the microcontroller to store things like settings or calibration data. And with the use of Processor Expert it can be easily implemented. But the same principles apply for projects without Processor Expert: all what I need is a change in the linker script plus a FLASH programming library.

Happy Flashing 🙂

Advertisements

99 thoughts on “Configuration Data: Using the Internal FLASH instead of an external EEPROM

  1. Hi Erich,

    A big THANKS for the support. This is very helpful.
    I’m introducing the kinetis and codewarrior to my colleagues and students here in the Philippines. You’re blog is such a good reference.

    Like

  2. I’ve been using this for years, and never failed so far. This method also brings data-security if the security options of the internal Flash is used. However, I find the PE a bit cumbersome to do this. I prefer doing in a more direct way, just including PageErase and ProgramByte functions, which could be obtained in Freescale’s application notes, and calling them.

    Like

  3. Hi Erich,

    I was wondering how can I implement writing a string in flash using this code. For example writing “mcu”, I want to every charter in each byte. And how am I supposed to read it back.

    Thanks.

    Like

    • Writing a string is not any different than writing any other data.
      To write such a string use e.g.
      IFsh1_SetBlockFlash(“mcu”, (IFsh1_TAddress)(NVMC_STRING_START_ADDR), sizeof(“mcu”));

      Like

      • Hi Erich,

        It returns this warning:

        ../Sources/NVM_Config.c:45:2: warning: pointer targets in passing argument 1 of ‘IFsh1_SetBlockFlash’ differ in signedness [-Wpointer-sign]

        Also how can I read it back?

        Thanks.

        Like

      • about the warning: simply insert a cast (I was too lazy).
        There are multiple ways how to read the string. I recommend to use a getter function like shown in the post.
        Or if you know that there is a valid string, you can use the pointer to the data (with a cast) too.

        Like

      • Thanks Erich.
        Im very new to kinetis and some freescale mcu, so sorry for some newbie questions.
        I will try our suggestions. I hope you have some discussion about this..

        Regards…

        Like

  4. Hi Erich,

    In my case the JTAG programmer deletes the saved data when it reprogrames the MCU. What didn’t I configure? (I’ve followed every single details of your tutorial)

    Thank you!

    Like

      • Erich ,Thank you !
        I just started learning FLASH , can you Provide me a demo about erase and write flash simply without Processor Expert Component ? I want to learn the process at length. It is better about the kinetis and codewarrior 10.x .Thank you very much!

        in detail
        at length

        Like

      • hi Erich,
        I know kL25Z128vlk4 have 128k flash ,and the flash sector size is 1 k from datasheet, while where can i find the divide of sector or each sector’s addrees ?

        Like

      • You find the memory map e.g. in the linker file:
        MEMORY {
        m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
        m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x0001F7F0
        m_data (RW) : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
        NVM_Config (RWX) : ORIGIN = 0x0001FC00, LENGTH = 0x00000400
        m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
        }

        Like

  5. Using PE is & a fixed address is abit ugly. Many times you don’t truly truly need to define the address manually. In CW you can force a variable to be in flash/rom if it is const & initialized & prefixed. You can then write to it without exceptions if it is sector aligned. For example: in global space write the following
    __attribute__ ((aligned(0x400))) //Define in global space!
    __inline const char myArray[0x400] = {};

    then in your main you can write to it via the following:
    IFsh1_SetByteFlash((uint32_t)(&myArray),’A’);

    Note this “IFsh1_SetByteFlash” is the PE component demoed in the tutorial above. You could also write your own Flash driver if you want to eliminate the use of PE all together. See this tutorial combined with the information I just posted:
    http://community.arm.com/groups/embedded/blog/2014/04/07/writing-data-to-flash-during-program-execution-with-the-freescale-kl25z-series

    Sadly the “__attribute__ at” doesn’t work in CW. which is why you will need to do what I did above.

    Anyhow, this method is nice cause it doesn’t force you to muck with the linker file.

    Like

    • Hi Nathan,
      thanks for sharing! That’s indeed another nice way to do it, so I need to keep this one in mind. Using absolute addresses really is a brute force way to do it, I agree. About the __attribute__ syntax: did you use CW with GNU gcc, or with the Freescale ARM compiler?

      Like

  6. Pingback: Unlocking and Erasing FLASH with Segger J-Link | MCU on Eclipse

  7. Pingback: Tutorial: How to Erase the FLASH with the GNU debugger | MCU on Eclipse

  8. Hello Mr Styger, best wishes for 2015! ( i know… im a bit late for that :S )

    I amtrying to use the FlexNVM part of my K20DX72 which is supposed to have 32kb of Flex Memory. I think I’m a little confused but lets say I understand some parts of its functionnalities ( from AN4282 : Using the Kinetis Family Enhanced EEPROM Functionality ) :
    – There is a EEE controller that uses the FlexRAM to backup in the FlexNVM depending on an EEPROM size.
    – There is a splitting possible to treat the memory as part D-Flash and part E-Flash.

    My question is, is the D-Flash part (A subsystem) the accessible part and the E-Flash (B subsystem) the automatic backup part not accessible because it is managed by the EEE controller? Or, is it that the 1kb “eeprom” size selected is mapped on the E-Flash (B subsystem) and the A subsystem is ordinary flash memory, that can be used at compile time as program code or data?

    What confuses me is in the intFlash_LDD, I use 8kb for the EEPROM backup size, for a 512 bytes Eeprom size. For my cpu, Flex Memory starts at 0x10000000 and is 32kb large. Doing so, gives me 0x6000kb Dflash block (0x8000kb – 0x2000kb) that can be mapped in the “Build Options”of the Cpu component. I was guessing that the 8kb(->512bytes) I wanted to configure as eeprom was mapped after the Dflash and managed by the EEE controller. I wanted to use the IntFLASH component to access the eeprom data but somehow I can’t. My guess is, the FlexNVM can be splitted like so 1/8 (A) + 7/8 (B), A subsystem is the accessible part and B subsystem is the backup part, the ratio gives you endurance, and my EEPROM address is starting at 0x10000000.

    I’m a bit confused because your example above doesn’t seem to use the FlexNVM, but ratter uses direct flash access without the EEE controller part and the FlexRAM. Or maybe it is, and the EEPROM is actually mapped on the Flash Block 1, I just don’t understand how everything works.

    As usual, thanks for your help,
    Mevon

    Like

    • From AN4282 : Using the Kinetis Family Enhanced EEPROM Functionality :
      “How FlexMemory EEE works
      To provide enhanced EEPROM functionality, the FlexMemory uses a RAM block (FlexRAM), a flash
      block (FlexNVM), and EEE state machine. When the EEE functionality is enabled, the FlexRAM becomes
      your EEE memory. The FlexRAM address space is where you access all of your EEE data. When the EEE
      is accessed, the EEE state machine keeps track of the data and backs it up as data records, stored in some
      portion of the FlexNVM used as an E-flash. Using a large block of E-flash to back up the data for a smaller
      amount of EEE data allows the FlexMemory EEE implementation to offer extremely high endurance.

      My guess is I need to access the FlexRAM to access the FlexNVM ( FlexRAM address range = 0x1400_0000 – 0x1400_07FF) and the “virtual eeprom” is not accessible from within the IntFLASH component?

      Thanks immensly,
      Mevon

      Like

  9. Hi Erich,

    Thanks for the post, it has been very useful.

    About how to read the data from the flash, I understand the getting methods with: byte, word, or longe because the functions have as argument the pointer to return the data.

    But I don’t understand how to use the SetBlock Flash, there’s not poiter. I looked in web and in the component help, but I still don’t get it. ¿Can you give me an example?

    Thank you.

    Like

    • Hi Camilo,
      SetBlockFlash() uses int32 (a 32bit number which corresponds to the memory address). Below is an example how I use it:


      #define NVMC_REFLECTANCE_DATA_START_ADDR (NVMC_FLASH_START_ADDR)
      #define NVMC_REFLECTANCE_DATA_SIZE (6*2*2) /* maximum of 6 sensors (min and max) values with 16 bits */
      #define NVMC_REFLECTANCE_END_ADDR (NVMC_REFLECTANCE_DATA_START_ADDR+NVMC_REFLECTANCE_DATA_SIZE)

      uint8_t NVMC_SaveReflectanceData(void *data, uint16_t dataSize) {
      if (dataSize>NVMC_REFLECTANCE_DATA_SIZE) {
      return ERR_OVERFLOW;
      }
      return IFsh1_SetBlockFlash(data, (IFsh1_TAddress)(NVMC_REFLECTANCE_DATA_START_ADDR), dataSize);
      }

      ...
      if (NVMC_SaveReflectanceData((void*)&SensorCalibMinMax, sizeof(SensorCalibMinMax))!=ERR_OK) {
      SHELL_SendString((unsigned char*)"FAILED saving calibration.\r\n");
      }
      ...

      Like

      • Hi Eric, Thanks for the answer, I understand.

        I’m having a problem saving the data, may be you know the solution.

        This is the function that I’m using to save the data:

        byte SaveFileCount (byte index, void* data, word dataSize) {
        if (dataSize > FILE_COUNT_DATA_SIZE) {
        return ERR_OVERFLOW;
        }
        return IFsh1_SetBlockFlash((IFsh1_TDataAddress)data, (IFsh1_TAddress)(FILE_COUNT_START_ADDR + index), dataSize);
        }

        This is how I’m using the function:

        int count;

        err = SaveFileCount(index,(void*)&count, sizeof(count));
        if (err == ERR_OK){
        (void)CDC1_SendString((str) “\r\nSaved!”);
        } else {
        (void)CDC1_SendString((str) “\r\nNot saved! “);
        CDC_SendInteger(e);
        }

        With the serial port I change the value of count and try to save it.

        The problem is that in the first try just after the debugger, works fine, but in a second try with a different value it fails except when the value is zero or sometimes when is 1 or 2. After that, works only when the value is the same that it’s already saved.

        When fails Always the error is: ERR_VALUE – Read value is not equal to written value.

        Do you know what is the problem?

        Thank you so much.

        Like

      • No, I haven’t.

        That was the problem, I’ve set the write mode to ‘safe write’ and now it works well.

        Thank you so much for the help.

        Like

  10. Hi erich,
    I want to increase the endurance and hence i’m using 2 sectors for eeprom emulation. when the data storing is started in the next sector, i’m erasing the previous sector. For this, sector0 start = 1fc00 size 400, and what do i configure the next sector start address? How do i arrive at this value? i tried setting 20000 as the sector1 start address, throws an error “there is no access into the memory from 20000 to 20400” in cpu->build options->ram/rom. Please advise.

    thanks,
    pramod tm

    Like

    • I just realized this is 128k part and i’m trying to write beyond it which doesn’t exist. I have decreased the m_text by 0x400 and the new sector starts from 128k-0x800-(other rx/rwx). It works as expected.

      Thanks,
      Pramod TM

      Like

  11. Hi Erich,

    Thanks for the post, it has been very useful.

    I’m working with the “FRDM-K64F” platform and I can not determine the start address of the “Flex Memory,” then I can not set the parameters for the memory space reserved. I put any direction, up from blocks allocated in the CPU, and tells me that does not exist direction. Something similar to the post of “March 15, 2015 at 14:32”.

    But I have another problem before that. When I add the component IntFLASH, I set everything as you indicate you and to generate the code, it generates this:

    ….
    #ifndef __BWUserType_IFsh1_TDataAddress
    #define __BWUserType_IFsh1_TDataAddress
    typedef byte* IFsh1_TDataAddress ; /* Address of the data block in memory for methods Get/SetBlockFlash. To maintain backward compatibility, it is double-word on Freescale 56800/E family, otherwise it is pointer to the smallest addressable unit (byte). */
    #endif

    #define IFsh1_WRITE_TYPE_SAFE
    /* Number of flash memory areas. For each area there are several constants with information about the area. */
    #define IFsh1_AREA_COUNT (0x02U)
    /* TRUE if the component setting allows rewrite of already programmed flash memory location. */
    #define IFsh1_ALLOW_CLEAR (TRUE)

    typedef LDD_FLASH_TAddress IFsh1_TAddress;
    ….

    and I can not set values:

    /* Minimal erasable unit. Value is in minimal addressable units */
    #define IFsh1_AREA_SECTOR_SIZE (0x0400U)

    It will be for the component version, or the version of CodeWarrior, or the platform I’m using?

    I hope you can help me, because I’m really stuck with it to save non-volatile values.

    Thank you,
    Gabriel

    Like

    • Hi Gabriel,
      I have not used FlexMemory with the K64F, and it even could not be available on that device (I think it depends on the part number). As for the Flash sector size: this is device (flash technology specific).

      Like

  12. Erich,
    Another great post, thank you! My question is that I have a software version that I would like to store in the NVM section that I created. I would prefer not to write the version string to the flash at each boot as this is unnecessary wear on the device. Is there a way to put a variable in the flash at a specific memory location. I have tired the __attribute__((at(0x1FD60))); and I do not think that at() it is supported by GCC. I read your your post titled about defining variables at absolute addresses with GCC (https://mcuoneclipse.com/2012/11/01/defining-variables-at-absolute-addresses-with-gcc/) but the problem with this is that in my data is not at the start of the new memory area NVM_Config area, is this what the “aligned” modifier is for? Also it appears that you manually have to change the linker file for this, and that is not ideal for my application as this is an easily forgotten step that could “break” the application down the road.
    I also need to add a CRC to my flash image so I read the SRecord article you wrote, I was thinking if all else fails I could concatenate a custom S19 file that contains the version string at the correct addresse(s), but that sounds FAR more complicated… I am hoping there is an easy way to force the 7 bytes in flash that I need. Thank you in advance for the help!!

    Like

    • Hi CoryF,
      Not sure why you think it is necessary to write the version string to FLASH at each boot? You only need to do this if the version information is erased or really need to be updated. and yes, at() is not supported in GNU/gcc, and you already have found the right article how to place variables at a given address :-). Aligned is used to make sure the variable/object is properly aligned according to the bus/CPU architecture (e.g. that each 32bit variable is at a 4byte address. And I can definitely recommend the SRecord utility, as this one makes all these more complex things possible. Give it a try.

      Like

  13. Hello Erich,
    Thank you for yet another great posting. I am trying to implement a similar use of internal Flash for non-volatile data storage. I have discovered an issue that I believe may be a bug in processor expert. Perhaps you can weigh-in on our discussion in the Freescale forum: https://community.freescale.com/thread/357531
    It would be helpful to know if I’m crazy, or just doing something I shouldn’t do…
    🙂

    Like

    • Hello,
      I only read that community post at a high level. I have to say that in all my cases I’m using the ‘safe write’ method, and not the ‘write’ only method. But from the description, I’m of the opinion that you have found a bug in Processor Expert flash programming?

      Like

  14. Hi Erich,

    Thanks again for this great tutorial !

    I have a little and maybe dummy question about address and size of pointed data in the flash memory, probably linked with the alignment. I am a little confusing about that.
    I understand that :
    1FC00 : represents the starting address of the data user
    400 : is the size of available space for that data
    1FC00 + 1 : should be the second available address
    1FC00 + 2 : should be the third available address

    First question for be sure: 400 does it represent the number of available address ? Means that the last address is 1FC00 + 400 ?

    After:
    If I want to write a uint8_t (1 bytes, 8bits) : I can use one of this address, without constraint.
    If I want to write a uint16_t (2 bytes, 16bits) : need to use an address that can be devised per 2 ?
    If I want to write a uint32_t (4 bytes, 32bits) : need to use an address that can be devised per 4 ?

    so, does it mean that each address point to a space of 8 bits ?

    If yes, it’s will mean that 400 represents : 4*8^2=256 bytes, which is different from 1Kbytes

    I probably have some mistake in my understanding, but cannot find where…

    Thanks in advice for your answer 😉

    Like

  15. Hello Erich,

    Thank you very much for this greate tutorial.

    I have aproblem when I debug the code. i just want to write a byte in the Flash. When i try to write a byte with the method IFsh1_SetByteFlash(dest_addr, data), the compiler just jump to the __thump_startup() methode in the __arm_start.c file!! i do not understand why its happened?

    Thanks in advice!
    Hani

    Like

    • Hello Hani,
      if the code jumps back to the startup code, it usually means your microcontroller has performed a reset. That could be because of the watchdog (is it turned on? If so, you have to serve it because the flash programming can take a while).
      I hope this helps,
      Erich

      Like

      • Hello Erich,

        The Watchdog is disabled! The code is just going in an infinit loop in the IFsh1_SetFlash(…) methode. see code below:

        byte IFsh1_SetFlash(IFsh1_TDataAddress Src, IFsh1_TAddress Dst, word Count)
        {
        LDD_TError Result;

        if (IFsh1_CmdPending) {
        return ERR_BUSY;
        }
        IFsh1_CurrentCommand = IFsh1_CMD_WRITE;
        IFsh1_CmdPending = TRUE;
        Result = IntFlashLdd1_Write(IntFlashLdd1_DevDataPtr, (LDD_TData *)Src, Dst, (LDD_FLASH_TDataSize)Count); /* Start reading from the flash memory */
        if (Result == ERR_OK) {
        do {
        IntFlashLdd1_Main(IntFlashLdd1_DevDataPtr);
        } while (IFsh1_CmdPending);
        Result = IFsh1_CmdResult;
        } else {
        IFsh1_CmdPending = FALSE; /* Command parameter error */
        if (Result == ERR_PARAM_ADDRESS) {
        Result = ERR_RANGE;
        }
        }
        return (byte)Result;
        }

        the variable IFsh1_CmdPending is always True! therefor the loop goes infinitly!

        What about the clock freq. for the Flash? my Bus frequency is 24Mhz. I am using the KEAZN8 with 8KB Flash.

        Thank you in advice.

        Hani

        Like

      • Hi Hani,
        I don’t have this device, so I cannot verify it. But IFsh1_CmdPending tells me that it started the flashing, but never completed it.
        Can you increase the stack size (to be sure that there is no suble stack overflow)?
        What I don’t understand is: earlier you said that the device resets and goes to the startup vector, but now you say it is hanging in this loop?
        Erich

        Like

  16. Hi Erich,
    Yes you are right, i explained it wrong.
    So the Problem still the same, programm jumps to the start up, cause it took alot of time in the while loop. i tryed to preserve the region that i used to not be erased when the controller starts, but no changes. What did you mean with the stack? did you mean the size of my Flash area?

    Hani

    Like

    • Hi Hani,
      I suspect that you still have your watchpoint enabled/turned on.
      With the stack I mean that you reserve enough memory for the stack. This is usually something like this in the linker file:
      __stack_size = 0x0600; /* required amount of stack */

      Like

  17. Hi Erich,

    you are right, the Watchdog was enabeld.
    but i still have the problem that the program hanging in the loop but not jumps to the startup method! but if i stopp running it i foud it hanging in the startup method. i am setting the FTMRE clk to 5MHz. and i incrreased the stack size but no effect.

    Like

  18. Hi Erich,

    i have good news :).
    if i enabel the interrupt service for the FTMRE component, the write method works fine! but the read method not, it jumps to the default interrupt handler method!! but i do not want to work with interrupts! i just want to write one byte to the flash and read it.

    Thanks.
    Hani

    Like

  19. Hi Erich,

    the solution was without interrupts. The problem was that i just tryed to read the Flash with the IFhs1_GetByte()-Method, not like yo did! But with your reading Method (Pointer Dereference) it works correctly!

    Hani

    Like

    • Hi Hani,
      that’s strange, and I don’t understand why. But indeed I have not used that access methods as I don’t need them.
      Thanks for letting me and everyone else know what solved it!
      Erich

      Like

      • Hi Erich,

        I think it is because of the interrupt. If I have the read methode and the interrupts are enabeld, so i have to get the byte in the ISR! but i did not find the ISR for the read method.

        But I have another problem: first, if i tried to write out side my reserved memors arrea it success!! Why? I told the linker about the area for my NVM. The flash has a page size of 512 Bytes, but i just need half of it, so that i just reserved 256 Bytes (0x100). i am using the setByteFlash()-Method, i want just to write 3-4 Bytes in the NVM. But the problem is, if i try to write with the method the Memory overwrites it is self, e.g.:
        eeprom_WriteByte((IFsh1_TAddress)0x1F00, 0x41);
        eeprom_WriteByte((IFsh1_TAddress)0x1F10, 0x42);
        eeprom_WriteByte((IFsh1_TAddress)0x1F20, 0x43);

        After the three writes the memory should have 0x41@0x1F00, 0x42@0x1F10 and 0x43@0x1F20. Some times it is like this, but some times the second write it is 0x46 or some thing else, or it overwrites the first write, the same is with the third write??? i do not understand.

        do i missing any thing? I need this for my project, i do not know where the problem is.

        thank you in advice.
        Hani

        Like

      • Hi Hani,
        no, I think you are not missing anything. This sounds like a bug to me. As for a try, can you add some delays between the writes to see if this helps? Otherwise I would recommend that you report this in the NXP forums so the engineeres could have a look at it.
        Erich

        Like

  20. Hello Erich,
    I have already added a delay between the writes, but did not help!
    Should the Flash Clock be divided to get it around 1 Mhz?

    Hani

    Like

  21. Hi Erich,

    What about read and write latencies? I measure for the write ca. 8ms, and for reading ca. 100us? Is that possible? I searched in the rederence manual for KEAZN8 but i did not find any thing about timing?

    Hani

    Like

    • Hi Hani,
      writing to FLASH is much, much slower than reading it. So 8 ms is maybe not very fast, but yes, could be realistic. I recommend that you read the specs (if there are any) about how much time is needed for writing.
      Erich

      Like

  22. Hi, Erich
    Thanks, very usefull post.

    There is a question:
    When KDS 3.2 with KSDK 1.3 used, what’s need to use instead
    #include “flash1.h” and
    IFsh1_SetBlockFlash() ?
    Are other corrections needed?

    Thanks in advice,
    Andrey

    Like

  23. Hi Erich,
    I would like to use program flash as EEPROM for kinetis MK10D processor.
    currently I was using FLASH_LDD component PE project . According to your tutorial , I need to use intFLASH component.
    FLASH_LDD component and intFLASH component are similar ?. Can I use intFLASH component instead of FLASH_LDD component ? Please help.

    BR,
    Rohit K.

    Like

  24. Erich, thanks for a very useful post.

    Do you have any suggestions for elegant ways to keep track of many variables saved to flash ? In your example, you had two variables (reflectance data, and Sumo data), and defined three parameters for each (start address, size, end address). This gets a bit lengthy if you have 20-30 variables to save. Would storing them as fields in a struct be a better option ? Any other suggestions ?

    Like

    • Hi Geoff,
      using individual variables and ranges are preferred for me if I have different versions of the firmware, where the not every version of the firmware needs all variables. That way I can easily turn things off. The other advantage is that I have less dependencies between the user of the storage, and the storage itself. But as you say, that gets complicated with many items.
      In that case, a struct is the better solution.
      What I’m using as well is storing parameters/settings on SD card (see https://mcuoneclipse.com/2014/04/26/frdm-with-arduino-ethernet-shield-r3-part-4-minini/). For this, I was thinking to have something similar in FLASH. Maybe a mini file system. But that only make sense for lots of variables/settings, because with the file system there is overhead.

      Like

  25. Pingback: Flash-based Configuration Data Using The ld Linker – vilimblog

  26. Hi Erich, great and very usefull post, as usual. Thanks!

    I normally work on custom boards using the Segger J-Link Pro, but I need to use this params saving method in the Freedom KL25 using its own OpenSDA. How could I preserve FLASH regions when using OpenSDA on the freedom board?

    Best regards, Victor

    Like

  27. Hi Erich,
    Need a little help! I want to store a value in flash, I saw your post in this link https://community.nxp.com/thread/329796 and I declared const char test[]=”hello” in my my bareboard project of FRDM-kl25z128 in code warrier 10.7. But I got an address like this:0x20002FF0. You can see it is not a flash address, So please help me to store a value in flash if you have time. I am really stuck in this, forgive me if I said anything stupid I am not pro embedded system 🙂

    Like

  28. Hi Erich,
    There is a big problem that should be mentioned here: if the CPU is in HSRUN mode (like 120Mhz) you cannot program the flash. This is true for lots of different M4’s, including the K22 and the K64 as far as I know.
    My project is running the K22 clock at 120Mhz (with a 16Mhz ext crystal), and these steps don’t work for me. The solution is to switch to a slower clock (80Mhz would be okay) when doing the flash erase and flash writes.
    Do you have a project that uses PEX to switch clocks in operation, I assume using the CPU_SetClockConfiguration() function to switch between them?

    Brynn

    Like

    • Hi Brynn,
      thanks for posting that comment, and indeed I saw such a discussion in the forums, and I thought that this was the problem I saw around the serial bootloader on K64F.
      From what I can tell, that HSRUN does not exist on the K64F, and somehow I have seen the flash programming problem with lower speed too on the K64F :-(.
      About switching clock configuration: yes, that’s the function to use. I believe I have a project somewhere using it on GitHub, but did not check.

      Like

    • I just tried using the CPU_SetClockConfiguration to switch to an 80Mhz clock instead of my 120Mhz clock, and it killed my USB connection. (otherwise it looked like it worked)
      Is there a way to suspend the USB briefly while I switch to 80Mhz and do some flash operations, then switch back to the 120Mhz and resume the USB?
      Or I’ll have to terminate the USB connection and then launch another after the clock returns to normal. I am just running CDC on the USB for a debug terminal connection – which is actually updating a 50×140 ANSI terminal screen 20 times a second which is lots of data…

      Like

      • Hi Brynn,
        yes, the USB block needs that 48 MHz to operarate, otherwise the connection will be lost. I have built in the Init() and Deinit() functions in the USB stack. I have not used them for that, but I know another use has sucessfully used it to shut down the USB communication and then start it gain.
        Or you might find a clock configuration with some prescalers which still keep the 48 MHz to the USB, but not sure if this will be supported easily.
        After all, it might be simpler to use an external I2C or SPI flash for your data?

        Erich

        Like

  29. Hi Erich,
    To late to change the hardware… I think we can live with losing the USB debug terminal when writing the calibration values.
    I am working to impliment the code, and found that at the beginning of the kinetis NVM component code they run a check to see if you are in clock_configuration_0, and if not, returns an ERR_SPEED error.
    Of course they seem to assume that clock_configuration_0 will be the NVM compatable speed, and anything else is not. My code has clock_configuration_0 being the 120Mhz, and _1 being the 80Mhz, so now I get a ERR_SPEED after slowing my clock…
    (AND before when I had just the one speed of 120Mhz I never got a ERR_SPEED which would have been apropriate)

    So short of rewriting the NVM PEX component, I’ll have to make clock config 0 be 80Mhz, and clock config 1 be the 120Mhz.
    We have lots of critical real-time control and floating point, so not running at 120Mhz is not an option.

    Brynn

    Like

  30. I would have to change the clock dividers that are set in the Init_USB_OTG section in my own code when I change the cpu clock, and it would have to not hiccup or barf at the change. Which seems unlikely I could make that change without some upset. Not a problem, as the USB is only going to be for developers or a service tech, and writes to flash will only affect that debug port.

    I will have to play with clock configs to make the number _0 one slow enough for the flash to be happy and _1 to be my Highspeed mode.

    Brynn

    Like

  31. Hi Erich,

    great tutorial, as you usually do.
    My question is:
    I am using a Freescale K60DN512 and MQX4.1 .I am not using PE.
    I need to store some data on NVM memory. I followed the MQX example flash_demo.c and it works fine.
    The problem is on the re-flash the program (for example for an update of FW) which erase also my previous data stored into NVM memory.
    Is there a way to preserve my NVM data after a reload of FLASH memory or I have to find another way (extern EEPROM bye I2C/SPI bus for example)? Thanks all,
    Stefano

    Like

  32. Hi Erich. I’m slowly moving over from KDS to MCUXpresso. One change is that manual modifications to the linker script is discouraged, and they recommend using the IDE to configure memory usage etc. I’ve looked through the documentation but haven’t quite understood how I could use the MCUXpresso IDE to configure the flash for saving a configuration variable, as you did in this article. Any chance you could provide a blog post on this ?

    Like

    • I have disabled automatic linker file generation for at least one of my projects. I agree that generating the linker file automatically is a good thing for new users or if you don’t need anything special, but changing the linker file is needed for any advanced projects.
      I see if I can come up with an article on that subject over the next week. Would that be ok?
      Erich

      Like

      • Thanks Erich. I’ve done some more reading and looking around, and think manually editing the linker file is what I’ll need to do. Since I am porting a project from KDS where I had already edited the linker file, it shouldn’t be hard to do the same thing in MCUXpresso.

        Like

      • Hi Geoff,
        I found have something which should help you with your data placement.
        In MCUXpresso IDE, use the menu Help > Help Content and search for “Placement of specific code/data items” (Chapter 12. Memory Configuration and Linker Scripts).
        I’m not fully through that, but it seems that this is the way to go.
        Erich

        Like

      • Thanks Erich. I did have a read through that section of the help file, but it seemed to be mostly offering ways to relocate code and/or data into specific RAM or flash blocks. But after bit more searching I’ve come across the following LPC support page which provides some instructions on how to allocate a variable to a specific address (basically, divide up and rename an existing block and place a single variable into the new block). They give the example of allocating a variable into an address in RAM, but I can’t see why it wouldn’t work also with flash also.
        “Placing data at an address” https://community.nxp.com/thread/389101

        Like

  33. Hi Erich,
    Great snippets on applications for the KL family! I am working on a KL26Z eval board using PE/CodeWarrior. I follow the steps listed above to use the internal FLASH but encounter ‘There is no access into memory from 0x410 to 0xf1c00’ when changing the size of m_text area basically not allowing me to partition the memory as above! Suggestions? Comment?

    Like

    • Hi Avdit,
      I’m not sure what you are saying? Where is this message coming from? I recommend that you partition the memory at the end of the lash area (e.g. reserve a 4K block).
      I hope this helps,
      Erich

      Like

  34. I found these interesting articles describing how using a table and only erasing (garbage collecting) when needed.

    ESA article: Using Flash Memory in Embedded Applications
    http://www.esacademy.com/en/library/technical-articles-and-documents/8051-programming/using-flash-memory-in-embedded-applications.html

    ST app note: AN2594
    http://www.st.com/content/ccc/resource/technical/document/application_note/ee/ef/d7/87/cb/b7/48/52/CD00165693.pdf/files/CD00165693.pdf/jcr:content/translations/en.CD00165693.pdf

    I think this should greatly increase the write life of my part when frequently updating the values of a few variables.

    Do you know of a library or example of implementing EEPROM emulation on a Kinetis KL05 or similar? (Just asking before I roll my own 😉

    Like

  35. A bit late to the game but my question relates to blocking/non-blocking resources.

    If I do not have DMA enables, will writes to FLASH be code-blocking? Resource (FLASH) blocking?

    Like

    • that depends on the flash controller on the chip and of the driver. Most I have seen are running a small program in RAM because the FLASH memory is blocked during programming. The bigger issue is that interrupts need to be disabled too.

      Like

  36. Hi Erich,
    This was a good tutorial where I learnt partitioning internal flash memory area into an NVM and saving my variables in the event of a power loss. However, what I intend on doing is using the 256 bytes of internal eeprom that I have available in my s9kean32 kinetis part. Is there a processor expert component for this?
    One of the ways to do this is to instruct the compiler while I declare my variables itself, to allocate memory for what I want saved in the internal eeprom area i.e. 0x1000_0000–0x1000_00FF as per the datasheet. On further digging on the compiler user manual- I stumbled across this.


    The compiler defines its own sections to organize the data and executable code it
    generates. You may also define your own sections directly in your program’s source code.
    Use the __declspec directive to specify where to place a single definition in object code.
    The following listing shows an example.
    Listing: Using the __declspec directive to specify where to place definitions

    Defining Sections in Source Code.
    #pragma define_section data_type “.myData” abs32 RW
    __declspec(data_type) int red;
    __declspec(data_type) int sky;


    Where can I find more info on this? Any thoughts on the approach is appreciated.
    Thanks!

    Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s