view doc/Calypso-OpenOCD-Howto @ 82:e2161ac7d641

linux-patch: move original 2020-07 version into orig-202007
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 06 Dec 2020 01:20:27 +0000
parents 6d02f30e35ad
children
line wrap: on
line source

Using OpenOCD to operate on Calypso JTAG: proof of concept
==========================================================

We have a proof-of-concept OpenOCD configuration for talking to Calypso JTAG
based on the theoretical findings described in the Calypso-JTAG-notes document
in the freecalypso-docs repository; the present document describes how one can
practically use OpenOCD on an FCDEV3B target.

Choice of JTAG adapter hardware
===============================

The PoC presented here uses an off-the-shelf unbuffered FT2232D breakout board
with a special EEPROM configuration as the JTAG adapter, as described in the
Unbuffered-FT2232x-JTAG article.  ADBUS0 through ADBUS3 are wired to standard
JTAG signals as required by FTDI and ADBUS7 (acting as a GPIO) is wired to the
XDS_RESET line on JTAG connector pin 2.  This choice of using a generic FT2232D
breakout board as opposed to a more purpose-made "professional" JTAG adapter
was made deliberately in order to force the user to make a mental shift
regarding reset signals: any standard JTAG adapter product will have two reset
outputs designated as TRST and SRST, but the XDS_RESET signal on the FCDEV3B
does not correspond to either of those.  But a generic (non-JTAG-specific)
FT2232x breakout board does not have TRST or SRST, it only has ADBUS and ACBUS
pins that become GPIOs in MPSSE mode, allowing the user to break out of the
TRST and SRST mentality: you just have a bunch of GPIOs, then arbitrarily pick
one of those GPIOs and connect it to XDS_RESET, *without* associating it with
either TRST or SRST.

The full set of needed wire connections is thus:

FT2232D signal	FCDEV3B JTAG signal
-----------------------------------
ADBUS0		TCK (pin 11)
ADBUS1		TDI (pin 3)
ADBUS2		TDO (pin 7)
ADBUS3		TMS (pin 1)
ADBUS7		XDS_RESET (pin 2)

You will also need to connect at least one ground pin, hence 6 wires in total.
There is no need to connect the undocumented and non-understood EMU0 and EMU1
signals - we don't know what to do with them and we work without them.  This
wiring arrangement and all functionality described in this article work exactly
the same way on both D-Sample and FCDEV3B boards.  You will also need to
reprogram the EEPROM on the FT2232D board as described in the
Unbuffered-FT2232x-JTAG article *before* you connect it to the Calypso target
board.

One can also connect just the 4 JTAG wires, without reset: there are some
historical commercial phones and modems on which JTAG lines are accessible, but
Iota nTESTRESET is not, or perhaps nTESTRESET is accessible, but you don't feel
like replicating the transistor circuit that is required in order to drive it
safely - the circuit that is present on development boards, but not on hacked-up
phones and modems.  In that case you will still be able to halt an already-
running Calypso, but of course you won't be able to exercise reset_halt or
reset_run operations described below.

Unpowered FT2232D adapter quirk
===============================

If you connect the FT2232D board to the FCDEV3B as described above, including
the XDS_RESET signal and ground, you will notice the following quirk: if the
custom-crimped JTAG cable is connected between the two boards, but the FT2232D
board is not plugged into a USB host (has no USB power), the FCDEV3B will be
held down in test reset: the green LED will be off, and neither button on the
board will do anything.  The FCDEV3B will be released from this reset and will
boot in test reset mode with the green LED on the moment you plug the FT2232D
board into your USB host.

Running OpenOCD
===============

With the FT2232D board plugged into your host PC or laptop and programmed with
the custom USB ID of 0403:7151, you can run OpenOCD with the custom config file
presented in the calypso-jtag directory in this repository:

openocd -f ft2232d-unbuf-poc.cfg

Being a proof of concept, this OpenOCD config file does not follow any of the
guidelines regarding separation between adapters and targets, but is fully
monolithic instead.  This config is written to work with openocd-0.10.0
(depends on the new ftdi driver), but does NOT use the target/ti_calypso.cfg
fragment that has been included in mainline OpenOCD for quite some time: in the
Mother's opinion, the latter is bogus.  If someone wishes to bring Calypso
support in the mainline OpenOCD distribution up to par, I do not have any
advice or guidance for you: it is your job, not mine.  The present PoC config
that is rather antagonistic to mainline OpenOCD, its framework and its
guidelines will always remain our standard answer to FreeCalypso customers
asking how to make JTAG work.

When you run OpenOCD as above, the FCDEV3B target needs to be in the running
state with the green LED on.  OpenOCD will exercise and verify the scan chain,
but it won't issue any resets or halts on its own, thus whatever code was
running on the board won't be disturbed in any way by the act of running
OpenOCD.  You can then reset and/or halt the target as desired with our custom
commands (Tcl procedures) as described below.

Halting the Calypso without a reset
===================================

To halt an already-running Calypso ARM7 core without a reset, stopping it at
whatever point it happens to be in its code execution, execute this sequence:

enable_halt; halt

The enable_halt step is a custom Tcl procedure added by us, issuing the
mysterious 0xB instruction and DR scan that are needed in order to enable halts
on TI's modified version of the ARM7TDMI core.  Once you have halted as above,
you can resume and halt again without needing to re-execute the enable_halt
step; the only time when the enable_halt step will need to be repeated is when
the Calypso is reset.

You can safely halt the Calypso in this manner when the flash is blank and the
boot ROM waits forever for a serial download, when you have loaded a RAM image
with fc-xram -j and the target is left in loadagent, or when one of our standard
firmwares is running; in all of these states the Calypso watchdog timer is
disabled.  However, if you are going to halt the Calypso when the watchdog timer
is running, you will need to execute our wd (watchdog disable) command quickly
after the halt, before the watchdog timer is allowed to expire.  A simple way
would be:

enable_halt; halt; wd

The wd command (Tcl procedure) name was deliberately made short so it can be
typed quickly with fingers if need be.

Resetting with or without a halt
================================

We don't support OpenOCD's standard reset command because we found it too
difficult to override its built-in assumptions which are wrong for our Calypso.
Instead we have our own reset_halt and reset_run custom commands (Tcl
procedures) that replace OpenOCD's standard 'reset halt' and 'reset run',
respectively.

The reset_run command will reset the board without halting the Calypso, letting
it boot and run normally.  It is equivalent to pressing the RESET button on the
board with your finger, except that it also re-initializes OpenOCD's scan scain
and "target examination" state which would otherwise get confused.

The reset_halt command will reset the board and halt the Calypso immediately as
it comes out of reset, halting at the reset vector before the first instruction
of the boot ROM code (or the first instruction from external memory if operating
on a D-Sample board with the boot switch set to external) is executed.  The
necessary disabling of the watchdog timer (wd procedure call) is already built
into the reset_halt Tcl procedure; except for this wd step, all Calypso and Iota
registers will be in their most pristine reset state.

Recovering bricked Compal phones
================================

Some Mot C1xx phones have Calypso JTAG signals brought out to accessible contact
pads, allowing a way to recover from a bricked flash bootloader via JTAG.
However, they do not bring out Iota nTESTRESET, instead they bring out a signal
which they call DLPWR, which is really Iota RPWON.  A procedure similar to our
reset_halt would need to be performed as the first step in the recovery
sequence, but it would need to be modified to work with DLPWR instead of
XDS_RESET.  The RPWON aka DLPWR signal will need to be driven with an OC/OD
driver (it is internally pulled up to raw VBAT, which is not a safe voltage for
standard 3.3V logic), and the switch-on and boot sequence will be triggered
when this signal is pulled low, i.e., transitions from high to low.  The
subsequent release transition (from low back to pull-up high) does not matter,
i.e., RPWON may be permanently pulled down as the Calypso boots and runs, very
much unlike nTESTRESET or XDS_RESET.

It will be up to you to design whatever circuit you wish to use to produce an
OC/OD driver that can be triggered from OpenOCD, but connecting RPWON aka DLPWR
directly to an FT2232x I/O pin is not acceptable.  Copying the circuit from
TI/FC development boards that propagates XDS_RESET into nTESTRESET won't work
either: this circuit only works when the V-IO regulator is already on, but
RPWON is not a reset and will need to be triggered when the chipset is fully
"cold".

You will also need to figure out the appropriate timing.  You will need to
insert a certain delay between RPWON assertion and the 'jtag arp_init' step in
our reset_halt procedure: the VRPC state machine in the Iota chip will do a
bunch of work between sensing a low on RPWON and releasing the Calypso from
reset via ON_nOFF, and until then the JTAG scan chain won't work.  But the
delay cannot be too long either, or you won't halt the Calypso before it starts
executing bogus code from the phone's bricked flash.

Once you do get a working reset_halt variant, the following steps will be
straightforward:

1) Run fc-loadtool -h compal -c none /dev/ttyXXX on the serial port connected
   to the phone's headset jack;

2) Enable the boot ROM and jump to it with these commands:

   mwh 0xFFFFFB10 0x100
   resume 0

The boot ROM will run while fc-loadtool is sending its beacons, fc-loadtool
will load and run loadagent, and you can then recover the flash.

Lack of performance optimizations
=================================

Our PoC OpenOCD-on-Calypso config does not set up a work area (an area of
system RAM that is declared as a scratchpad for OpenOCD), nor does it enable
arm7_9 dcc_downloads or arm7_9 fast_memory_access.  These omissions are
intentional, as those performance optimizations are outside of the scope of
what I set out to do, which is to prove Calypso JTAG as working and provide a
"golden reference" setup.

If you wish to set up an area in Calypso IRAM as a work area for OpenOCD, which
is a prerequisite for arm7_9 dcc_downloads, you will need to choose the location
based on your specific application - whether a given area will be suitable or
not will depend on exactly what you are debugging and exactly what you are
trying to do, which is once again outside of the scope of this PoC.