Showing posts with label pyOCD. Show all posts
Showing posts with label pyOCD. Show all posts

December 19, 2013

debugging pyOCD gdb (tutorial)

I finally found a root cause of pyOCD locking kinetis chip. It took me quite a while to get into gdb server implementation, still many functions are unveiled for me. I am going to give you few tips what I would do once something is not working, or even to be sure that the right binary is going to be flashed. That's was my case, when I knew that pyOCD is flashing wrong data to the wrong address.

To start with, please if you use gdb server, change logging to DEBUG. This information is in gdb_test.py file.

logging.basicConfig(level=logging.DEBUG)

What helped me a lot to just see how data are interpreted, disable erasing the chip and then flashing as well. The code below is from gdbserver.py file. Don't forget, if you change anything inside pyOCD, please rerun setup.py file with a command

python setup.py install

Comment out two lines that init() and eraseALL().
if ops == 'FlashErase':
    self.flash.init()
    self.flash.eraseAll()
    return self.createRSPPacket("OK")

Flashing is carried out by calling programPage. Once you comment that line out, your target won't be flashed, so you can add a breakpoint anywhere there, write data to a file and see how they are interpreted.
while len(self.flashData) > 0:
    size_to_write = min(self.flash.page_size, len(self.flashData))
    #if 0 is returned from programPage, security check failed
    if (self.flash.programPage(flashPtr, self.flashData[:size_to_write]) == 0):
        logging.error("Protection bits error, flashing has stopped")
        return None
    flashPtr += size_to_write

    self.flashData = self.flashData[size_to_write:]

    # print progress bar
    sys.stdout.write('\r')
    i = int((float(flashPtr)/float(bytes_to_be_written))*20.0)
    # the exact output you're looking for:
    sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
    sys.stdout.flush()

There are many debug files commented in the implementation, which are intended for debugging purposes. The one below is from FlashDone command case, once you enable it, the bad_bin contains entire data which are going to be written to the flash. You can compare it to your bin generated, reveal if it matches the data.

elif 'FlashDone' in ops :
    flashPtr = 0
    bytes_to_be_written = len(self.flashData)

    """
    bin = open(os.path.join(parentdir, 'res', 'bad_bin.txt'), "w+")
    
    i = 0
    while (i < bytes_to_be_written):
        bin.write(str(self.flashData[i:i+16]) + "\n")
        i += 16
    """

How did I solve that problem with locking the chip? The most important addition is the security bits check, which is crucial. If data at the address 0x400 are not set to 0xFF, flashing should be stopped. If it would not be stopped, the chip can get secured, depending on the 16 byte value at that address.
I added the following lines, this is why debug logging is good to have enabled, you can see how those bits are set and are going to be flashed. This would have unveiled that chip is going to get locked.

def checkSecurityBits(self, address, data):
    #error if security bits have unexpected values
    if (address == 0x400):
        for i in range(12):
            logging.debug("data[%d] at add 0x%X: 0x%X", i, i, data[i])
            if (data[i] != 0xff):
                return 0

        logging.debug("data[%d] at add 0x%X: 0x%X", i+3, i+3, data[i+3])
        logging.debug("data[%d] at add 0x%X: 0x%X", i+4, i+4, data[i+4])
        if ((data[i+3] != 0xff) or (data[i+4] != 0xff)):
            return 0

    return 1

I even locked sometimes the chip (only security bit or some other bits, not mass erase bit). If chip is locked, mbed msd drive does not need to appear! Don't get frustrated. Follow the lines below, and you might get mbed drive again.
To solve this problem, get into bootloader mode (to disable CMSIS-DAP which enables another interface to access the mcu chip), use external jlink or just openSDA jlink. Execute the commands I shared in the previos post:
unlocking kinetis chip with jlink console [http://embeddedworldweb.blogspot.com]
Don't be afraid if it returns error, sometimes it does but chip is functional again. Just reconnect your board, mbed drive should appear again if the chip is not bricked (like mass erase bit is set).

To get familiar with gdb serial protocol, this link helps
GDB Remote serial protocol [www.embecosm.com/appnotes/]

I will add more chips to pyOCD. Finding the root cause of locking the kinetis chip provided a really appreciated lesson. Happy to contribute to pyOCD.

Side note: the security check is on my branch at the moment - waiting for merge to the master branch. Don't use KL25Z with pyOCD from the origin master at the moment! You can lock your chip. Thanks for understanding.
To test the above features, here's link to my branch  dev issue#1 - security bits check [github.com/0xc0170]

December 3, 2013

unlocking kinetis (KL25Z) with the jlink console

I locked my KL25Z board using pyOCD gdb yesterday, was not able to connect to the chip with ULINK, neither with CMSIS-DAP interface on KL25Z (K20). Because I am using older bootloader on openSDA interface, the board does not recognize jlink openSDA binary file. The only option left for me was to test it with an external jlink. So you need an external jlink to follow. I am not aware that ulink can do this. If you are, leave a comment!

To start with this, enter to the bootloader mode, if you are using openSDA hardware interface. So no any other interface is active which would block an access to the target.

I connected my jlink to it, shown error while connecting to the chip. Usually when I locked kinetis chip, at least jlink was able to connect to MCU. This time I assumed the mass erase protection bit was set. Thus I followed just simple steps find out what is the state of my core. I got lucky, the mass erase bit was not set, jlink was able to unlock the kinetis. If mass erase bit is set, it would fail. I accidentally selected KL26Z chip.

SEGGER J-Link Commander V4.76f ('?' for help)
Compiled Sep 27 2013 16:54:08
DLL version V4.76f, compiled Sep 27 2013 16:53:51
Firmware: J-Link Lite-FSL V1 compiled Jun 25 2012 16:40:07
Hardware: V1.00
S/N: 361000149
VTarget = 2.874V
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
No devices found on JTAG chain. Trying to find device on SWD.
Info: Found SWD-DP with ID 0x0BC11477

****** Error: Error while identifying Cortex-M core.
Info: Found SWD-DP with ID 0x0BC11477
No device found on SWD.
Failed to identify target. Trying again with slow (4 kHz) speed.
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
No devices found on JTAG chain. Trying to find device on SWD.
Info: Found SWD-DP with ID 0x0BC11477

****** Error: Error while identifying Cortex-M core.
Info: Found SWD-DP with ID 0x0BC11477
No device found on SWD.

J-Link>device ?
Info: Device "MKL26Z128XXX4" selected (128 KB flash, 16 KB RAM).
Reconnecting to target...
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
J-Link>unlock kinetis
Unlocking device...O.K.
J-Link>SWDReadAP 0x1000000
Read AP register 16777216 = 0x00000000
J-Link>SWDReadAP 0x1000000
Read AP register 16777216 = 0x00000031
J-Link>erase
Info: Found SWD-DP with ID 0x0BC11477
Info: Found SWD-DP with ID 0x0BC11477
Info: Found Cortex-M0 r0p0, Little endian.
Info: FPUnit: 2 code (BP) slots and 0 literal slots
Info: Kinetis L-series (setup): Disabling watchdog.
Erasing device (MKL26Z128xxx4)...
Info: J-Link: Flash download: Flash programming performed for 1 range (1024 byte
s)
Info: J-Link: Flash download: Total time needed: 1.086s (Prepare: 0.465s, Compar
e: 0.143s, Erase: 0.017s, Program: 0.047s, Verify: 0.012s, Restore: 0.399s)
Erasing done.
J-Link>

To read further about MDM-AP Control register (check the output SWDReadAP), see chapter 9.3.1 MDM-AP Control Register where all bits are described.

Update1:
I am testing the KL46Z interface, got locked today, but was not able to revive it with the same procedure as above, unlocking failed firstly. I invoked erase, passed with a error, and the unlock. My chip is again alive!

SEGGER J-Link Commander V4.76f ('?' for help)
Compiled Sep 27 2013 16:54:08
DLL version V4.76f, compiled Sep 27 2013 16:53:51
Firmware: J-Link Lite-FSL V1 compiled Jun 25 2012 16:40:07
Hardware: V1.00
S/N: 361000149
VTarget = 3.280V
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
No devices found on JTAG chain. Trying to find device on SWD.
Info: Found SWD-DP with ID 0x0BC11477

****** Error: Error while identifying Cortex-M core.
Info: Found SWD-DP with ID 0x0BC11477
No device found on SWD.
Failed to identify target. Trying again with slow (4 kHz) speed.
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
No devices found on JTAG chain. Trying to find device on SWD.
Info: Found SWD-DP with ID 0x0BC11477

****** Error: Error while identifying Cortex-M core.
Info: Found SWD-DP with ID 0x0BC11477
No device found on SWD.
J-Link>device ?
Info: Device "MKL46Z256XXX4 (ALLOW SECURITY)" selected (256 KB flash, 32 KB RAM)
.
Reconnecting to target...
Info: Could not measure total IR len. TDO is constant high.
Info: Could not measure total IR len. TDO is constant high.
J-Link>unlock kinetis
Unlocking device...Timeout while unlocking device.
J-Link>unlock kinetis
Unlocking device...Timeout while unlocking device.
J-Link>unlock kinetis
Unlocking device...Timeout while unlocking device.
J-Link>erase
Info: Found SWD-DP with ID 0x0BC11477

****** Error: Kinetis (connect): Timeout while halting CPU. CPU does not stop.
Erasing device (MKL46Z256xxx4 (allow security))...
Info: Found SWD-DP with ID 0x0BC11477
Info: Found SWD-DP with ID 0x0BC11477
Info: Found Cortex-M0 r0p0, Little endian.
Info: FPUnit: 2 code (BP) slots and 0 literal slots
Info: Kinetis L-series (setup): Disabling watchdog.
Info: J-Link: Flash download: Flash programming performed for 1 range (1024 byte
s)
Info: J-Link: Flash download: Total time needed: 1.173s (Prepare: 0.481s, Compar
e: 0.245s, Erase: 0.016s, Program: 0.001s, Verify: 0.010s, Restore: 0.417s)
Erasing done.
J-Link>unlock kinetis
Unlocking device...O.K.
J-Link>

December 2, 2013

pyOCD (gdb) and KL25Z

As I wrote yesterday, that everything was working, I run today directly gdb, using elf file. The result? KL25Z got locked, can't flash it anyhow. Need to replace the chip and look into the gdb server implementation, why it caused locking the chip. This confirmed what users reported on mbed site, that it locks the chip.

Here's an output:


Readelf returns from application elf file (simple gpio demo which I used yesterday, but bin file created from this elf file):

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0xc1
  Start of program headers:          52 (bytes into file)
  Start of section headers:          111732 (bytes into file)
  Flags:                             0x5000002, has entry point, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         23
  Section header string table index: 20

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .isr_vector       PROGBITS        00000000 008000 0000f4 00  AX  0   0  4
  [ 2] .flash_protect    PROGBITS        00000400 008400 000010 00   A  0   0  1
  [ 3] .text             PROGBITS        00000410 008410 006818 00  AX  0   0  8
  [ 4] .ARM.exidx        ARM_EXIDX       00006c28 00ec28 000008 00  AL  3   0  4
  [ 5] .data             PROGBITS        1ffff0c0 00f0c0 0000dc 00  WA  0   0  4
  [ 6] .bss              NOBITS          1ffff19c 00f19c 000154 00  WA  0   0  4
  [ 7] .heap             PROGBITS        1ffff2f0 00f1a0 000080 00      0   0  8
  [ 8] .stack_dummy      PROGBITS        1ffff2f0 00f220 000080 00      0   0  8
  [ 9] .ARM.attributes   ARM_ATTRIBUTES  00000000 00f2a0 000028 00      0   0  1
  [10] .comment          PROGBITS        00000000 00f2c8 0000e0 01  MS  0   0  1
  [11] .debug_info       PROGBITS        00000000 00f3a8 00579f 00      0   0  1
  [12] .debug_abbrev     PROGBITS        00000000 014b47 0011c7 00      0   0  1
  [13] .debug_loc        PROGBITS        00000000 015d0e 000e8a 00      0   0  1
  [14] .debug_aranges    PROGBITS        00000000 016b98 000298 00      0   0  8
  [15] .debug_ranges     PROGBITS        00000000 016e30 0002d0 00      0   0  8
  [16] .debug_line       PROGBITS        00000000 017100 0016d4 00      0   0  1
  [17] .debug_str        PROGBITS        00000000 0187d4 00184b 01  MS  0   0  1
  [18] .debug_frame      PROGBITS        00000000 01a020 0012f0 00      0   0  4
  [19] .stabstr          STRTAB          00000000 01b310 000076 00      0   0  1
  [20] .shstrtab         STRTAB          00000000 01b386 0000ed 00      0   0  1
  [21] .symtab           SYMTAB          00000000 01b80c 002730 10     22 439  4
  [22] .strtab           STRTAB          00000000 01df3c 000e64 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)


Be warned !

November 28, 2013

pyOCD with KL25Z (introduction)

This is an introduction to pyOCD, my very first steps getting familiar with pyOCD. Two mbed users reported locking of their KL25Z chips with pyOCD. I hope we find out why!

The pyOCD used to be part of mbed github repository, but not anymore. It was separated, can be found here pyOCD repo [github.com/mbedmicro/pyOCD]. It has awesome readme file there, which serves as documentation.

the official mbed page for pyOCD Debuging from GDB using pyOCD [mbed.org/blog].

I started with pywinusb (using windows on my laptop), installed via easy_install.


The second step was to build pyOCD, run from the pyOCD root directory python setup.py install.


Connect KL25Z to your PC, be certain it has mbed interface! Time to start gdb session, either gdb from toolchain or from pyOCD. I chose to run gdb_test.py which is in pyOCD/test folder.


KL25Z detected, presume to flashing part. To be save, I opened basic_test.py located in test directory and commented out line 156 flash.flashBinary(binary_file). This prevents from flashing (locking alert which I explain later).


Everything went ok according to the console, flashing was skipped though. Now return the line 156 to test flashing part. Have ready compiled GCC program (I use bin file from the example I created for mbed GCC KL25Z demo).

If you run it without arguments, the default path is /binaries/l1_target.bin, the name of bin file for KL25Z is l1_kl25z.bin . Flashing was successful but program was not running correctly and chip got to secured state. I restarted gdb test script, received an error. I opened uVision, it displays a warning that chip is locked, but not permanently, fortunately! I have to get my prototype board, to continue with testing.

I'll share more once I explore what's going on and why chip got locked once.

Update 1st of December:
I have been debugging it for a while, I added some extra code which completely messed connection to the chip, gdb returned error. Once I found out what I did wrong, everything seems to be functional.
Even flashing different binaries does not lock chip, still using pyOCD scripts, not directly its gdb implementation.