Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save tobiasfrejo/d98e9f4cbbc6893662ab032b06388685 to your computer and use it in GitHub Desktop.

Select an option

Save tobiasfrejo/d98e9f4cbbc6893662ab032b06388685 to your computer and use it in GitHub Desktop.

CC2652 unbricking with Raspberry Pi and OpenOCD

I was a bit quick when flashing my generic CC2652R and ended up dowloading and flashing firmware for CC2652P.. Since it was the wrong firmware, the bootloader also didn't work anymore, making me unable to flash the correct firmware with the integrated USB serial programmer.

Luckily the module has a cJTAG debugging interface, that should make it possible to flash directly onto the chip without the bootloader. But I don't have any serial debuggers, so I have had to come up withj my own from various limited information I could find.

Approach

Using OpenOCD we can use a Raspberry Pi as a JTAG debugger. It does not support cJTAG for debugging, so it will instead send a signal to make the CC2652 switch to normal JTAG. We will then have to connect a few additional cables to the TDO and TDI pins for a full 4-pin JTAG connection.

Using telnet to connect to OpenOCD, we can then send debugging commands to the chip to flash the correct firmware.

I imagine this approach should be easily adoptable to other CC2xxx based modules.

Requirements

Hardware

  • cJTAG breakout cable (5-pin JST-SH to female dupont)
  • 2x male-female dupont cables
  • Raspberry Pi

Software

How

Connect the CC2652 with the Raspberry Pi's GPIO pins

Using the following chart, connect the CC2652 with the Raspberry Pi's GPIO pins:

Name RPi GPIO# RPi Pin CC2652P Pin Name
3v3 Power N/A 17 VDD (cJTAG)
JTAG_TDI 10 19 DIO_17
JTAG_TDO 9 21 DIO_16
JTAG_TMSC 25 22 TMS (cJTAG)
JTAG_TCKC 11 23 CLK (cJTAG)
GND N/A 25 GND (cJTAG)

Note: The TDI and TDO pins of the CC2652P are specified in the datasheet. If you are trying this guide on another chip, you should look up its datasheet to make sure you connect it correctly.

You can check out pinout.xyz to easily find the correct GPIO pins.

It is possible to use different pins on the Raspberry. You will then just have to change the interface configuration file of OpenOCD.

From the cJTAG breakout cable, connect 3v3, GND, TMS, and CLK. Leave the RST pin unconnected.

Use the two single dupont cables to connect to the through-hole soldering points. There should be a bit of resistance, which will ensure a reasonable connection.

Install and configure the software

We need to install OpenOCD and a telnet client on the Raspberry Pi

sudo apt update
sudo apt install openocd telnet

Now copy the preconfigured cc26x2 launchpad file for OpenOCD to your home directory

cp /usr/share/openocd/scripts/board/ti_cc26x2_launchpad.cfg openocd.cfg

We will need to change it a bit to use the Raspberry's GPIO as the JTAG interface, so change

source [find interface/xds110.cfg]
adapter speed 5500

to

source [find interface/raspberrypi2-native.cfg]
adapter speed 1000

If you are using a Raspberry Pi 1, then replace raspberrypi2-native.cfg with raspberrypi-native.cfg

The contents of ~/openocd.cfg should then be

#
# TI CC26x2 LaunchPad Evaluation Kit
#
source [find interface/raspberrypi2-native.cfg]
adapter speed 1000
transport select jtag
source [find target/ti_cc26x2.cfg]

Different GPIO pins

You can connect the cables to different GPIO pins on the Raspberry Pi, edit /usr/share/openocd/scripts/interface/raspberrypi2-native.cfg and set the used GPIO numbers (NOT pin numbers) on the line

bcm2835gpio_jtag_nums 11 25 10 9

This has to be the GPIO number, e.g. where GPIO 11 is on pin 23. See pinout.xyz for a reference guide.

Download firmware

Download the correct firmware. For reference, I am using Koenkk's compiled Z-stack coordinator firmware. Make sure to get the correct one this time! (that mistake is the reason I have had to do this, and I guess a similar reason as to why you are here too 😅)

wget https://github.com/Koenkk/Z-Stack-firmware/raw/develop/coordinator/Z-Stack_3.x.0/bin/CC2652R_coordinator_20221102.zip
unzip CC2652R_coordinator_20221102.zip

Start the debugger

Now simply run openocd. It will load the config located at ~/openocd.cfg automatically.

If you see

Info : JTAG tap: cc26x2.jrc tap/device found: 0x3bb4102f (mfg: 0x017 (Texas Instruments), part: 0xbb41, ver: 0x3)
Info : JTAG tap: cc26x2.cpu enabled
Info : cc26x2.cpu: hardware has 6 breakpoints, 4 watchpoints

in the output, the configuration should be loaded correctly

Connect with telnet and flash

In a new terminal, run

telnet localhost 4444

You should now be able to run the following commands in the telnet console to flash the firmware

init
reset
halt
flash write_image erase CC2652R_coordinator_20221102.hex
flash verify_image CC2652R_coordinator_20221102.hex

Hopefully you end up with a successful verification telling you that it is successfully flashed:

verified 179184 bytes from file CC2652R_coordinator_20221102.hex in 0.635823s (275.209 KiB/s)

Sources

This guide has been made by combining bits and pieces from the following places

@FilipDem
Copy link

Hi all, I am also struggling and have the same problem as SureshKarthik.
I have a zigbee2mqtt Dongle Plus Smart Home Stick which is based on a cc2652P. I checked the layout of the pinheader with the chip pinout and wired to a Raspberry Pi4. I already checked the wiring from the chip cc2652P to the raspberry pi and all are OK.
However still having the problem Error: JTAG scan chain interrogation failed: all zeroes.
I played already with the adaptor speed (reducing), but didn't change.
Is there anything special I might not have paid attention? I really checked in detail the whole procedure described above...

@art103
Copy link

art103 commented May 23, 2025

@FilipDem, please see my post above. I had the same error with RPI4 and needed to change the .cfg file used by the openocd version installed:

# The JTAG/SWD specification requires pull-up at the target board
# for either signal. Connecting the signal pulled-up on the target
# to the pull-down on the adapter is not a good idea.
# GPIO 8 is pulled-up by default.
echo "Warn : TMS/SWDIO moved to GPIO 8 (pin 24). Check the wiring please!"```

@FilipDem
Copy link

Hi art103, thanks for the answer.
I read indeed the information, but could not make the link procedure above: the interface/raspberrypi2-native.cfg is used (using GPIO25 for TMSC) while in your comments, you are referring to interface raspberrypi-gpio-connector.cfg (with GPIO8 for TMSC).

In my version (installed with apt install openocd, I have not found the raspberrypi-gpio-connector.cfg (or perhaps I looked over it - will check again tomorrow).

So is it rather using the interface raspberrypi-gpio-connector.cfg? Or changing to the GPIO8 in the raspberrypi2-native.cfg because of the pullup? If I well understood it would be required to use the GPIO8 due to the buildin pull-up instead of GPIO25. Is this right?

A bit of extra guidance could probably help me further.
Already a big thanks for your reaction!

Filip

@FilipDem
Copy link

OK, sorry, now I understand what is meant with "update"... I thought I had to change something, but it is taking the last version version from Github. All done, using now the interface/raspberrypi-native.cfg as the interface/raspberrypi2-native.cfg is deprecated. Changed connection to GPIO8 on the raspberry... So I think I understand the whole required changes.
But still same result for me...

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