Storing data in non volatile memory on KL43

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Storing data in non volatile memory on KL43

1,350 Views
piotrcerba
Contributor III

I am willing to save some program data in a non volatile memory on the board.

However, as I see KL43 does not have the EEPROM memory.

My question is: What to do if I want my configuration data to remain intact after powering off the device?

EDIT: I see that there is something like FlexMemory, however, I can't find if it is available in my board.

Labels (2)
0 Kudos
6 Replies

986 Views
mjbcswitzerland
Specialist V

Hi

You can write to any long word in the Flash so you can save parameters etc. anywhere (within reason) in the chip's Flash memory.

The KL43 doesn't have EEPROM or FlexMemory but this is also not needed for most such usage.

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html

KL43: http://www.utasker.com/kinetis/FRDM-KL43Z.html / http://www.utasker.com/kinetis/TWR-KL43Z48M.html

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

986 Views
piotrcerba
Contributor III

Good to know :smileyhappy:

Can you give me some more information on how to approach this topic? What instructions/keywords do I need to use  to program my board so that it stores some data after power-off? What are the limitations?

0 Kudos

986 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Piotr Cerba:

You can also download KSDK and use the available flash driver: Software Development Kit for Kinetis MCUs|Freescale

Once installed you would find project examples for the flash routines in these paths:

C:\Freescale\KSDK_1.2.0\examples\frdmkl43z\demo_apps\flash_demo

C:\Freescale\KSDK_1.2.0\examples\frdmkl43z\driver_examples\flash

Regards!

Jorge Gonzalez

0 Kudos

986 Views
piotrcerba
Contributor III

Despite looking into both KDSK projects - I can't find a proper function to write/program longword what Mark has mentioned.

Am I missing something?

Which of the functions from those example apps can be used for storing data in non-volatile part of Flash?

0 Kudos

986 Views
bobpaddock
Senior Contributor III

Is there a way to attach a .zip file?  Can't find it and 'Advance Editor' is not coming up (Again :-(  This system always hoses my code posts. :-( ).

Here are the functions you need.  It won't compile directly because of missing .h files (from the .zip file).

Mostly add #include <stdint.h> .

I wrote this for the KL27 a child of the KL43.  Add defines for KL43 and it should work with no other changes.

/** @(#)flash_kinetis.h <08-Oct-2013 13:49:11 Bob Paddock>

*  Last Time-stamp:    <19-Oct-2015 08:14:41 bob p>

*

*  \file flash_kinetis.h

*  \brief  Commands to erase/program Flash.

*

* Note!: CCIF: Depending on how quickly the read occurs after reset

*        release, the user may or may not see the 0 [busy] hardware

*        reset value.

*/

/*lint -save -e755 -e756 Disable warning(s), this file only, global macro/typedef 'Symbol' (Location) not referenced */

#ifndef _FLASH_KINETIS_H_

#define _FLASH_KINETIS_H_ (1)

#ifdef  DEFINE_SPACE_FLASH_KINETIS_H

#define EXTERN_FLASH_KINETIS

#else

#define EXTERN_FLASH_KINETIS extern

#endif

#if defined(__cplusplus) && __cplusplus

extern "C" {

#endif

#if( defined (MCU_MKL25Z4) || defined(MCU_MKL26Z4) || defined(MCU_MKL27Z4) )

#define FLASH_SECTOR_SIZE (1024UL) /* The smallest portion of the program flash memory (consecutive addresses) that can be erased */

   enum FTFA_CMDS{

     FCMD_OK                        = 0x00U, /* Command completed without error */

     FCMD_READ_1s_SECTION           = 0x01U, /* Verify that a given number of program flash locations from a starting address are erased */

     FCMD_PGM_CHECK                 = 0x02U, /* Tests previously-programmed locations at margin read levels */

     FCMD_READ_RSC                  = 0x03U, /* Read 4 bytes from program flash IFR or version ID */

     FCMD_PGM_U32                   = 0x06U, /* Program 4 bytes in a program flash block */

     FCMD_ERASE_FLASH_SECTOR        = 0x09U, /* Erase all bytes in a program flash sector */

     FCMD_READ_1s_ALL_BLOCKS        = 0x40U, /* Verify that the program flash block is erased then release MCU security */

     FCMD_READ_ONCE                 = 0x41U, /* Read 4 bytes of a dedicated 64 byte field in the program flash 0 IFR */

     FCMD_PGM_ONCE                  = 0x43U, /* One-time program of 4 bytes of a dedicated 64-byte field in the program flash 0 IFR */

     FCMD_PGM_ERASE_ALL_BLOCKS      = 0x44U, /* Erase the program flash block, verify-erase and release MCU security.  Only possible when all memory locations are unprotected */

     FCMD_VERIFY_BACKDOOR_ACCES_KEY = 0x45U, /* Release MCU security after comparing a set of user supplied security keys to those stored in the program flash */

     FCMD_ERROR                     = 0xFFU  /* Unknown Error.  Indicates some error in flash processing.  Used by higher level flash manipulations like valuestore functions */

   };

   enum FTFA_MARGINS{

     FMARGIN_NORMAL,

     FMARGIN_USER,

     FMARGIN_FACTORY

   };

#define FCMD_PGM_U32_MARGIN_FAILURE (0x80000000UL)

   enum FTFA_RESOURCES{

     FRSC_IFR, /* 256 bytes 0x00_0000 -> 0x00_00FF */

     FRSC_ID   /*   8 bytes 0x00_0000 -> 0x00_0007 */

   };

#endif /* #if defined( MCU_MKL25Z4 ) */

    /*

     * Push current alignment rules to internal compiler stack then

     * force 1-byte alignment boundary:

     */

#pragma pack(push,1)

   /*

    * Flash Common Command Object (FCCOB):

    *

    * The FCCOB register group uses a Big Endian addressing

    * convention. For all command parameter fields larger than one

    * byte, the most significant data resides in the lowest FCCOB

    * register number.

    */

   typedef union /* MISRA deviation */

   {

     uint8_t FCCOB_ary_u8[ 12U ];  /**< Flash Common Command Object Registers */

     struct /* As bytes: */

     {

       uint8_t FCCOB3_u8;          /**< Flash Common Command Object Registers, offset: 0x4 */

       uint8_t FCCOB2_u8;          /**< Flash Common Command Object Registers, offset: 0x5 */

       uint8_t FCCOB1_u8;          /**< Flash Common Command Object Registers, offset: 0x6 */

       uint8_t FCCOB0_u8;          /**< Flash Common Command Object Registers, offset: 0x7 */

       uint8_t FCCOB7_u8;          /**< Flash Common Command Object Registers, offset: 0x8 */

       uint8_t FCCOB6_u8;          /**< Flash Common Command Object Registers, offset: 0x9 */

       uint8_t FCCOB5_u8;          /**< Flash Common Command Object Registers, offset: 0xA */

       uint8_t FCCOB4_u8;          /**< Flash Common Command Object Registers, offset: 0xB */

       uint8_t FCCOBB_u8;          /**< Flash Common Command Object Registers, offset: 0xC */

       uint8_t FCCOBA_u8;          /**< Flash Common Command Object Registers, offset: 0xD */

       uint8_t FCCOB9_u8;          /**< Flash Common Command Object Registers, offset: 0xE */

       uint8_t FCCOB8_u8;          /**< Flash Common Command Object Registers, offset: 0xF */

     }FTFA_regs_8;

     struct /* As uint32: */

     {

       uint32_t FCCOB3210_u32;

       uint32_t FCCOB7654_u32;

       uint32_t FCCOBBA98_u32;

     }FTFA_regs_32;

   }FLASH_COMMAND_OBJ;

    /*

     *  Command Object is copied directly to hardware via the

     *  Flash_CMD_in_RAM therefore the definition of structures

     *  requiring tight packing, to match the underlying hardware that

     *  will not have possible structure padding:

     */

   EXTERN_FLASH_KINETIS FLASH_COMMAND_OBJ flash_cmd_obj;

   /* Restore original alignment rules from stack: */

#pragma pack(pop)

   uint32_t flash_cmd_in_ram( void ) __attribute__ ((long_call, section (".flash_cmd"))); /* Place in .data section of RAM */

   uint32_t flash_erase_sector(  uint32_t const *dst_adr_u32 );

   uint32_t flash_one_u32(       uint32_t const *dst_adr_u32, uint32_t const data_value_u32 );

   uint32_t flash_pgm_block_u32( uint32_t const *dst_adr_u32, uint32_t const *src_adr_u32, uint32_t const size_u32_in );

   /*

    * The first four bytes returned are the flash parameter revision,

    * and the second four bytes are the flash version ID:

    */

   uint32_t flash_read_id( uint8_t *const id_adr_u8 );

#if defined(__cplusplus) && __cplusplus

}

#endif

#endif /* _FLASH_KINETIS_H_ */

/*lint -restore */

/** @(#)flash_kinetis.c    <08-Oct-2013 14:13:04 Bob Paddock>

*  \date Last Time-stamp: <19-Oct-2015 08:14:02 bob p>

*

*  \file flash_kinetis.c

*  \brief  Commands to erase/program Flash.

*

* Note!: CCIF: Depending on how quickly the read occurs after reset

*        release, the user may or may not see the 0 [busy] hardware

*        reset value.

*/

/*lint -save */

#include "compiler.h"

#define  DEFINE_SPACE_FLASH_KINETIS_H (1)

#include "flash_kinetis.h"

uint32_t flash_read_id( uint8_t *const id_adr_u8 )

{

  flash_cmd_obj.FTFA_regs_32.FCCOB3210_u32 = 0UL;

  flash_cmd_obj.FTFA_regs_8.FCCOB8_u8      = (uint8_t) FRSC_ID;

  flash_cmd_obj.FTFA_regs_8.FCCOB0_u8      = (uint8_t) FCMD_READ_RSC; /* Read ID resource */

  uint32_t status_u32 = flash_cmd_in_ram();

  if( FCMD_OK != status_u32 )

    {

      return( status_u32 ); /* ID read failed */

    }

  /* Flash parameter revision: */

  id_adr_u8[0U] = FTFA_FCCOB4;

  id_adr_u8[1U] = FTFA_FCCOB5;

  id_adr_u8[2U] = FTFA_FCCOB6;

  id_adr_u8[3U] = FTFA_FCCOB7;

  flash_cmd_obj.FTFA_regs_32.FCCOB3210_u32 = 4UL;

  flash_cmd_obj.FTFA_regs_8.FCCOB0_u8      = (uint8_t) FCMD_READ_RSC; /* Read ID resource */

  status_u32 = flash_cmd_in_ram();

  /* Flash version ID: */

  id_adr_u8[4U] = FTFA_FCCOB4;

  id_adr_u8[5U] = FTFA_FCCOB5;

  id_adr_u8[6U] = FTFA_FCCOB6;

  id_adr_u8[7U] = FTFA_FCCOB7;

  return( status_u32 );

}

uint32_t flash_erase_sector( uint32_t const *dst_adr_u32 )

{

  flash_cmd_obj.FTFA_regs_32.FCCOB3210_u32 = ((uint32_t) dst_adr_u32 & ~(FLASH_SECTOR_SIZE - 1U)); /* Align requested address to start of sector boundary */

  flash_cmd_obj.FTFA_regs_8.FCCOB0_u8      = (uint8_t) FCMD_ERASE_FLASH_SECTOR;

  return( flash_cmd_in_ram() );

}

/*

* The supplied address must be longword aligned (the lowest two bits of the byte address

* must be 00):

*  • Byte 3 data is written to the supplied byte address ('start'),

*  • Byte 2 data is programmed to byte address start+0b01,

*  • Byte 1 data is programmed to byte address start+0b10,

*  • Byte 0 data is programmed to byte address start+0b11.

*/

uint32_t flash_one_u32( uint32_t const *dst_adr_u32, uint32_t const data_value_u32 )

{

  flash_cmd_obj.FTFA_regs_32.FCCOB3210_u32 = (uint32_t) dst_adr_u32;

  flash_cmd_obj.FTFA_regs_32.FCCOB7654_u32 = data_value_u32;

  flash_cmd_obj.FTFA_regs_8.FCCOB0_u8      = (uint8_t) FCMD_PGM_U32;

  uint32_t status_u32 = flash_cmd_in_ram();

  if( FCMD_OK != status_u32 )

    {

      return( status_u32 ); /* Flash write failed */

    }

/* Verify the written data a user margin levels: */

  flash_cmd_obj.FTFA_regs_32.FCCOB3210_u32 = (uint32_t) dst_adr_u32;

  flash_cmd_obj.FTFA_regs_32.FCCOBBA98_u32 = data_value_u32;

  flash_cmd_obj.FTFA_regs_8.FCCOB4_u8      = (uint8_t) FMARGIN_USER;

  flash_cmd_obj.FTFA_regs_8.FCCOB0_u8      = (uint8_t) FCMD_PGM_CHECK;

  status_u32  = flash_cmd_in_ram();

  if( FCMD_OK != status_u32 )

    {

      status_u32 |= FCMD_PGM_U32_MARGIN_FAILURE; /* Indicate this is a verification error not a flash write error */

    }

  return( status_u32 );

}

/********************************************************

*

* Proram a block of uint32_t's:

*

********************************************************/

uint32_t flash_pgm_block_u32( uint32_t const *dst_adr_u32, uint32_t const *src_adr_u32, uint32_t const size_u32_in )

{

  uint32_t const *d_adr_u32     = dst_adr_u32;

  uint32_t size_u32       = size_u32_in;

  uint32_t return_val_u32 = FCMD_OK;

  while( 0UL != size_u32-- )

  {

    return_val_u32 = flash_one_u32( d_adr_u32, *src_adr_u32++ );

    if( FCMD_OK != return_val_u32 )

      {

        break; /* while() */

      }

    d_adr_u32 += 4UL;

  }

  return( return_val_u32 );

}

/*lint -restore */

/** @(#)flash_kinetis_cmd.c <09-Oct-2013 14:24:33 Bob Paddock>

*  \date Last Time-stamp:  <19-Oct-2015 08:15:00 bob p>

*

*  \file flash_kinetis_cmd.c

*  \brief  Command executing in RAM to modify Flash.

*

*/

/*lint -save */

#include "compiler.h"

#include "flash_kinetis.h"

/* Suppress warning of casting &(FTFA_BASE_PTR->FCCOB3) to uint8_t pointer: */

#pragma GCC diagnostic push

#pragma GCC diagnostic ignored "-Wcast-qual" /* There is a bug in GCC versions less than 4.8.5 giving this bogus error */

/*

* 'flash_cmd_in_ram()' is declared long_call and is put in its own RAM

* section via the custom linker script.  It is copied there via

* custom code in vectors.c at power up.

*/

uint32_t flash_cmd_in_ram( void )

{

  uint8_t *flash_cmd_obj_reg_u8_p = (uint8_t *) &(FTFA_BASE_PTR->FCCOB3);

  /* Wait while CCIF bit shows busy: */

  while( 0U == (FTFA_FSTAT & FTFA_FSTAT_CCIF_MASK) )

    {

      nop();

    }

  /* Clear RDCOLERR, ACCERR and FPVIOL flag in flash status register: */

  FTFA_FSTAT = (FTFA_FSTAT_RDCOLERR_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_FPVIOL_MASK);

  /* Copy object buffer to real FCCOB registers: */

  for( uint_fast16_t idx = 0U; idx < sizeof( flash_cmd_obj ); ++idx )

    {

      *flash_cmd_obj_reg_u8_p++ = flash_cmd_obj.FCCOB_ary_u8[ idx ];

    }

  irq_disable(); /* We are about to pull the rug out from under any running IRQs, so disable any IRQs to prevent system crash */

  /* Start the command: */

  FTFA_FSTAT |= FTFA_FSTAT_CCIF_MASK;

  /* Wait while flash command completes: */

  while( 0U == (FTFA_FSTAT & FTFA_FSTAT_CCIF_MASK) )

    {

      nop();

    }

  irq_enable(); /* Flash command has completed, safe to enable IRQs now */

  return( (FTFA_FSTAT & (FTFA_FSTAT_RDCOLERR_MASK | FTFA_FSTAT_ACCERR_MASK | FTFA_FSTAT_FPVIOL_MASK | FTFA_FSTAT_MGSTAT0_MASK) ) );

}

#pragma GCC diagnostic pop

/*lint -restore */

986 Views
mjbcswitzerland
Specialist V

Hi

You can get full information in chapter 46 of the KL43's users manual.

Basically you need to program values as long word - you can only program a long word once without erasing the 2k sector that it is in. Maximum 10k cycles with 5 years data retention (see the data sheet 3.4.1.4).

There are many sources for such code but I have attached the uTasker Flash interface as reference, that realises a fail-safe parameter system in the Flash and supports K, KL and KE Flash types.

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html

KL43: http://www.utasker.com/kinetis/FRDM-KL43Z.html / http://www.utasker.com/kinetis/TWR-KL43Z48M.html

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos