In July, 2010, I had the freescale support about how to save data in SE8 Flash Memory. OK.
Actually, I have an application (temperature controller), which has 8 x 4 parameters (a const signed int vector in C language) to be saved in Flash Memory.
When I program the hardware and enter the "save parameters mode" the first time, it works okay (I'm able to save the data in the memory).
However, when I turn it off and turn it on again (the hardware), I'm not able anymore to save the data.
I tried to debug the application, but it has been very difficult to find the problem.
#include "FLASH.h"
/*
*
*/
#pragma CODE_SEG DEFAULT
void flash_init(void)
{
if(!(FCDIV & 0x80))
{
if(FSTAT & 0x30) //Check to see if FACCERR is set
{
FSTAT |= 0x30; //write a 1 to FACCERR to clear
}
FCDIV = FLASH_CLOCK;
}
}
/*
*
*/
#pragma CODE_SEG FLASH_ROUTINES
unsigned char flash_cmd(unsigned int flashAddress, unsigned int flashDataCounter, unsigned char* pFlashDataPtr, unsigned char flashCommand)
{
/* Clear Flags if set*/
FSTAT = 0x30;
do
{
/* Wait for the Last Busrt Command to complete */
while(!(FSTAT&0x80));
/* Write Data into Flash*/
(*((volatile unsigned char *)(flashAddress++))) = *pFlashDataPtr;
pFlashDataPtr++;
/* Write Command */
FCMD = flashCommand;
_asm NOP;
_asm NOP;
_asm NOP;
_asm NOP;
/* Put FCBEF at 1 */
FSTAT = 0x80;
/* Check if Flash Access Error or Protection Violation Error are Set */
if(FSTAT & 0x30)
{
/* If so, finish the function returning 1 to indicate error */
return (1);
}
}while (--flashDataCounter);
/* wait for the last command to complete */
while((FSTAT & 0x40)==0);
/* Return zero to indicate that the function executed Ok */
return (0);
}
#pragma CODE_SEG DEFAULT
/******************************************************************************************************/
/******************************************************************************************************/
/******************************************************************************************************/
/* This is the implementation to copy a function to RAM; Read Technical Note 228 for more information */
extern char __SEG_START_FLASH_ROUTINES[];
extern char __SEG_SIZE_FLASH_ROUTINES[];
/*
* Start_Copy_In_RAM refers to the begining of the segment
* ToCopyToRAM. This segment contains the functions after
* they have been copied to RAM.
*/
#define START_COPY_IN_RAM __SEG_START_FLASH_ROUTINES
#define SIZE_COPY_IN_RAM __SEG_SIZE_FLASH_ROUTINES
/*
* Start_In_ROM refers to the begining of the segment
* ToCopyToRAM. This segment contains the functions in ROM.
*/
void flash_copyInRAM(void)
{
char *srcPtr;
char *dstPtr;
int count;
srcPtr = (char *)START_COPY_IN_RAM;
dstPtr = (char *)&flash_cmd;
for (count = 0; count < (int) SIZE_COPY_IN_RAM; count++, dstPtr++, srcPtr++)
{
*dstPtr = *srcPtr;
}
}
/*
*
*/
void memoryManager_enableMemory(unsigned char status)
{
if(status == MEMORY_ENABLED)
{
RTCSC_RTIE = 0; //Disable Timer Interrupt
DisableInterrupts;
SOPT1_COPT = 0;
}
else if(status == MEMORY_DISABLED)
{
SOPT1_COPT = 1;
__RESET_WATCHDOG();
RTCSC_RTIE = 1; //Enable Timer Interrupt
EnableInterrupts;
}
}
Please, could anyone help me?
Thank you in advance.
It seems you forgot to erase the flash page.
Before writing to flash it is mandatory that you erase the whole page you're going to write data.
I hope it helps,
Celso
Hi Celso,
I'm erasing the flash page. Please, see below some lines of my routine. I did some tests today morning, and I got the problem in two scenarios:
Scenario 1:
- Program the hardware
- Save/change two or three parameters (OK)
- Turn the hardware off and on
- Save/change one parameter (Not OK). All the other features of my software works fine, but I'm not able to save the parameters anymore
Scenario 2:
- Program the hardware
- Save/change two or three parameters (OK)
- Continue saving more and more parameters (Not OK). I had problems to save the 8th or 9th parameters. The microcontroller was reseted once. After, the memory and the software were completely erased.
Conclusion:
If I don't use the memory, all is okay. However, if I use the memory (erase and program) some times, the software is lost or completely erased.
Thank you, in advance.
Cremonezi
I forgot to post some lines of my routine. Sorry.
RTCSC_RTIE = 0; //Disable Timer Interrupt
DisableInterrupts; //Disable global interrupts
SOPT1_COPT = 0; //Disable WDT
if(flash_erase(MEMORY_PAGE) == 0) //If there is no problem during erase process, enter program mode.
{
for(i = 1; i <= PARAMETERS_NUMBER; i++)
memoryManager_saveParamValue(i, menu_parameterNumber, menu_data[PARAM_VALUE]);
}
SOPT1_COPT = 1; //Enable WDT
__RESET_WATCHDOG(); //Reset WDT
RTCSC_RTIE = 1; //Enable Timer Interrupt
EnableInterrupts; //Enable global interrupts
//*********************************************************
void memoryManager_saveParamValue(unsigned char index, unsigned char paramIndex, signed int value)
{
unsigned char address;
unsigned char addressAdjust;
addressAdjust = ((index-1)*4);
address = ((index-1)*8) + PARAM_VALUE_INDEX;
if(index == paramIndex)
{
memoryManager_writeData(address,value);
memoryManager_bufferData[index-1] = value;
}
else
memoryManager_writeData(address,memoryManager_bufferData[index-1]);
address += 2;
memoryManager_writeData(address,memoryManager_parameters[addressAdjust+1]);
address += 2;
memoryManager_writeData(address,memoryManager_parameters[addressAdjust+2]);
address += 2;
memoryManager_writeData(address,memoryManager_parameters[addressAdjust+3]);
}
void memoryManager_writeData(unsigned char address, signed int singleInt16)
{
unsigned char index;
unsigned char memData;
index = address;
memData = getByte16Bits(singleInt16,1);
memoryManager_writeByte(index, memData);
index++;
memData = getByte16Bits(singleInt16,2);
memoryManager_writeByte(index, memData);
}
void memoryManager_writeByte(unsigned char address, unsigned char singleByte)
{
unsigned char dataToWrite;
dataToWrite = singleByte;
memoryAddress = MEMORY_INIT_ADDRESS + (unsigned int)address;
if(flash_program(memoryAddress, dataToWrite))
{
memoryErrorCode = MEMORY_WRITE_ERROR;
}
}
Should I use the burst command instead of using a normal program command, byte to byte?
COPT bits are write once. You can't turn COP off then on. First write to SOPT1 register (setting/clearing any SOPT1 bit) will lock COPT setting.