KL17 core lockup during flash write

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

KL17 core lockup during flash write

1,797 Views
klausb
Contributor II

Hello,

in my setup I use a KL17Z64 that receives bytes via UART (interrupt driven) and depending on the value sometimes writes a few bytes into a ringbuffer in the FLASH.

I've read so far that during a flash write operation other flash reads (e.g. executing an interrupt from flash) are not allowed, since the KL1764 only has one flash block.

In order to avoid this I first tried disabling interrupts before the CCIF bit in FTFA_FSTAT is cleared (by software) and enabling them again after the bit is 1 again (set by hardware after flash write completion).

But this is rather inconvenient since sometimes UART bytes get lost because the interrupts are disabled too long (especially when I erase a flash section so I can reuse it)

Then I further read that an alternative would be to store the UART ISR in SRAM, so it can be executed while the flash write operation is in progress.

I did this by giving the ISR the attribute __attribute__ ((section(".custom_ramfunctions"))) and adding *(.custom_ramfunctions) after *(.data*) in the .data section of the linker file. Additionaly I defined __ram_vector_table__ so the vector table is also in RAM. This (without writing the flash) seems to work since the ISR is still executed and when I use my debugger I can see the PC somewhere in the SRAM. Additionally I moved the clearing of the CCIF bit and the loop until it's set again into the SRAM as well (since I think this is the only clean way to actually write the flash when you only have one flash block?).

However, if I combine the ISR and the flash writes I sometimes get a reset due to a core LOCKUP event.

I don't understand why this happens, since I only read RAM while the flash write operation is in progress. Did I forget some important step?

Is there any way to find out what exactly cause the LOCKUP event? Or does anyone have a small working project with both flash writes and interrupts from RAM?

For now it might be sufficient to drop some bytes, but I hope that I can actually do this in a cleaner way.

Thanks,

Klaus

Labels (1)
0 Kudos
11 Replies

1,302 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi

Please refer AN4695 to avoid read while write errors during Flash programming.

AN4695 software.

As Mark mentioned, it need to make sure all software code running in RAM during Flash operation phase.


Wish it helps.

Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,302 Views
klausb
Contributor II

Thanks for the link, but this appnote was my starting point for the code. That's why I moved the interactions with the CCIF flag into SRAM as well.

But the reading that was more helpful in actually moving code to SRAM was Relocating Code and Data Using the KDS GCC Linker File for Kinetis.

As mentioned in my reply to Mark, I checked and every instruction seems to be in SRAM.

Unfortunately those 2 references were all I could find, and they don't actually use interrupts.

0 Kudos

1,302 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi

For the KL17 with 32KB SRAM, customer could try to place the whole demo code at SRAM as a test. Then customer could check if there still with core lockup issue or not.


Thank you for the attention.

Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,302 Views
klausb
Contributor II

Thank you.

I tried this just now.

Turns out, when everything is in SRAM, no lockup happens (at least not within seconds after startup like it was before). The only code that's still in flash is everything that happens before main() is called.

But as soon as a function like main() or only a small function like this:

void SWI_vCloseSwitch(void) {
   GPIOD_PSOR = PORT_PD5;
}

(which is executed periodically between the flash writes) is moved back into the flash, the lockup happens.

Even though this function is only called before my flash write function, and never in interrupts.

By the way, currently I compile with -O0, so I doubt this is some compiler function rearangement problem.

Could it be that I made a mistake in interacting with the CCIF flag?

I now have this function in RAM:

__attribute__ ((section(".custom_ramfunctions")))
void vStartFlashCommand(void) {
   //Start command
   FTFA_FSTAT = FTFA_FSTAT_CCIF;
   //Wait for completion
   while (!(FTFA_FSTAT & FTFA_FSTAT_CCIF));
}

From what I understand, the first line initiates the flash write (or whatever I set in the control registers beforehand). When this happens the CCIF flag should be 0 until the operation is completed.

Therefore the while loop should prevent the execution of any non-interrupt code while the flash operation is in progress.

Am I mistaken here?

However, if I wrap those two lines with

   __asm volatile ("cpsid i" : : : "memory");
   __asm volatile ("cpsie i" : : : "memory");

then again no lockup happens, but then obviously some UART bytes get lost due to disabled interrupts.

0 Kudos

1,302 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi

I checked there with TFS Flash driver software for Kinetis MCU, includes KL series product. There with demo to run the Flash operation with code located at Flash target. The TFS Flash driver software supports IAR and CodeWarrior for MCU IDE software.

I would recommend customer to download and refer those demo.

Customer could refer related demo software's link configuration file also.


Wish it helps.

Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,302 Views
mjbcswitzerland
Specialist V

Hi

Are you sure that there are no sub-routines being called from the RAM code that are Flash-resident?
Beware that compiler library code 'may' include subroutines that are not expected.
Eg.
void routine(void)
{
    int array[10] = {0};
    return;
}
The GCC compiler sometimes uses memset() to initialise the local array to zero, which is an example where it would not be fully RAM resident. The same may be true for functions that use things like modulo divide, integer divides etc. which may call library code - eg. x %= 2;
It would be a good idea to single step the entire RAM code (all possible routes) to ensure that there are no possible jumps to Flash.

Can you add pauses to the UART protocol - eg using RTS/CTS or XOFF/XON?
The uTasker SREC/iHEX serial loader solves this issue by using XON/XOFF as described on page 15 of
http://www.utasker.com/docs/uTasker/uTaskerSerialLoader.PDF

Regards

Mark

1,302 Views
klausb
Contributor II

Hi, thanks for the input.

I do use a callback function in the UART interrupt, but I already moved this function into SRAM as well.

While stepping through the interrupt (in instruction stepping mode) every asm line executed was in the SRAM region (somewhere above 0x1ffff000). So it seems like the processor only reads SRAM and some registers which I read directly (e.g uint8_t ucData = (LPUART1_DATA&0xFF); with #define LPUART1_DATA            (*(volatile uint32_t *)0x4005500CU) ). It doesn't make sense that the lockup occurs.

And I don't think I can reproduce the LOCKUP event while stepping through the code since the flash write operation will be long done after I step over one instruction.

Unfortunately I only have the RX/TX lines available for UART, so I can't use RTS/CTS signals.

Do you have any further ideas what could cause this?

0 Kudos

1,302 Views
mjbcswitzerland
Specialist V

Klaus

Unfortunately I haven't any further ideas as to why the SRAM based code is not reliable.

I understand that RTS/CTS is not possible but XON/XOFF doesn't need additional wires and that is why I chose it (for my case). Other loading protocols use handshakes so that the processor can inform "when it is ready" to receive 'more' data - maybe one of these could still be possible to avoid needing to receive at the same time as erasing and this simplifying the flashing routine?

Regards

Mark

0 Kudos

1,302 Views
klausb
Contributor II

Hi

as in my latest reply to Ma Hui, turns out the problem is not in the SRAM based ISR code, but even if a very small non-interrupt function is the only one that's in Flash, this still happens.

I might look into the XON/XOFF handshake, but since the intended communication may contain arbitrary data (sensor values) I can't really rely on reacting to XON/XOFF bytes.

0 Kudos

1,302 Views
mjbcswitzerland
Specialist V

Klaus

Protocols that use XON/XOFF either use byte stuffing (eg. PPP) to avoid a control character within a binary stream, or else use ASCII coding so that all values are transferred as 7 bit characters and also avoid control ones.

Another option is to use DMA for UART reception so that no UART interrupts are involved, which would possibly work around the issues by allowing you to block interrupts (KL supports free running circular buffer reception as long as aligned appropriately and so can bridge quite long periods depending on the data rate and buffer size/RAM you have to throw at it).

Unfortunately I don't understand what is going on with the small (unrelated) piece of code in Flash but I wouldn't exclude general compiler/linker control difficulties whereas this piece of code also has an impact on the way that it relocates code to SRAM. Personally I prefer to not use more SRAM code than absolutely necessary since it opens the back door to all sorts of nasty compiler/IDE specific things that need to be carefully studied and understood; days or weeks of frustrating work (I don't know who pays your time, but employers/customers tend to prefer to see water-tight results for their money) which then breaks when the compiler version is changed or a different IDE must be used (back to square one...).

If you can easily upgrade to DMA UART reception it may be a solution with the present protocol, otherwise I would lobby for a simple protocol tweak to put the issue to bed and get on to something productive.

Regards

Mark

0 Kudos

1,302 Views
klausb
Contributor II

DMA UART reception sounds interesting, I might look into that as well.

However, it might only be a partial solution, since the final project might as well contain more interrupts beside UART.

The unrelated flash code was just an example, doesn't actually matter what function i move back to Flash, as long as it is executed in my loop. For example, if i keep the main() function in flash this happens as well. I just wanted to point out that a completely unrelated function (aside from the fact that it is executed in between flash writes) in flash already causes a lockup

0 Kudos