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 */