Hello friends,
we are working with MK10FX512VLQ12 on our custom developed board. We completed almost the firmware for the intended application, and had no problem until now.
The problem started while trying to implement the bootloader functionality. The bootloader FW writes some parameters in flash memory, that are used by both applications (bootloader and user). After the write is done, we check if the parameters are really in flash on the desired locations, but while accessing the flash location, the MCU goes to hard fault.
I will try to clarify all the steps that we make before the hard fault.
#define BL_RUN_FLAG_ADDRESS 0x9000 bootloader_run_flag = *((uint32_t*) BL_RUN_FLAG_ADDRESS);
The read function returns the correct value, and is set to enter the bootloader application if no user application is present.
if(BL_CheckMsgIDinFlash()){ BL_WriteMsgIDtoFlash(); Cpu_SystemReset(); } bool BL_CheckMsgIDinFlash(void) { uint32_t rtrn = 0; uint32_t i = 0; for (i = 0; i < MSGID_NR; i++) { if (Flash_MSGID[i] != *((uint32_t*) (BL_RUN_FLAG_ADDRESS + ((i + 1) * 4)))) { rtrn++; } } return (bool) rtrn; } bool BL_WriteMsgIDtoFlash(void) { uint32_t i = 0; uint32_t err = 0; uint32_t tmp32 = 0; uint32_t addr = 0; for (i = 0; i < MSGID_NR; i++) { tmp32 = Flash_MSGID[i]; addr = BL_RUN_FLAG_ADDRESS + (i + 1) * 4; err = IFsh1_SetBlockFlash((IFsh1_TDataAddress) &tmp32, addr, 4); // write data to specified location in flash } return err; }
When I run this part of code in debugger, the memory locations are not written correctly, at least the debugger shows it incorrectly. While single stepping trough BL_WriteMsgIDtoFlash() i have this in my memory locations:
Step | 0x9000 | 0x9004 | 0x9008 | 0x900C | 0x9010 | 0x9014 |
---|---|---|---|---|---|---|
1 | 0x00000431 | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | |
2 | 0xFFFFFFFF | 0x00000431 | 0x00000432 | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF |
3 | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF |
4 | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0x00000434 | 0xFFFFFFFF |
5 | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0x00000434 | 0x00000435 |
On the third step the first two locations are erased, and at the end the two last locations are correct.
bootloader_run_flag = *((uint32_t*) BL_RUN_FLAG_ADDRESS);
I read the flowing values in the system registers:
Register | Value | Location |
stacked_r0 | 0xffffffff | 0x1fff111c |
stacked_r1 | 0x00000000 | 0x1fff1120 |
stacked_r2 | 0x00000000 | 0x1fff1124 |
stacked_r3 | 0x00009000 | 0x1fff1128 |
stacked_r12 | 0x00000000 | 0x1fff112c |
stacked_lr | 0x0000371d | 0x1fff1130 |
stacked_pc | 0x000036fe | 0x1fff1134 |
stacked_psr | 0x21000000 | 0x1fff1138 |
_CFSR | 0x00008200 | 0x1fff113c |
_HFSR | 0x40000000 | 0x1fff1140 |
_DFSR | 0x00000009 | 0x1fff1144 |
_AFSR | 0x00000000 | 0x1fff1148 |
_BFAR | 0x00009000 | 0x1fff1150 |
_MMAR | 0x00009000 | 0x1fff114c |
The PC shows the last location where it broke, and this is the part of the code:
222 bootloader_run_flag = *((uint32_t*) BL_RUN_FLAG_ADDRESS); 000036fa: mov r3,#0x9000 000036fe: ldr r3,[r3,#0] 00003700: str r3,[r7,#4]
The same problem happens when I try immediately read the memory locations after the write command, without resetting the CPU.
I attached also the InitFLASH source files for reference.
I'm very confused now, because we implemented this bootloader firmware on two other devices (MK10DX128 and MK40DN512) and it works without any problems.
Does anyone have a suggestion what could be the problem here?
Best regards,
Dario
Original Attachment has been moved to: Generated_Code.rar
Solved! Go to Solution.
Dario
You are not respecting the phrase programming requirements fo the Flash in the K10FX512.
You are only allowed to write 8 byte blocks at at time (phrase) and any attempt to write to one of these phrases (8 byte blocks) that is not erased will corrupt the Flash and cause it to return a hard fault afterwards (it then requires an erase to recover).
You need to change your code to leave a long word space after the 5th long word that you have written:
eg:
0x10000004, 0x10000008, 0x1000000C, 0x10000010 and 0x10000014 + 0xffffffff
and then add futher data after that and it will work (or some other equivalent method).
The problem is that the Flash is being written as follows (assuming X is divisible by 4):
Phase Address X = 0x10000004, 0x10000008
Phase X + 1 = 0x1000000C, 0x10000010
Phase X + 2 = 0x10000014 + 0xffffffff
If you tried to write at long word offset 5 it was doing
Phase X + 2 = 0x10000014 + "changed value"
It is not allowed to write to a phrase twice (without a sector erase inbetween) and so your problem arisies.
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
K60: http://www.utasker.com/kinetis/TWR-K60N512.html / http://www.utasker.com/kinetis/TWR-K60D100M.html / http://www.utasker.com/kinetis/TWR-K60F120M.html
For the complete "out-of-the-box" Kinetis experience and faster time to market
:smileyinfo: Out-of-the-box support for 46 Kinetis boards and 10 IDEs (460 combinations from a single code source with no porting required)
Today we did some more debugging, and came to a weird behavior of the MCU while writing data to flash.
Attached you can find a CodeWarrior (10.6) project with an example application of the behavior.
To clarify the behavior, we try to write 5 data bytes to flash memory on locations 0x10000004, 0x10000008, 0x1000000C, 0x10000010 and 0x10000014. The data bytes are:
uint32_t Flash_MSGID[5] = { 0x430U, 0x431U, 0x431U, 0x431U, 0x431U};
We use the FLASH_LDD component from ProcessorExpert to write and read data. If we write the above mentioned array Flash_MSGID, there is no problem, and the data is written and read correctly. But if we change the value of second element in the array to 0x430U, then we get corrupted data on that locations, and the read command generates a hard fault condition.
uint32_t Flash_MSGID[5] = { 0x430U, 0x430U, 0x431U, 0x431U, 0x431U};
Hope someone can give us some help with this problem.
Dario
You are not respecting the phrase programming requirements fo the Flash in the K10FX512.
You are only allowed to write 8 byte blocks at at time (phrase) and any attempt to write to one of these phrases (8 byte blocks) that is not erased will corrupt the Flash and cause it to return a hard fault afterwards (it then requires an erase to recover).
You need to change your code to leave a long word space after the 5th long word that you have written:
eg:
0x10000004, 0x10000008, 0x1000000C, 0x10000010 and 0x10000014 + 0xffffffff
and then add futher data after that and it will work (or some other equivalent method).
The problem is that the Flash is being written as follows (assuming X is divisible by 4):
Phase Address X = 0x10000004, 0x10000008
Phase X + 1 = 0x1000000C, 0x10000010
Phase X + 2 = 0x10000014 + 0xffffffff
If you tried to write at long word offset 5 it was doing
Phase X + 2 = 0x10000014 + "changed value"
It is not allowed to write to a phrase twice (without a sector erase inbetween) and so your problem arisies.
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
K60: http://www.utasker.com/kinetis/TWR-K60N512.html / http://www.utasker.com/kinetis/TWR-K60D100M.html / http://www.utasker.com/kinetis/TWR-K60F120M.html
For the complete "out-of-the-box" Kinetis experience and faster time to market
:smileyinfo: Out-of-the-box support for 46 Kinetis boards and 10 IDEs (460 combinations from a single code source with no porting required)
Mark,
thank You for the answer, it helped us a lot.
You are right, the problem was that we didn't respect the phrase requirements for this MCU.
We changed everything so that we write always 8 byte blocks at once, and now works everything OK.
Best regards,
Dario