FreeCalypso > hg > freecalypso-docs
view Calypso-JTAG-notes @ 94:7aaed576fa26
SIM-data-formats: fix Russian UCS-2 string example
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 10 May 2022 06:33:43 +0000 |
parents | 7ba5c951803c |
children |
line wrap: on
line source
This document describes the quirks of Calypso JTAG in an abstract, tool- independent sense, and also covers the little bit of experience we've had with TI's original official tools, but does not delve into OpenOCD specifics. For OpenOCD-on-Calypso custom config and instructions, please refer to the freecalyps-hwlab repository - but the present document should still be read first. Unconventional reset structure ============================== The first major way in which the JTAG interface on Calypso development boards (or more generally, what is available in the Calypso+Iota chipset) differs from "canonical" JTAG is that this chipset does NOT have reset signals that are anything like classic TRST or SRST. Instead there is only one bundled-with-JTAG reset signal (we call it XDS_RESET) which is turned into Iota nTESTRESET through a transistor circuit - please refer to the Calypso-test-reset article. Aside from its effects on the VRPC state machine described in that article, this test reset can be thought of as a simultaneous combination of an equivalent of TRST (all JTAG logic is hard-reset), an equivalent of SRST (the Calypso is fully reset and proceeds with a cold boot) and more (all hardware is reset at a very deep level), but comparisons to classic TRST and SRST aren't really appropriate as the latter signals simply don't exist in our chipset. However, despite its highly unconventional nature, this XDS_RESET signal provided along with JTAG on TI's development boards performs a very important function: this combination of JTAG and test reset allows a "reset and hold still" maneuvre where all hardware is put into its pristine state with a very deep reset, but the ARM7 CPU is halted before it gets a chance to execute any instructions from the reset vector. This ability is not particularly important on current Calypso hardware with a working and enabled boot ROM, but it was vital on earlier platforms without this boot ROM: if the flash is blank or contains a bad code image, or if RAM is mapped onto the boot chip select instead of flash, allowing the ARM7 core to execute garbage out of reset is bad, whereas having a "reset and hold still" ability allows guaranteed reliable recovery and bootstrapping from a blank or bricked state. As explained later in this article, this "reset and hold still" maneuvre is executed by first giving the target a test reset pulse (which unstoppably blows away all prior hw state), then immediately (the timing is critical) performing certain manipulations via the JTAG scan chain - thus the bundling of the XDS_RESET signal with JTAG is important. EMU0 and EMU1 signals ===================== In addition to the 4 standard JTAG signals TCK, TDI, TDO and TMS, the Calypso provides two TI-proprietary signals called EMU0 and EMU1. (The test reset goes to the Iota ABB, not to the Calypso.) These EMU0 and EMU1 signals are brought out to the 14-pin JTAG connector on TI's D-Sample and E-Sample boards, and also on our FCDEV3B. The function of these two signals is completely unknown: all we know is that they are listed as "bidirectional in/out" in the cal000.pdf document, and that same-named signals also exist on TI's general-purpose DSP chips, both C54x and the newer families, where they are also very poorly documented. We don't know what these EMU0/1 signals do on the Calypso, and it is a particular unknown whether they are specific to the DSP part or if the ARM7 part can also make use of them somehow. I (Mother Mychaela) previously thought that these signals might facilitate a way to halt the ARM7 core without going through the scan chain, or a different way to halt directly out of reset than the one we ultimately found, but a recent experiment has shown that pulling either or both of these signals low (they are pulled up on target boards) has absolutely no visible effect on ARM7 code execution, whether they are pulled low coming out of test reset or while running. Thus until we recover more understanding of what is going on inside the chip, we are going to ignore these two signals and leave them unconnected. Iota not included in the JTAG scan chain ======================================== In addition to the Calypso chip itself (the DBB), the Iota ABB chip also has JTAG pins and could potentially be included in the scan chain. However, this wiring arrangement is not typically used: both on TI's D-Sample board and on our own FCDEV3B (based on Leonardo schematics) the JTAG interface is wired only to the Calypso and not to Iota. The same arrangement has also been found in all historical commercial phones and modems that provide a JTAG interface. We don't have any plans to change this arrangement in any of our future designs: in the absence of 100% complete understanding of the internals of both chips, there is no telling what unexpected gotcha may occur if the Iota chip is included in the same scan chain as the Calypso, hence we are not doing that. ARM7 and C54x DSP cores ======================= The regular JTAG scan chain inside the Calypso goes through two TAPs corresponding to the two processor cores. The ARM7 TAP with a 4-bit IR is closer to TDI, and the C54x DSP TAP with an 8-bit IR is closer to TDO. The debug interface to the ARM7 core through its respective TAP is consistent with public ARM7TDMI documentation from ARM except for one important quirk described below, but we know absolutely nothing about the DSP TAP and its debug protocol other than how to put it into BYPASS so we can operate on the ARM. It appears from passing references in some TI documents that they did intend to have an ability to debug the Calypso DSP via JTAG "emulation", and TI's CCS software working through TI's XDS510 or XDS560 hardware (the same setup that successfully connects to the ARM7 part of the Calypso) supports C54x targets. However, we have no idea how any potential JTAG access to the DSP would interact with its reset control coming from the ARM or with its power saving modes, and it is very likely that there are some security mechanisms restricting debug access to the DSP (perhaps needing some secret key to unlock it), thus being able to debug the DSP via JTAG is not something we can realistically hope for unless we either buy out the complete chip design from TI or physically reverse-engineer the chip transistor by transistor, both options being equally cost-prohibitive. At our current level of budgetary means, our ability to use the JTAG interface on the Calypso is limited to the ARM7 part, not the DSP. Non-standard extension to the ARM7TDMI TAP ========================================== We know that TI made at least one non-standard extension to the ARM7TDMI TAP in the Calypso because it implements at least one additional opcode that does not appear in any public documentation from ARM. When connecting to this ARM7 target, TI's CCS software working through XDS510 or XDS560 hardware apparently scans a 0xB opcode (4'b1011) through the IR, and then apparently scans 2'b10 through the 2-bit DR selected by this opcode. (I said "apparently" because so far the only people who have actually sniffed the JTAG communications produced by the XDS+CCS combo were OsmocomBB people, not anyone from the FreeCalypso team, hence we don't have any authentic knowledge currently.) Experiments with OpenOCD show that the just-described sequence of IR and DR scans with an unknown instruction and an unknown data register is necessary in order to allow halting the ARM7 core: if we try to halt it in the standard ARM7TDMI way (either via DBGRQ or via a catch-all breakpoint unit setup) without doing the magic sequence first, no halt is effected. Fortunately though, after we issue the non-understood magic sequence once, all subsequent ARM7TDMI halt/resume manipulations done in the standard way appear to work just fine, no more quirks. The only time when the "halt unlock" magic sequence needs to be repeated is after a reset, which is expected. Interaction with the watchdog timer =================================== The Calypso chip includes a watchdog timer feature; if this watchdog timer is enabled and allowed to expire, it effects a fairly deep reset of the chip. The Calypso boot ROM code and most firmware designs do a step early on to disable this watchdog, and it is not subsequently re-enabled except to effect a reboot when so desired, but as the ARM7 core first comes out of reset and starts executing instructions from the reset vector (whether ROM or external memory), the watchdog timer is enabled and ticking. This watchdog timer interacts with JTAG as follows: 1) When the ARM7 core is halted via JTAG, the watchdog timer (if enabled) is NOT stopped or paused, but keeps ticking. 2) If a watchdog reset occurs while the ARM7 core is halted, everything goes out of whack, consistent with the note in standard ARM7TDMI documentation which says that a reset must not be applied to the core while it is in debug halt state. Therefore, if the ARM7 core is to be halted at a time when the watchdog timer is enabled and ticking, the halt operation must be quickly followed by two system bus write operations (mwh command in OpenOCD) to the WATCHDOG_TIM_MODE register, executing the watchdog disable sequence before the timer is allowed to expire while halted. JTAG clock speed ================ It is often stated that the JTAG clock speed must be no greater than 1/6 of the system clock speed when talking to ARM cores, and that JTAG access is blocked when the core goes into a power saving mode with the clock stopped. Neither of these constraints applies to our beloved Calypso though: the stated issues occur in chip designs which internally synchronize JTAG signals including TCK to their system clock, but Calypso and its predecessors don't do that, they use the hard macrocell version of the ARM7TDMI core instead, use TCK directly to clock JTAG- specific logic and perform "hard" clock switching for debug mode. According to the available cal000_a.pdf document, the maximum TCK frequency supported by the Calypso is 10 MHz, which also appears to be the only TCK frequency which TI's older XDS510 "emulator" pods can produce without hardware modifications. This 10 MHz TCK frequency can be used no matter what frequency is fed to Calypso's main CLKTCXO clock input or what frequency the ARM7 core is configured to run at, and JTAG keeps working even when the main clock is completely stopped. It is possible to halt the Calypso ARM7 core when it is in a sleep mode, even in deep sleep: manipulation of internal scan chain 2 to set DBGRQ is a JTAG-only operation, contained entirely in the TCK clock domain, thus it works even with the main VCXO stopped, and the actual halt occurs on wakeup when the ARM7 core regains its regular clock and sees the internal DBGRQ signal asserted. Halting immediately out of reset ================================ To me (Mother Mychaela) it always seemed evident that the Calypso and its predecessors had to have some way to perform a "reset and hold still" maneuvre, as this capability was absolutely essential for deterministic bootstrapping and recovery of boards before the Calypso boot ROM subsumed that function. However, the exact manipulations required to achieve this effect have remained elusive for a long time until I found the answer in May-June of 2019. The trick is NOT done through EMU0/1 pins like I once thought, and the method used on many other chips involving classic TRST and SRST signals is clearly not applicable to the Calypso given its very different reset structure. The answer lies in the clocking architecture of TI GSM chipsets, involving a VCXO that is started and stopped and a 32.768 kHz clock which is always running. When the Calypso starts its boot process in response to the ON_nOFF signal going from low to high (in the XDS-triggered test reset scenario this event immediately follows the release of external reset), the main VCXO is off (i.e., it hasn't been started yet) and only the 32.768 kHz clock is running. At this point the ARM7 core receives no clock at all (the 32.768 kHz clock is never fed to the ARM7), and the ULPD block (the same block that handles deep sleep) goes through the sequence of first enabling the main VCXO, then waiting for it to stabilize. This sequence takes about 8192 cycles of the slow clock (about 250 ms), and only at the completion of this sequence the ARM7 core gets its first clock. But during that 250 ms time window the JTAG logic is out of its reset and functioning, and it can be operated because Calypso JTAG does not depend on the main ARM clock which is stopped. The following sequence of steps successfully achieves the effect of resetting the Calypso+Iota chipset and all board-level peripherals that are subservient to it, and halting the Calypso directly at the reset vector before the first instruction is executed: 1) Give the chipset a test reset pulse via the XDS_RESET line; the exact required duration is not known, but my OpenOCD-based proof of concept gives a 50 ms pulse. 2) Immediately after releasing the reset or after a short delay (my PoC does a 10 ms delay), start exercising the JTAG scan chain, which has been fully reset - it will be responsive at this point. 3) Perform the "magic" IR and DR scans to enable halting ability, just like we do when we wish to halt an already-running Calypso. 4) Going through scan chain 2 inside the ARM7TDMI TAP, set the DBGRQ bit. All steps up to this one must happen before Calypso ULPD enables the VCXO-derived clock to the ARM7. 5) Also going through scan chain 2, poll and wait for DBGACK to get set, indicating that the ARM7TDMI core halted - this event will happen when the core gets its first clocks. 6) Once the ARM7TDMI core is halted, perform the two mwh operations to the 0xFFFFF804 register (WATCHDOG_TIM_MODE) to disable the watchdog, otherwise it will generate another internal reset and mess up the system state. We never found any built-in provision in TI's CCS (see below) or any script for CCS that does the above, instead I (Mother Mychaela) found it on my own by thinking about how it could possibly be done, and proved the idea working with an OpenOCD setup presented in the freecalypso-hwlab repository. Original official TI tools ========================== TI's original and official tool for operating on Calypso JTAG was their Code Composer Studio (CCS) software, working through TI's XDS510 and XDS560 "emulator" hardware. The original hardware solution was the XDS510, and I mean the original XDS510 which was an ISA card made by TI themselves, not any of the later "XDS510-class" "emulators" made by companies acting as TI's 3rd-party partners. The next successor to this original XDS510 was the original XDS560, also made by TI themselves and distinct from the later "XDS560-class" devices by TI's 3rd-party partner companies. The original XDS560 is a PCI card rather than ISA, thus a little easier to get working in 2019, and also more readily available on ebay. Both XDS510 and XDS560 consist of a desktop PC card (ISA or PCI) and an active pod, and the pod has a non-detachable target connection cable coming out of it, terminating in a female connector mating with the TI-style 14-pin JTAG header. The pod connector fits perfectly to TI's original D-Sample board, but on our FCDEV3B it fails to fit because the JTAG and dual UART headers are too close together. Therefore, anyone who is interested in connecting TI's original XDS510 or XDS560 to an FCDEV3B would need to get some male-to-female jumper wires or make a custom-crimped interposer cable. The version of CCS which we found to work with these "emulator" adapters (both XDS510 and XDS560) and with Calypso targets is this one: ftp://ftp.freecalypso.org/pub/GSM/TI_tools/CCS/CCS_3.3.83.20_win32.zip In order to get this CCS to work with a Calypso target, you will need to create a "custom board" configuration in CCS setup - none of the predefined board configs shipped with CCS will work. To create the needed "custom board" config, select your "emulator" (XDS510 or XDS560), then add an ARM7 target and a TMS320C5400 target in this order, which is the order from TDI to TDO. With this custom config saved, running CCS brings up what they call the Parallel Debug Manager, which supposedly supports coordinated debugging of both ARM and DSP cores. However, I (Mother Mychaela) have not tried connecting to the DSP part, only ARM7; another FreeCalypso community member who also got a working XDS510 setup talking to an FCDEV3B did try it, but saw what appears to be garbage. As discussed earlier in this article, we are completely in the blind here, hence this direction is not being seriously explored at the present. In order to play with just the ARM7 core, leaving the DSP alone, select the ARM7 target in the Open menu in Parallel Debug Manager - the main CCS debug window will then open, and it will be specific to the ARM7 target. In my own testing all further operations were done from the latter window and its menus. Reset with TI's tools --------------------- Both XDS510 and XDS560 "emulators" have only one reset output; on TI's general- purpose DSP development boards outside of the GSM Skunkworks division this one reset line was TRST, whereas on D-Sample and Leonardo boards (and on our FCDEV3B) this signal is repurposed to drive Iota nTESTRESET through a clever transistor circuit. TI's general-purpose (non-GSM) DSP chips and boards have internal pull-downs on TRST rather than pull-ups (JTAG logic permanently held down in reset when no "emulator" is connected), hence both XDS510 and XDS560 pods drive this signal with an active push-pull driver - which is why Calypso development boards include the special transistor circuit rather than connect the XDS_RESET line (as we call it) directly to internal nTESTRESET. Prior to initialization, a "cold" XDS560 pod has its reset output held low, thus the target board will be held down in test reset and will appear completely unresponsive. To initialize the XDS560 and release it from reset, select "Emulator Reset" from the Debug menu. For this operation to succeed, the LDO regulators in the Iota ABB need to be turned on, putting out 2.8 V on the V-IO rail which is used as the target voltage reference by the XDS560 pod, so you will probably need to press either the PWON button or the RESET button on the FCDEV3B initially - and if the green LED stays off after that button press, you know that the board is being held down in test reset by the XDS560 pod. Then do the "Emulator Reset" operation, at which point the green LED will turn on and the board will boot normally. From this point onward, doing a repeated "Emulator Reset" operation causes a low-then-high pulse to be put out on the XDS_RESET line, resetting the board and once again causing it to go through a fresh boot. Connecting to the ARM7 core and halting it ------------------------------------------ Once the XDS560 has been initialized and the target board has been lifted out of test reset with the "Emulator Reset" operation, you can execute the "Connect target" operation, also in the Debug menu. This operation produces a successful halt (I can only guess that this step is the point at which the mysterious 0xB JTAG instruction and the unknown 2-bit register scan are issued, unlocking the halting ability on this modified ARM7TDMI core), but the halt happens at whichever point the ARM7 core happens to be in its code execution, i.e., the generic, non-GSM-specific CCS has no knowledge of the peculiar timing sequence that is required to achieve a halt directly out of reset on the Calypso. It is my (Mychaela's) guess that CCS probably has some scripting ability for more advanced users, and that TI's GSM Skunkworks division used this custom scripting mechanism to do a sequence of {Emulator reset, then connect to target and halt, then execute two register writes to disable the watchdog} with machine rather human timing between the steps. Machine rather than human timing is required in order to hit the 250 ms window between the release of reset and the beginning of ARM core execution, and also to disable the watchdog after the halt via two register writes before it goes off. Using OpenOCD on Calypso targets ================================ Building on top of the work that was done almost a decade earlier by some people in the OsmocomBB camp (they sniffed the magic "halt unlock" sequence from an XDS+CCS setup and gained the ability to halt an already-running Calypso with OpenOCD, albeit without the reset magic) and adding the more in-depth understanding provided by Mother Mychaela, we now have the ability to use OpenOCD with a simple FT2232D adapter (instead of TI's XDS+CCS) to connect to JTAG on TI/FC development boards, both D-Sample and FCDEV3B, gaining the power of Free Software instead of proprietary tools. For the details, please refer to the freecalypso-hwlab repository.