As in another question, I have a CC2652 which is locked in cJTAG mode. I would like to completely erase the flash memory so that the bootloader is re-enabled, but I don't have a JTAG or cJTAG debugger (the bootloader uses serial UART for which I already have the FT232RL).

So, for just this one "Erase Flash" cJTAG command, plus all the handshaking protocols needed around it, how can I bit bang the TCK and TMS signals? I have an Arduino (and other programmable microprocessors with GPIO pins) to easily control the TCK and TMS signals.

A complete answer with all toggles and time points is probably too much to ask for here, so just a crude flow sequence would be fine.

Firstly, I am wondering how much I can slow the TCK clock down. Could I just manually toggle this clock signal every 10 seconds and walk through the TMS toggling manually (either 0V, or 3V, or high-impedance when a response is expected)?

Secondly, I am wondering what responses will come on TMS. Are there just a few ACK/NAK along the way? With wishful thinking for ACKs only, can I just ignore responses?

This would make for a good low-level-timing cJTAG learning example (I can't find any oscilloscope timing diagrams of cJTAG communication on the internet to help me understand this though it seems like most embedded microcontrollers are moving to cJTAG). The full spec might be in TI's application note but, before I dig into it, I want to estimate how much time this whole project would take me...I really don't want to spend weeks on this, but I often fall down these "rabbit holes" and regret it in the end.

  • \$\begingroup\$ Try TI's UNIFLASH. \$\endgroup\$
    – RussellH
    Dec 30, 2023 at 20:56
  • \$\begingroup\$ @RussellH UNIFLASH would require a cJTAG debugger (it uses some variant of XDS100) which I don't allow for this question. \$\endgroup\$
    – bobuhito
    Dec 31, 2023 at 0:27
  • \$\begingroup\$ About rabbit hole of implementing all this... If you start fresh and have to grasp FTDI, JTAG, cJTAG, ARM debug, CC26, you may have a hack that barely works in a few days. If you want some generic system that works with other chips, does correct abstraction of debug adapters, protocols and components, count months. \$\endgroup\$
    – Nipo
    Dec 31, 2023 at 14:13

1 Answer 1



CJTAG is defined in IEEE-Std-1149.7, an extension to JTAG. A TAP with .7 functionality is called a TAPC in the spec.

Main idea behind 1149.7 is to provide alternate wire protocols for JTAG, among which some use only two wires (TCK and TMS, called TCKC and TMSC in .7 world). This involves transmitting data that is usually on TDI/TDO through TMSC.

CJTAG in CC2652

Nonetheless, CC2652 TAPC also supports "classic" 1149.1 4-wire protocol. Thing is you have to reconfigure the TAPC to switch to this mode. This involves writing to TAPC registers with a specific protocol (not using TDI and TDO, as they are not specified at this time).

CJTAG TAPC registers

Each TAPC has a set of registers that can be written to. This uses the protocol defined in 1149.7 chapter 9, explained as well in CC2652 Reference Manual chapter 6.2.1.

Basically, this uses the usual JTAG TAP states, in an unusual yet standard and benign way, to transfer data. It uses three operations:

  • DR Capture,
  • DR Shift,
  • Run/Test-Idle.

RTI state marks the boundary of the command, Capture moves between successive values, Data value is the count of bits transferred with Shift. Everything is done using an instruction where DR shifts never harm, like Bypass or IDCODE. Note a TAP is mandated by standard to be reset in one of these states.

Changing to 4-wire JTAG

This requires to send the following commands to TAPC:

  • Control level lock to 2,
  • STC2, unconditionally (c = 0), APFC (bb = 0), on (v = 1),
  • STMC, StateCtl (bbb=0), ECL (xy=1).

This is translated to the following shift counts separated by RTI:

  • Constant, [0, 0, 1],
  • CP0 = 0b00010, CP1(cbbvv) = 0b01001, i.e. [2, 9],
  • CP0 = 0b00000, CP1(bbbxy) = 0b00001, i.e. [0, 1].

This translates to the following sequence (intermediate state are omitted):

  • RTI,
  • Capture DR, Update DR, Capture DR, Update DR, Capture DR, Shift DR 1 cycle, Update DR, RTI,
  • Capture DR, Shift DR 2 cycles, Update DR, Capture DR, Shift DR 9 cycles, Update DR, RTI,
  • Capture DR, Update DR, Capture DR, Shift DR 1 cycle, Update DR, RTI.

Note if no Shift happens between Capture and Update, you must go through the following states: Capture, Exit1, (optionally Pause and Exit2), Update. This effectively shifts no bit between Capture and Update, and is called a Zero-bit shift (ZBS). If not marked above, going from Update to capture must happen through the "short" path that goes from Update to Select DR (TMS=1).

Note that the actual TDI value is meaningless, here counts the number of states you run through Shift DR.

If ever you reset the TAP, you must go through this again.

Are we there yet ?

Of course not.

CC26xx features a TAP router called iCEpick that allows to dynamically connect / disconnect other TAPs from the chip in the chain. By default, iCEpick does not expose any other TAP than its own. We need to enable the Cortex' one, but first, we need to set the connect register (See Ti CC2652RM,

ARM JTAG-DP enablement is performed through the Router register (See 6.3.3) with:

  • Write-enable = 1,
  • Block = Debug,
  • Number = 0,
  • Value bit 8 = 1.

This boils down to a write to

  • IR = 7, DR = 0x89 (8 bits)
  • IR = 2, DR = 0xa0280127 (32 bits), run for 10 cycles.

After this, ARM JTAG-DP is in the chain, and enumeration may happen normally.

Flash programming

Like most ARM Cortex-M based microcontrollers, CC26xx are programmed by using the main memory bus to issue commands to the flash controller (I already did a breakdown of all this in another answer).

Chip Mass-erase

Besides ARM JTAG-DP (that allows debug and programming), CC26xx features another TAP called "WUC" that can be connected to the chain through iCEpick. This TAP has a few commands defined in the TRM (chapter 6.8), one of which is CHIP_ERASE_REQ (IR=1, DR=2). Actual usage of this command is a bit underdefined.


All above is basically performed in OpenOCD's TCL inits: cJTAG init, iCEpick init.


Don't expect any answer when issuing TAPc register writes, there is no defined response possible, not even at the protocol level.

iCEpick has a lot of registers, you can basically enumerate all sub-TAPs. This is mostly explained in the datasheet.

You may run TMS as slow as necessary, even 0.1 Hz. I would not recommend to bit-bang this by hand anyway.

Most of the standard concepts and workings are explained in the CC2652 Reference Manual. Problem with this datasheet is terrible writing. Once you read the standard and understand it, you start understanding the datasheet.

  • \$\begingroup\$ "You may run TMS as slow as necessary" answers one of my questions (are you sure 0.1 Hz is ok?). Any thoughts on my other questions or how the exact pin toggling looks if I just want to erase the flash? \$\endgroup\$
    – bobuhito
    Dec 31, 2023 at 12:52
  • \$\begingroup\$ Added a note about WUC TAP in the main answer \$\endgroup\$
    – Nipo
    Dec 31, 2023 at 14:07
  • \$\begingroup\$ I would not need to change to 4-wire JTAG, right? I just want to do a cJTAG (2-wire is OK) Chip Mass-Erase in as few toggles as possible. \$\endgroup\$
    – bobuhito
    Dec 31, 2023 at 18:24
  • \$\begingroup\$ Documentation and examples for cJTAG are way more sparse. If you want to trade ease of development for count of toggles, you may stay in cJATG mode. It will probably be a frustrating experience, though. \$\endgroup\$
    – Nipo
    Jan 2 at 10:18
  • \$\begingroup\$ So, maybe I should set my first goal even lower than Chip Mass-Erase. Can you think of something even easier to bit bang that will just confirm that cJTAG has not been disabled (so, I guess I would need some request, like CHIP_ID, after which I could confirm a non-empty response from CC2652)? or the simplest hello which I could use to see an ACK/NAK response? \$\endgroup\$
    – bobuhito
    Jan 2 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.