All,
I am using the K64 FRDM board for some proof concept regarding the flex nvm setup for flash EEPROM and DFLASH. I couldn't find any demos or application notes on how to leverage this library code, but essentially started playing with it to get a working solution. I was finally able to get it to work, however have noticed some intermittent behavior for settings this up using the partition command. If i let the code run on its own, the flash EEPROM does not get properly setup, and stays at the default of no E-flash and only D-flash is used. However if I manually step through the FLASH_ProgramPartition() function, specifically into the flash_command_sequence(), and the callFlashRunCommand() function it E-flash and D-flash or properly partitioned and works as expected. Not sure what is going on here. I have intentionally turned off all interrupts during this just to make sure nothing will pull the rug from underneath the fsl_flash.c functions. Any help or even and app note that specifically details how to actually use this fsl_flash.c library with E-FLASH and D-FLASH.
It should be important to note, that I am using mbed cli to create the project and export to IAR.
Below is the code that shows what I've done:
#include "mbed.h"
#include "intrinsics.h"
#include "fsl_flash.h"
#include <stdio.h>
#include <errno.h>
#define MAX_STRING_SIZE 20
#define TEST_VALUE 0xB00B3 //721075
#define CALC_ADDR_END( start, var ) (start + sizeof( var ))
#define EEPROM_START FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS
typedef struct
{
uint32_t test_var1;
uint16_t test_var2;
bool test_var3;
uint8_t test_var4;
uint16_t test_var5;
}
TestStruct1_t;
typedef struct
{
uint8_t test_var1;
char test_string1[MAX_STRING_SIZE];
uint8_t test_var3;
}
TestStruct2_t; // Create global variable that is tied to flex_nvm memory space
__no_init
uint32_t eeprom1_uint32 @ EEPROM_START;
#define E_UINT32_2 CALC_ADDR_END(EEPROM_START, eeprom1_uint32)
__no_init uint32_t eeprom2_uint32 @ E_UINT32_2;
#define E_TEST_STRUCT_1 CALC_ADDR_END(E_UINT32_2, eeprom2_uint32)
__no_init TestStruct1_t e_test_struct1 @ E_TEST_STRUCT_1;
#define E_TEST_STRUCT_2 CALC_ADDR_END(E_TEST_STRUCT_1, e_test_struct1)
__no_init TestStruct2_t e_test_struct2 @ E_TEST_STRUCT_2;
#pragma location="__flash"
const uint32_t test_var = 0;
flash_config_t flash_config;
template <class T, class U>
static status_t
Copy_Mem_To_EEPROM(T *start, U *src, uint32_t num_bytes)
{
return FLASH_EepromWrite(&flash_config, (uint32_t)start, (uint8_t*)src, num_bytes);
}
template <class T, class U>
static status_t Copy_Value_To_EEPROM(uint32_t *start, T src, uint32_t num_bytes)
{
return FLASH_EepromWrite(&flash_config, (uint32_t)start, (uint8_t*)&src, num_bytes);
}
void flex_mem_demo(void)
{
__disable_interrupt();
TestStruct1_t p1;
TestStruct2_t p2;
// manually break and set the eeprom1_uint32 = 0 using the debugger
// this allows the one time program partition to be run. Every other restart
// instance from this point forward will only initialize and increment the
// eeprom1_uint32 , but not repartition the Flex NVM. Enjoy
if(eeprom1_uint32 == 0xFFFFFFFF)
{
FLASH_Init(&flash_config);
FLASH_ProgramPartition(&flash_config, kFLASH_PartitionFlexramLoadOptionLoadedWithValidEepromData, 0x32, 0x0B);
FLASH_Init(&flash_config);
Copy_Value_To_EEPROM(&eeprom1_uint32, TEST_VALUE, sizeof(eeprom1_uint32));
p1.test_var1 = 1; //modify local parameter //now store in eeprom Copy_Mem_To_EEPROM(&e_test_struct1.test_var1, &p1.test_var1, sizeof(e_test_struct1.test_var1));
}
else
{
FLASH_Init(&flash_config); p1.test_var1 = e_test_struct1.test_var1 + 1; Copy_Mem_To_EEPROM(&e_test_struct1.test_var1, &p1.test_var1, sizeof(e_test_struct1.test_var1));
Copy_Value_To_EEPROM(&eeprom1_uint32, (eeprom1_uint32 + 1), sizeof(eeprom1_uint32));
}
__enable_interrupt();
}
int main(void)
{
device.baud(115200);
flex_mem_demo();
dflash_mem_demo();
while(1);
}
Hello Ed
The K64 on the FRDM-K64F does not have FlexNVM. It uses the K64FN1M0. You need a K64FX512 - have you changed the chip on the board?
On the other hand the K64FN1M0 has program flash swap, which the K65FX512 doesn't.
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
Kinetis K64:
- http://www.utasker.com/kinetis/FRDM-K64F.html
- http://www.utasker.com/kinetis/TWR-K64F120M.html
- http://www.utasker.com/kinetis/TEENSY_3.5.html
- http://www.utasker.com/kinetis/Hexiwear-K64F.html
Professional Kinetis support, one-on-one training and complete fast-track project solutions: http://www.utasker.com/support.html
I actually removed the K64FN processor and swapped it with a 100pin compatible K64FX processor. My bad I should have been more precise. That's how I have been able to get it to work. I think I have found the issue though, and it has to do with my compilers __disable_interrupt & __enable_interrupt are not correctly setting the PRIMASK to 1 and 0 respectively. I'll update here in a second just so other users are aware of any potential issues with the IAR compiler and these interrupt directives.
IAR has an issue with using __disable_interrupt; __disable_interrupt(); & __enable_interrupt __enable_interrupt(); If you don't use the __xxxx_interrupt(); with parenthesis the code compiles without warnings or errors, but the assembly instruction (cpsid or cpsie) does not get compiled in. I've updated the above code to use the __xxxx_interrupt(); It works now so feel free to use it as a demo for E-flash.