Hello,

Thank you for the report and investigation.

On Sat, Jan 26, 2019 at 09:43:34PM -0000, Bill Paul wrote:
> The first has to do with the way the ST-LINK V2 performs write accesses. It
> performs an automatic verify on write, which means that after a write
> transaction is issued, it then peforms a read tranaction to the same location
> and compares the result with what it tried to write. If they don't match, then
> the dongle returns an error status.

Are you running a version with http://openocd.zylin.com/#/c/4368/
merged?

-- 
Be free, use free (http://www.gnu.org/philosophy/free-sw.html) software!
mailto:fercer...@gmail.com


---

** [tickets:#222] Flashing NXP Kinetis with ST-LINK V2 dongle fails, leaves 
flash locked**

**Status:** new
**Milestone:** 0.9.0
**Created:** Sat Jan 26, 2019 09:43 PM UTC by Bill Paul
**Last Updated:** Sat Jan 26, 2019 09:43 PM UTC
**Owner:** nobody
**Attachments:**

- 
[kinetis.c.diff](https://sourceforge.net/p/openocd/tickets/222/attachment/kinetis.c.diff)
 (3.6 kB; text/x-patch)


A while ago, a friend and I created a project based on the NXP Kinetis KW01 
chip, which has a Cortex-M0+ core , 16KB RAM and 256KB flash. We included a 
10-pin header for SWD. We used OpenOCD with the Olimex USB-ARM-OCD-H debugger 
and everything worked perfectly.

Later, I acquired a cheap ST-LINK V2 clone dongle and decided to see how it 
worked with our board. I was able to debug just fine, but when I try and 
re-flash the firmware, the flash process terminated with an error almost 
immediately, and after that the MCU was locked. I was able to recover it using 
the Olimex debugger to issue a kinetis mass_erase command. This requires a 
low-level debugger, so it can't be done with the ST-LINK V2.

I was able to eventually patch the kinetis.c flash driver to correct the 
problems. I identified two issues.

The first has to do with the way the ST-LINK V2 performs write accesses. It 
performs an automatic verify on write, which means that after a write 
transaction is issued, it then peforms a read tranaction to the same location 
and compares the result with what it tried to write. If they don't match, then 
the dongle returns an error status.

It turns out this behavior conflicts a bit with the behavior of the Kinetis 
flash controller. To start a flash operation, you write a 1 to bit 7 (0x80) of 
the FTFx_STAT register. This bit also indicates command completion: once you 
write a 1 to it, it will automatically clear and stay clear until the flash 
command completes. So to check for completion, you poll the FTFx_STAT register 
until bit 7 becomes set again.

The problem is, since the bit clears as soon as you write to it, this pretty 
much guarantees that when the dongle automatically reads back the register 
after writing it to it, the value it reads will not match what it wrote, so it 
will return  a verification error.

The kinetis_ftfx_command() function sees this return status from 
target_write_u8() and thinks issuing the command failed, so it aborts the whole 
flash update process. In reality though, the command has succeeded. Usually 
this command is an erase.

It also happens that the Kinetis parts have flash security registers whose 
values are loaded from offset 0x400 in the flash. Due to the above problem, 
these locations will be erased and then not properly re-written again. (If I 
remember right, the kinetis.c driver has code in it specifically to update this 
flash configuration field, but we never get to it because the whole flash 
update has been aborted.) The result is that now if you reset or power-cycle 
the MCU, it will load the security registers with values that put the chip into 
a secure state, and now you've basically locked yourself out of the device with 
no way to recover unless you happen to also have a low-level debugger handy.

Ironically, immediately after the target_write_u8(), there's a loop that reads 
the FTFx_STAT register to check for command completion, which works correctly.

I patched the kinetis_ftfx_command() function to remove the test of the return 
status from target_write_u8( ) and just rely on the completion check loop to 
detect if there was a problem executing the command, and this corrected this 
problem.

The second issue has to do with the update of the flash config field itself, 
which is done in kinetis_erase() using kinetis_write_inner().  Normally flash 
updates are done with a fast block update algorithm. Even with the above fix, I 
found that sometimes this can also fail. I suspect there's a similar timing 
problem involved as with the first issue, but I'm not certain where.

I was able to correct this problem by forcing the code to fall back to the slow 
write method just for this one operation. (That way updating the rest of the 
flash is still quick.)

I'm attaching a patch for the kinetis.c module which applies both these fixes. 
With this patch I can reflash the firmware in our KW01 board with the ST-LINK 
V2 reliably. (At least, I wasn't' able to get it to fail again with the fixes 
in place.) I'm not necessarily suggesting these fixes be used verbatim because 
I don't have any other Kinetis parts to check it against. Hopefully someone 
with access to more devices can do some better validation.


---

Sent from sourceforge.net because openocd-devel@lists.sourceforge.net is 
subscribed to https://sourceforge.net/p/openocd/tickets/

To unsubscribe from further messages, a project admin can change settings at 
https://sourceforge.net/p/openocd/admin/tickets/options.  Or, if this is a 
mailing list, you can unsubscribe from the mailing list.
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to