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