Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Flashing CC2538 using OpenOCD (&UART)

Flashing CC2538 using OpenOCD (&UART)

Problem description

CC2538 SoCs are Cortex-M4 based SoCs by Texas Instruments for 802.15.4 PAN networking, especially for Zigbee communication using their Zigbee Stack solution. It also is a solid foundation for hobbyist-grade solutions involving Zigbee communication, especially for running a self-implemented Zigbee coordinator (often called "Zigbee gateway" in commercial distribution of similar tech). Software-wise, this is usually done by running "ZNP" (Zigbee Network Processor) firmware on the SoC and using a separate controller/computer to act as the "ZAP" (Zigbee Application Processor). In a hobbyist setting, the former is usually a cheap module from china containing the chip, capacitors and an antenna or antenna connector, while the latter is e.g. a Raspberry Pi or an Intel NUC or whatever floats your boat. The API between both components is specified and so the software side on the ZAP does not need to bother with Zigbee communication states but can act on a higher level. Examples for such software are zigbee2mqtt by koenkk or zigbee-lua by yours truly. This software usually was built on the CC2530/31 chipsets - however, the CC2538 is compatible in the ZNP/ZAP API and generally much more crafty and stable as it has a faster CPU core and more available memory. RF wise, as per the specs, they are mostly on par.

While the CC2530/31 uses an 8051 based CPU core and has its own proprietary two-wire debugging protocol that is also used for flashing the firmware, the CC2538 uses cJTAG (and in a second stage optionally JTAG) for this purpose. The easy way to flash firmware onto the CC2538 is therefore the Segger J-Link. In its "Edu" variant, which probably fits hobbyists best license-wise, it is somewhat affordable for hobbyists - but still not a bargain.

The reason of this short gist is therefore a short description on how to use a generic approach to flash CC2538 devices using open source OpenOCD software.

Approach

The CC2538 allows debug access using cJTAG (this is active by default upon boot) and - after switching over - using JTAG. We will use this facility to write to CC2538 memory. Currently, there does not seem to be available code that allows for easy flashing a full firmware blob. So we're resorting to a trick and do this in two steps:

  • first we access the internal flash controller control registers. We will write a few values that will make the CC2538 erase its last flash page. This will, among other things, clear the "valid firmware present" indicator in said flash page, and will also set a flag that in combination will activate the integrated bootloader in the CC2538.
  • then after a reset, the CC2538 will be in bootloader mode. Via its UART port, https://github.com/JelmerT/cc2538-bsl can be used to flash a full firmware image.

NOTE: using a (slightly forked) variant of OpenOCD, erasing the flash page and then using the serial bootloader is obsolete: it has a flash loader for the CC2538. So flashing a firmware is now as easy as connecting JTAG and running OpenOCD. See this comment: https://gist.github.com/hwhw/fc43892785aa84913d03495c97b0f25a#gistcomment-3518720

Prerequisites

In order to flash the CC2538 using OpenOCD, you need

  • a reasonably recent version of OpenOCD (https://openocd.org/)
  • an "interface" that OpenOCD can use. This can e.g. be FT2232 based USB/multiprotocol adapter, or in my case a Raspberry Pi (and in that case you would run OpenOCD on said RPi).
  • some telnet client to interact with OpenOCDs CLI.
  • https://github.com/JelmerT/cc2538-bsl for flashing after we used OpenOCD to prepare bootloader mode (not needed when using forked OpenOCD with CC2538 flash loader)

By the way: now is a good point in time to check if said bootloader mode is active on your CC2538 anyway (just wire up UART connection and run cc2538-bsl.py), which will save you lots of time since then you don't need to use OpenOCD.

Wiring up the CC2538 for (c)JTAG

From now on, information in the CC2538 reference manual is indispensible: http://www.ti.com/lit/ug/swru319c/swru319c.pdf When using OpenOCD in combination with a Raspberry Pi, you need to check the according OpenOCD interface configuration. By default, you'll find this in /usr/share/openocd/interface/raspberrypi2-native.cfg (for RPi >=2). The RPi pins used for JTAG communication are specified there. I suggest you go with the defaults. Note that there's two numbering schemes for RPi GPIOs, which will make things veeeeery awkward. At some point, you'll get this right, I guess. Default config is:

  • JTAG TCK - GPIO 11 - Pin 23
  • JTAG TMS - GPIO 25 - Pin 22
  • JTAG TDI - GPIO 10 - Pin 19
  • JTAG TDO - GPIO 9 - Pin 21

You need to wire up the full JTAG interface, as we will be using cJTAG just for switching over to JTAG mode. The CC2538 side is as follows:

  • JTAG TCK = cJTAG TCK - dedicated TCK pin 47.
  • JTAG TMS = cJTAG TMSC - dedicated TMS pin 46.
  • JTAG TDI - PB6 (=pin 49)
  • JTAG TDO - PB7 (=pin 48)

Also connect at least a common ground connection. You can also power the CC2538 using the RPi's 3.3V rail. Make double sure that you use the 3.3V rail, not the 5V rail.

Running OpenOCD

On the RPi (or whatever host you are using), run

openocd -f /usr/share/openocd/interface/raspberrypi2-native.cfg -f /usr/share/openocd/target/cc2538.cfg

(adapt to the interface you're using if it is not a RPi >= 2.)

It should output some status that will basically tell you it communicated successfully with the CC2538. Well, probably it won't on try #1 and you need to re-check your cables and so on, but at some point it hopefully will.

Use the OpenOCD CLI

In a different terminal - possibly even on another computer - run telnet localhost 4444 You should be greeted by the OpenOCD command line then. The following commands are to be entered on this OpenOCD command line interface.

erase flash CCA

using a fork of OpenOCD, this is not needed anymore, see https://gist.github.com/hwhw/fc43892785aa84913d03495c97b0f25a#gistcomment-3518720

Set erase address:

mww 0x400D300C 0x7F800

(note that this was shifted in an earlier release of this document - with a current version of OpenOCD of today, this seems to work instead now)

Issue erase command (also set flags to unlock)

mww 0x400D3008 0x0205

That's it, the CCA should be erased and all flags should be cleared now. I tried to reconstruct this from my OpenOCD history. I sincerely hope that these are the right commands. You can check the CCA contents using the command mdb 0x0027F800 2048 and hopefully, everything is cleared. If you want to read up on what those register writes did, check the reference manual for the CC2538 and read up on the flash controller in the memory section.

Use the bootloader

using a fork of OpenOCD, this is not needed anymore, see https://gist.github.com/hwhw/fc43892785aa84913d03495c97b0f25a#gistcomment-3518720

wiring up an UART

Use whatever UART adapter you like - e.g. maybe the built-in UART of the RPi you used for flashing? Or a simple USB-UART adapter? Make sure it has an adequate voltage level, then connect it as follows:

  • cc2538 UART RX is on PA0
  • cc2538 UART TX is on PA1
  • make sure you have a common ground connection and to power the cc2538 with a 3.3V source

run cc2538-bsl.py

https://github.com/JelmerT/cc2538-bsl will show you information about a connected cc2538 in bootloader mode and will allow flashing. Be sure that you've read the documentation. Especially about the bootloader backdoor configuration (also have a look into the cc2538 reference manual to learn about the exact way how to configure the backdoor enable pin). Note that using the JTAG method described above you do not need the bootloader backdoor. It might still be handy to enable it if possible, as this saves a step and some wiring.

@huyphamnhu

This comment has been minimized.

Copy link

@huyphamnhu huyphamnhu commented Aug 12, 2020

After issue erase command mww 0x400D3008 0x205 :

  • The bootloader backdoor configuration at byte 0x0027FFD7 stay unchanged 11101111 (bit 4 still 0, mean backdoor and boot loader disable)
  • The image_valid bits 0x0027FFD8 to 0x0027FFDB stay unchanged 0x00000000 (indicate valid image in flash)

After playing with 0x400D3008 and 0x400D300C for awhile, I'm still unable to erase those fields.

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 22, 2020

Yeah, same issue here
After mww 0x400D3008 0x0205, I check mdb 0x0027F800 2048 and see all FF, except
0x0027ffc0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ef 00 00 00 00 00 00 20 00
According to cc2538 spec, byte 2011-2008 if 0 meaning image valid
Because of this byte 2007 = EFh which makes backdoor and bootloader disable
I think mww 0x400D3008 0x0205 will NOT do flash mass erase, that's why image valid byte is still set

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I found the problem.
Somehow there is bug in openocd v.0.10.0 which I'm using
The bug is, mww command will shift 2 bit to the left
So for writing address 0x1FE00, then need to issue :

mww 0x400D300C 0x7F800

and for writing command 0x0205, then need to issue :

mww 0x400D3008 0x8240
@th0m4sek

This comment has been minimized.

Copy link

@th0m4sek th0m4sek commented Aug 25, 2020

Is this method applicable to cc1352? I can't find similar registers in cc1352 reference manual.
https://www.ti.com/lit/ug/swcu185d/swcu185d.pdf

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

@th0m4sek: Try this https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/796369
I don't have cc1352 so can't test, so good luck ....

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

I found the problem.
Somehow there is bug in openocd v.0.10.0 which I'm using
The bug is, mww command will shift 2 bit to the left
So for writing address 0x1FE00, then need to issue :

mww 0x400D300C 0x7F800

and for writing command 0x0205, then need to issue :

mww 0x400D3008 0x8240

Can you explain this better? I tried it without sucess.
And I can't see how the shifting requires the change that you refer...

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I found the problem.
Somehow there is bug in openocd v.0.10.0 which I'm using
The bug is, mww command will shift 2 bit to the left
So for writing address 0x1FE00, then need to issue :

mww 0x400D300C 0x7F800

and for writing command 0x0205, then need to issue :

mww 0x400D3008 0x8240

Can you explain this better? I tried it without sucess.
And I can't see how the shifting requires the change that you refer...

Which openocd version are you using?
You just try "mww 0x400D300C 0x1FE00" and read it back "mdb 0x400D300C 16" then
you can tell whether mww writes correct data or not

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

I found the problem.
Somehow there is bug in openocd v.0.10.0 which I'm using
The bug is, mww command will shift 2 bit to the left
So for writing address 0x1FE00, then need to issue :

mww 0x400D300C 0x7F800

and for writing command 0x0205, then need to issue :

mww 0x400D3008 0x8240

Can you explain this better? I tried it without sucess.
And I can't see how the shifting requires the change that you refer...

Which openocd version are you using?
You just try "mww 0x400D300C 0x1FE00" and read it back "mdb 0x400D300C 16" then
you can tell whether mww writes correct data or not

I know it doesn't, but I can't see what your workaround does... it still gives a wrong number

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I know it doesn't, but I can't see what your workaround does... it still gives a wrong number

well, in my case i can see my openocd mww shift 2 bits
your case might be different, so you just need to find correct formula

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

I know it doesn't, but I can't see what your workaround does... it still gives a wrong number

well, in my case i can see my openocd mww shift 2 bits
your case might be different, so you just need to find correct formula

Could you please show an example to send me to the right path? Thanks

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I know it doesn't, but I can't see what your workaround does... it still gives a wrong number

well, in my case i can see my openocd mww shift 2 bits
your case might be different, so you just need to find correct formula

Could you please show an example to send me to the right path? Thanks

what do you see when you try "mww 0x400D300C 0x1FE00" and read it back "mdb 0x400D300C 16" ?

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

also what do you see when you try "mww 0x400D3008 0x0205" and read it back "mdb 0x400D3008 16" ?

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

I know it doesn't, but I can't see what your workaround does... it still gives a wrong number

well, in my case i can see my openocd mww shift 2 bits
your case might be different, so you just need to find correct formula

Could you please show an example to send me to the right path? Thanks

what do you see when you try "mww 0x400D300C 0x1FE00" and read it back "mdb 0x400D300C 16" ?

I get 80 7f 00 00 00 00 00 00 4e 06 64 b9 0f 03 03 01

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

mww 0x400D3008 0x0205

04 02 00 00 80 7f 00 00 00 00 00 00 4e 06 64 b9

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I get 80 7f 00 00 00 00 00 00 4e 06 64 b9 0f 03 03 01

I should be the same issue like mine, mww is shifted 2 bit to the left
1FE00 = 0001 | 1111 | 1110 | 0000 | 0000
then shifted 2 bit to the left >>> 0001 | 1111 | 1110 | 0000 | 0000 | 00 = 7F800

So the next time you write "mww 0x400D300C 0x7F800" and read it back "mdb 0x400D300C 8", should get
00 e0 1f 00 00 00 00 00

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

I get 80 7f 00 00 00 00 00 00 4e 06 64 b9 0f 03 03 01

I should be the same issue like mine, mww is shifted 2 bit to the left
1FE00 = 0001 | 1111 | 1110 | 0000 | 0000
then shifted 2 bit to the left >>> 0001 | 1111 | 1110 | 0000 | 0000 | 00 = 7F800

So the next time you write "mww 0x400D300C 0x7F800" and read it back "mdb 0x400D300C 8", should get
00 e0 1f 00 00 00 00 00

it is still not 1FE00...
Or am I gettinhg this wrong?

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

it is still not 1FE00...
Or am I gettinhg this wrong?

what do you see when you write "mww 0x400D300C 0x7F800" and read it back "mdb 0x400D300C 8" ?

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 25, 2020

it is still not 1FE00...
Or am I gettinhg this wrong?

what do you see when you write "mww 0x400D300C 0x7F800" and read it back "mdb 0x400D300C 8" ?

I get 00 fe 01 00 00 00 00 00

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 25, 2020

I get 00 fe 01 00 00 00 00 00

that's correct data >> 01 fe 00 (little endian)
so after writing mww 0x400D300C 0x7F800 then mww 0x400D3008 0x8240,
you can verify flash memory page 255 data by issuing mdb 0x0027F800 2048 then you will see all content FF

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 26, 2020

unfortunatelly no... CCA remains the same... so, bootloader still locked... Any ideas @dony71 ?

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 26, 2020

So, I finally got it...
@dony71, you were partially right:
first you must use:
mww 0x400D300C 0x7F800
because of the bit shift, but after that you should use the command in the OP:
mww 0x400D3008 0x0205

That way, it works like a charm! ;)

@dony71

This comment has been minimized.

Copy link

@dony71 dony71 commented Aug 26, 2020

mww 0x400D3008 0x0205

very strange ... if 0x1FE00 must shift 2 bit then 0x0205 must shift 2 bit also since both are using mww command
anyway ... glad that finally it works for you

@MadDoct

This comment has been minimized.

Copy link

@MadDoct MadDoct commented Aug 26, 2020

mww 0x400D3008 0x0205

very strange ... if 0x1FE00 must shift 2 bit then 0x0205 must shift 2 bit also since both are using mww command
anyway ... glad that finally it works for you

Issue the command you suggested instead of 0x0205 and read back the value...
If you use mww 0x400D3008 0x0205, and read the value it will be 04 02, which is perfect because the last bit is changed back to 0 after the erase resulting in 04 02 instead of 05 02... That shows that 0205 was sent correctly...

By the way, to help others, the default telnet port is not 3333 as stated in the OP, but 4444

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Oct 17, 2020

I'am using a RPI B+.
In only get this errors:

Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-10-17-13:52)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select '.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response

Any idea what the problem can be?

@th0m4sek

This comment has been minimized.

Copy link

@th0m4sek th0m4sek commented Oct 24, 2020

I'am using a RPI B+.
In only get this errors:

Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-10-17-13:52)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select '.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response

Any idea what the problem can be?

same here...

@th0m4sek

This comment has been minimized.

Copy link

@th0m4sek th0m4sek commented Nov 1, 2020

I don't know how to proced hope debug log will help https://github.com/th0m4sek/cc2538/blob/main/openocd.log

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 4, 2020

Sorry all, somehow I did not see all the alerts on this gist. I can't really help that much, it's mostly a description of my poking at OpenOCD and the CC2538. It seems it has helped at least some of you, so it was probably worth it to write everything down.
@th0m4sek: Are you sure the cabling is correct?

@th0m4sek

This comment has been minimized.

Copy link

@th0m4sek th0m4sek commented Nov 4, 2020

I just received jlink edu mini and flashed with it. Thanks for help.

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Nov 6, 2020

You can also flash directly from openocd with:
sudo src/openocd -f tcl/interface/raspberrypi-native.cfg -f tcl/target/cc2538.cfg -s tcl/ -c "program {/home/pi/firmware/MODKAMRU_V3_UART-no-flow-control_with_SBL.hex}"
I had openocd build but not installed with "make install".

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 6, 2020

Nice, so OpenOCD has a flash stub now for the CC2538? That's great! This makes the crude approach described in this gist obsolete.

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Nov 6, 2020

Yes, I have used this openocd: https://git.jim.sh/jim/openocd. That can make maybe a difference.
I had also troubles with the commands from this topic and the confusing shifts or not. So I tried this flash.

I did this:

pi@raspberrypi:~/openocdcc2538 $ git clone https://git.jim.sh/jim/openocd.git
cd openocd
./bootstrap
./configure --enable-sysfsgpio --enable-bcm2835gpio
make

Then edit the file tcl/target/cc2538.cfg
Adjust this 2 lines:
source [find tcl/target/icepick.cfg]
source [find tcl/target/ti-cjtag.cfg]

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 9, 2020

Indeed, this is a version of OpenOCD that has the flash loader for the cc2538 (in contrib/loaders/flash, plus glue code). That's marvellous! I'll add a corresponding note at the top of this document.

@miqmago

This comment has been minimized.

Copy link

@miqmago miqmago commented Nov 15, 2020

I've cleared CCA following the commands in the dev device from https://es.aliexpress.com/item/4001285481883.html.

It seems that something has happened after executing the instructions: the device starts without blinking leds, so it seems it is in bootloader, but I've tried to flash with cc2538-bsl and always getting the same error (also tried before removing CCA):

$ python cc2538-bsl.py -V -p /dev/tty.SLAB_USBtoUART

Opening port /dev/tty.SLAB_USBtoUART, baud 500000
Connecting to target...
*** sending synch sequence
Traceback (most recent call last):
  File "cc2538-bsl.py", line 1193, in <module>
    if not cmd.sendSynch():
  File "cc2538-bsl.py", line 373, in sendSynch
    return self._wait_for_ack("Synch (0x55 0x55)", 2)
  File "cc2538-bsl.py", line 267, in _wait_for_ack
    % (info,))
CmdException: Timeout waiting for ACK/NACK after 'Synch (0x55 0x55)'
ERROR: Timeout waiting for ACK/NACK after 'Synch (0x55 0x55)'

I've tried with openocd from https://git.jim.sh/jim/openocd which comes with cc2538 driver with no luck:

Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-11-15-00:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter driver' not 'interface'
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Info : cc2538.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000136c msp: 0x20008000
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000136c msp: 0x20008000
** Programming Started **
Info : Flash write discontinued at 0x0023c800, next section at 0x0027ffd4
Error: failed erasing sectors 0 to 120
embedded:startup.tcl:510: Error: ** Programming Failed **
in procedure 'script' 
at file "embedded:startup.tcl", line 26
in procedure 'program' called at file "/home/pi/flash.cfg", line 34
in procedure 'program_error' called at file "embedded:startup.tcl", line 575
at file "embedded:startup.tcl", line 510

flash.cfg looks like this:

source [find /home/pi/rpi_jtag.cfg]
transport select jtag
source [find target/cc2538.cfg]

if { [info exists CHIPNAME] } {
	set _CHIPNAME $CHIPNAME
} else {
	set _CHIPNAME cc2538
}

$_TARGETNAME configure -work-area-phys 0x08000 -work-area-size 11264
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME cc2538 0 0 0 0 $_TARGETNAME
init
targets
reset halt
program MODKAMRU_V3_UART-no-flow-control-devboard-v1.hex

Please any advice on how to recover the mcu? Is there a way to revert the write done with mww 0x400D3008 0x0205 so I can start playing again?

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 16, 2020

No, the whole CCA is deleted and there's a checksum of the main flash contents that determines whether the flash content is valid - that would be gone now. Well, in theory, you should be able to re-calculate that, but this won't be easy. The second openocd log is more telling: it fails when trying to erase memory. So I'd have a look at the CCA and see if access rights are properly set (unset, that is) for flash pages. Also, you will see the current bootloader config there, so this is mandatory information to check where you currently are. Last but not least, you could go on and try to erase the full flash using manual register access like the post does for the CCA.

@miqmago

This comment has been minimized.

Copy link

@miqmago miqmago commented Nov 16, 2020

Actually I could do the flashing connecting the device with an USB-UART dongle (RX on PA0 and TX on PA1) and using https://github.com/1248/cc2538-prog/:

git clone https://github.com/1248/cc2538-prog/
cd cc2538-prog
make
wget https://github.com/reverieline/CC2538-CC2592-ZNP/blob/master/MODKAMRU_V3/MODKAMRU_V3_UART-no-flow-control.hex -O MODKAMRU_V3_UART-no-flow-control.hex
./cc2538-prog -d /dev/ttyUSB0 -f MODKAMRU_V3_UART-no-flow-control.hex

This firmware has no backdoor, so to reflash I have to connect via JTAG and reset via openocd again. The good thing is that the wires can be kept (both JTAG and UART at the same time, just need to reset the device or power off and on again) so there is no need to disconnect it and reconnect wires.

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Nov 16, 2020

Actually I could do the flashing connecting the device with an USB-UART dongle (RX on PA0 and TX on PA1) and using https://github.com/1248/cc2538-prog/:

git clone https://github.com/1248/cc2538-prog/
cd cc2538-prog
make
wget https://github.com/reverieline/CC2538-CC2592-ZNP/blob/master/MODKAMRU_V3/MODKAMRU_V3_UART-no-flow-control.hex -O MODKAMRU_V3_UART-no-flow-control.hex
./cc2538-prog -d /dev/ttyUSB0 -f MODKAMRU_V3_UART-no-flow-control.hex

This firmware has no backdoor, so to reflash I have to connect via JTAG and reset via openocd again. The good thing is that the wires can be kept (both JTAG and UART at the same time, just need to reset the device or power off and on again) so there is no need to disconnect it and reconnect wires.

You can download with backdoor from here: https://github.com/egony/MODKAM-STICK-V3/tree/master/firmware/cc2538/Riverieline_2020-02

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 16, 2020

@miqmago: glad to hear you've been successful! (and in my mind I make a note that the alternative OpenOCD might not be a silver bullet after all...)

@miqmago

This comment has been minimized.

Copy link

@miqmago miqmago commented Nov 18, 2020

@glsf91 Thanks! Why don't make a pull request to https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_3.0.x/bin? This is the repo is the one pointed by https://www.zigbee2mqtt.io/ I think it could be usefull.

@miqmago: glad to hear you've been successful! (and in my mind I make a note that the alternative OpenOCD might not be a silver bullet after all...)

Thanks!! In my case I couldn't get to be done with cc2538-bsl. The only way was through cc2538-prog. Maybe would be worth to mention this alternative way in your awesome gist! Thanks again for this good job!!

@Ant1q

This comment has been minimized.

Copy link

@Ant1q Ant1q commented Nov 28, 2020

I'am using a RPI B+.
In only get this errors:

Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-10-17-13:52)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select '.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response

Any idea what the problem can be?

Hello! Did you pass this error? This what i did:

sudo apt-get install git autoconf libtool make pkg-config libusb-1.0-0 libusb-1.0-0-dev
git clone git.jim.sh/jim/openocd 
cd openocd/
./bootstrap && ./configure --enable-sysfsgpio --enable-bcm2835gpio && make
sudo src/openocd -f tcl/interface/raspberrypi2-native.cfg -f tcl/target/cc2538.cfg -s tcl/ -c "program {123.hex}"

maybe i missed something?

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Nov 28, 2020

I did not pass the error. I bought another CC2538.

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 28, 2020

@Ant1q: does that mean you're seeing the same errors? The spurious ACKs look a bit like connection problems. Too long/flimsy cables somewhere? Is there a stable power source for the CC2538? I found them to get a bit funny if their 3.3V rail is flaky. Do the errors only happen when trying to issue the program command? Is there a stable connection without giving the command to openocd?

@Ant1q

This comment has been minimized.

Copy link

@Ant1q Ant1q commented Nov 29, 2020

I have that

pi@raspberrypi:~/openocd $ sudo src/openocd -f tcl/interface/raspberrypi2-native.cfg -f tcl/target/cc2538.cfg -s tcl/ -c "program {123.hex}"
Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-11-28-00:48)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (4) in DAP response
in procedure 'program'
** OpenOCD init failed **
shutdown command invoked

i have doublechecked connections between pins and chip legs, so i think the wiring is ok, and try different sources of 3.3v, still same problem.
But i noticed - my chip have different design, so i do not have PB6\PB7 pins. I have
cc2538

i connect RPi3 pins 19 and 21 to TDI and TDO on cc2538

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Nov 30, 2020

These very probably are PB6/PB7. The quoted output you gave is still with running the "program" command, so I'm not sure if it is specific to that. The point where the error occurs is likely the cJTAG-to-JTAG switch, though, so it is probably something about the TDI/TDO lines. Can you visually inspect the module and possibly electronically probe that the pads are connected to the correct SoC pins and there's no funky business with other components on these lines?

@Roman-RV78

This comment has been minimized.

Copy link

@Roman-RV78 Roman-RV78 commented Dec 18, 2020

У меня есть это

pi@raspberrypi:~/openocd $ sudo src/openocd -f tcl/interface/raspberrypi2-native.cfg -f tcl/target/cc2538.cfg -s tcl/ -c "program {123.hex}"
Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2020-11-28-00:48)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Info : JTAG tap: cc2538.jrc tap/device found: 0x8b96402f (mfg: 0x017 (Texas Instruments), part: 0xb964, ver: 0x8)
Info : JTAG tap: cc2538.cpu enabled
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (6) in DAP response
Error: Invalid ACK (4) in DAP response
in procedure 'program'
** OpenOCD init failed **
shutdown command invoked

Я дважды проверил соединения между контактами и ножками микросхемы, поэтому я думаю, что с проводкой все в порядке, и пробую разные источники 3,3 В, все та же проблема.
Но я заметил - мой чип имеет другой дизайн, поэтому у меня нет контактов PB6 \ PB7. я имею
cc2538

Я подключаю контакты 19 и 21 RPi3 к TDI и TDO на cc2538

Hello. Was it possible to solve this problem? I have the same connection problems

@glsf91

This comment has been minimized.

Copy link

@glsf91 glsf91 commented Dec 29, 2020

I had also a CC2538 with messages like: Error: Invalid ACK (6) in DAP response when using Pi with openocd. See my message of 17 Oct above.
I could flash this device with a Segger J-Link clone by using this

@znanev

This comment has been minimized.

Copy link

@znanev znanev commented Jan 1, 2021

I had exactly the same experience as @ant1k and @Roman-RV78.

Then I tried with a J-Link and when connecting to the target it complained something in the lines that the debug interface of the chip was locked. So I erased it and after that I couldn't connect to the target until I disconnected the USB interface of the J-Link and plugged it back in. After that connecting and identifying the chip was successful and I programmed it with the latest firmware and the device now functions as expected. So probably there are steps missing in OpenOCD (or instructions for using it with this particular MCU), which prevents flashing it via JTAG with a Raspberry Pi.

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Jan 2, 2021

I am sorry it didn't work for you. It did for me. Very definitely. All the errors mentioned above do not really lead anywhere, it would need more debugging to see what the culprit is. As for now, I'm not even convinced it is just cabling and possibly a few passives on the modules in question getting in the way.

@janis-veinbergs

This comment has been minimized.

Copy link

@janis-veinbergs janis-veinbergs commented Jan 24, 2021

In case anyone using raspberry pi 4 with Ubuntu.

I installed openocd on ubuntu 20.04 using apt-get install openocd. However this lacked bcm2835gpio interface/adapter resulting in error: Error: The specified debug interface was not found (bcm2835gpio). So had to manually get openocd from github and compile it with that support. After removing openocd package:

git clone https://git.code.sf.net/p/openocd/code openocd
cd openocd
./bootstrap
./configure --enable-maintainer-mode --enable-bcm2835gpio --enable-sysfsgpio
make -j4

Credit: https://movr0.com/2016/09/02/use-raspberry-pi-23-as-a-jtagswd-adapter/ (code blocks are white in that site, but if you select all text, text is revealed)

And then adjust config for Rpi4:

sudo cp /usr/local/share/openocd/scripts/interface/raspberrypi2-native.cfg /usr/local/share/openocd/scripts/interface/raspberrypi4-native.cfg
sudo vim /usr/local/share/openocd/scripts/interface/raspberrypi4-native.cfg

Change bcm2835gpio_peripheral_base and bcm2835gpio_speed_coeffs to these values:

bcm2835gpio_peripheral_base 0xFE000000
bcm2835gpio_speed_coeffs 236181 60

Credit: https://www.raspberrypi.org/forums/viewtopic.php?t=252551

@hwhw

This comment has been minimized.

Copy link
Owner Author

@hwhw hwhw commented Jan 25, 2021

Thank you! Oh yes, I gather the frequency scaling of the RPi might run havoc with timing, so this might be another thing to look at. Clocked data shouldn't be all that touchy but... well, very irregular timing might be an issue.

@SBA7

This comment has been minimized.

Copy link

@SBA7 SBA7 commented Mar 8, 2021

Yes, I have used this openocd: https://git.jim.sh/jim/openocd. That can make maybe a difference.
I had also troubles with the commands from this topic and the confusing shifts or not. So I tried this flash.

I did this:

pi@raspberrypi:~/openocdcc2538 $ git clone https://git.jim.sh/jim/openocd.git
cd openocd
./bootstrap
./configure --enable-sysfsgpio --enable-bcm2835gpio
make

Then edit the file tcl/target/cc2538.cfg
Adjust this 2 lines:
source [find tcl/target/icepick.cfg]
source [find tcl/target/ti-cjtag.cfg]

Hi, I did all exactly as posted above but getting only this:

pi@raspberrypi:~/openocd $ sudo src/openocd -f tcl/interface/raspberrypi2-native.cfg -f tcl/target/cc2538.cfg -s tcl/ -c "program {/home/pi/firmware/MODKAMV3.hex}"
Open On-Chip Debugger 0.10.0+dev-01083-gb1fa3bf7 (2021-03-08-17:31)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
BCM2835 GPIO nums: swclk = 11, swdio = 25

Info : auto-selecting first available session transport "jtag". To override use 'transport select '.
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 100 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: cc2538.jrc: IR capture error; saw 0x3f not 0x01
Warn : Bypassing JTAG setup events due to errors
Info : Listening on port 3333 for gdb connections
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: cc2538.jrc: IR capture error; saw 0x3f not 0x01
Warn : Bypassing JTAG setup events due to errors
** Programming Started **
Error: Target not examined yet
Error: auto_probe failed
embedded:startup.tcl:510: Error: ** Programming Failed **
in procedure 'program'
in procedure 'program_error' called at file "embedded:startup.tcl", line 575
at file "embedded:startup.tcl", line 510

Any idea what is wrong and how to fix it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment