I have written a flash driver, which provides standard services, like read, write, erase sector, secure and unsecure MCU flash to the main application for K21F120.
The driver was implemented according to the "Standard Software Driver for C90TFS" user's manual,
All the flash commands and operating code is similar to the C90TFS driver available in Freescale project sample "demo_secure" into C90TFS Demos. All these routines of the driver must run from RAM. But my project doesn't run Flash operation from the RAM. I can do all operation with Flash in Debug in RAM, but when FW runs from Flash (in release mode) occurred the problem with "Secure" and "Unsecure" the flash: After the operation "Erase the first sector" that contain Vector table, my MCU is stops operation and FW is crash.
I have found some differences between my project and the Freescale project:
1. I am using fsl drivers and board initialization like in the attached project, and the Freescale example is a bareboard.
2. Freescale project contains a file, named "startup.c" where copied vectors from Flash to RAM and my project doesn't have a file like this one.
3. Linker files in both projects are different.
I tried to update my linker file and add the "startup.c" file to my project, but after adding this file the board does reset or received an error message that FW can't be loaded.
I understand that need to add operation for copy vectors from Flash to RAM, but can't fix this.
How can I add an option for run Flash operation from RAM?
Attached my CDC project, "startup.c" and linker file from the Freescale project example.
Thanks a lot.
Evgeni
Solved! Go to Solution.
Hi Mark.
Thank you very much for your interesting example. I have tested it, but the effect was the same as in my case. All interrupts during flash operations in my code are disabled.
I found a reason why the code was not copied in release mode and was causing the system to crash. To solve the problem, I had to copy the interrupt table to RAM, point the VTOR to the new copy of the vector table, and correct the .icf file to keep the interrupt table copy location in RAM intact. So this solved my Secure / unsecure flash operation problem.
Thanks for the help.
Hi
You don't need to copy interrupt vectors to SRAM but you should disable interrupts during flash operations. If you do allow interrupts during flash operations you would need to copy also all possible code used by interrupts to SRAM too.
The following is from the uTasker flash driver (which is compatible for all flash types and Kinetis processors) showing how the flash execution operation can be put to SRAM during run time and is thus compiler, linker script and environment independent - and so fully portable:
Initialise flash execution code in RAM:
static void (*fnRAM_code)(volatile unsigned char *) = 0;
#define PROG_WORD_SIZE 30 // adequate space for the small program
int i = 0;
unsigned char *ptrThumb2 = (unsigned char *)fnFlashRoutine;
static unsigned short usProgSpace[PROG_WORD_SIZE] = {0}; // make space for the routine in static memory (this will have an even boundary)
ptrThumb2 = (unsigned char *)(((unsigned long)ptrThumb2) & ~0x1); // thumb 2 address
while (i < PROG_WORD_SIZE) { // copy program to SRAM
usProgSpace[i++] = *(unsigned short *)ptrThumb2;
ptrThumb2 += sizeof (unsigned short);
}
ptrThumb2 = (unsigned char *)usProgSpace;
ptrThumb2++; // create a thumb 2 call
fnRAM_code = (void(*)(volatile unsigned char *))(ptrThumb2);
where the flash routine is:
#define FTFL_BLOCK 0x40020000 // Flash Memory Module
static void fnFlashRoutine(volatile unsigned char *ptrFTFL_BLOCK)
{
*ptrFTFL_BLOCK = FTFL_STAT_CCIF; // launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
while ((*ptrFTFL_BLOCK & FTFL_STAT_CCIF) == 0) {} // wait for the command to terminate
}
However in order to ensure that it is compiler independent (and not affected by optimisation, potential code in-lining etc.) it is best to use its assembler form:
static unsigned short fnFlashRoutine[] = { // to avoid potential compiler in-lining of the routine (removing position independency) the machine code is used directly
0x2180, // MOVS r1,#0x80 load the value 0x80 (command complete interrupt flag) to register r1
0x7001, // STRB r1,[r0,#0x00] write r1 (0x80) to the passed pointer location (r0)
0x7801, // LDRB r1,[r0,#0x00] read back from the same location to r1
0x0609, // LSLS r1,r1,#24 shift the register content by 24 bits to the left so that the command complete interrupt flag is at bit 31
0xd5fc, // BPL -4 if the command complete interrupt flag bit is '0' (register content is not negative value) branch back to read its value again
0x4770 // BX lr return from sub-routine
};
Therefore if you cut and past the above it will operate in any environment.
To use:
uDisable_Interrupt(); // protect this region from interrupts
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
uEnable_Interrupt(); // safe to accept interrupts again
Regards
Mark
uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training or product development requirements
Hi Mark.
Thank you very much for your interesting example. I have tested it, but the effect was the same as in my case. All interrupts during flash operations in my code are disabled.
I found a reason why the code was not copied in release mode and was causing the system to crash. To solve the problem, I had to copy the interrupt table to RAM, point the VTOR to the new copy of the vector table, and correct the .icf file to keep the interrupt table copy location in RAM intact. So this solved my Secure / unsecure flash operation problem.
Thanks for the help.