world leader in high performance signal processing
Trace: » comm

JTAG Communications

Many developers are now creating systems with applications developed using the GNU toolchain.

The GNU toolchain traditional design flow has the GDB debugger connecting to a GDB stub/server through an additional communications channel, such as the serial or Ethernet port. Since today's products are cost sensitive, and performance critical, they can not add the extra cost of the communications channel (serial or Ethernet), nor the run time overhead of running the GDB stub/server on the target processor.

This describes using an In Circuit Emulator (like the ones listed here) plus the existing JTAG connection as the transport channel replacing the functionality of traditional communications channels (both reducing both board cost and processor overhead).

Many commercial products include some type of support for exchange data between the host development system and target application without halting the processor. Analog Device's VDSP++ calls it Background Telemetry Channel (BTC). ARM calls it Debug Communications Channel (DCC). Since we are not very good at coming up with shiny new names, and have a much simpler use model, and protocol on the JTAG interface than either BTC or DCC - we are calling the GNU toolchain implementation JTAG Communications. At a high level, it is all the same thing.

This mechanism provides real-time visibility into a running program, exchanging data between a host and a target application, with minimal intrusion on the target system’s “real-time” characteristics and minimal addition on a user’s development and debugging time. JTAG Comm enables real-time data collection and status messaging, eliminating the overhead involved with halting the target application, getting the desired information, and then restarting the target application. Historical start/stop debugging can be impossible in many real time applications. While a mechanism like JTAG Communications has the advantage of not stopping the target processor, it does suffer the drawback of requiring target resident code, and consuming a very small amount of memory and performance.

Uses for a JTAG Comms include:

  • Monitoring program status without halting the processor
  • Viewing algorithm output in real time
  • Injecting data into a program
  • Streaming real-time data to a file (data logging)
  • Providing I/O (eg: printf, scanf), either standard or user-defined

The JTAG Comm consists of a register (EMUDAT and EMUSTAT) that are shared by the core processor, and the JTAG scan chain. The application/firmware developer dictates during the coding phase what information and how often it appears in those registers. To communicate with a development host, the target application must read/write the JTAG communications data register. By selecting where and how many times an application reads/writes this register, you control to what degree the real-time analysis impacts the actual target program, and the overall JTAG communications bandwidth.

Low Level Details

The low level details are about how the hardware works, and describes things in a little more details than what can be found in any of the existing processor documentation. This section may only be interesting to people trying to write their own host based JTAG software.

Since the JTAG communications is the same register being tied to both the core and the JTAG scan chain, it is easier to describe both sides independently and then how they are tied together.

Since the JTAG side of the communications interface can be updating the EMUDAT scan chain at the same time the processor core is read or writing the EMUDAT system register, to allow full-duplex data transfers, the EMUDAT register is a special register inside the processor, which consists of two 32-bit registers, one for reading (EMUDAT_IN) and one for writing (EMUDAT_OUT), that map to the same register name (EMUDAT) and share the same JTAG scan chain, (EMUDAT_SCAN). It is special in the fact that reads will not return the most recently written information.

Although we described the communication channel as full duplex, with low overhead, since reading/writing data on the processor and JTAG is asynchronous and either can update things at any time, care must be taken so none of the following occurs:

  1. data over-writes (write data into the register before the other side reads it out),
  2. misinterpret “valid/new” data as “invalid/old data” (and throw it away)
  3. misinterpret “invalid/old” data as “valid/new data” (and uses the same value twice)
  4. or locks things up (either the target or host doesn't read, and the other side's buffers explode)

This is only possible when following the recommendations described below.

Processor core side

Hardware description

EMUDAT is a system register, and falls into the same group of ASTAT, SEQSTAT, SYSCFG, RETI, RETX, RETN, RETE, or RETS, LC[1:0], LT[1:0], LB[1:0], CYCLES, and CYCLES2. Specifically, it can only be used with certain register move instructions:

  • Dreg = EMUDAT ; /* EMUDAT to 32-bit D-register */
  • Preg = EMUDAT ; /* EMUDAT to P-register */
  • EMUDAT = Dreg ; /* 32-bit D-register to EMUDAT */
  • EMUDAT = Preg ; /* 32-bit P-register to EMUDAT */
  • EMUDAT = USP ; /* EMUDAT to Userspace stack pointer */
  • [--SP] = EMUDAT ; /* Push EMUDAT to the stack */
  • EMUDAT = [SP++] ; /* Pop EMUDAT from the stack */

As described above, stores (writes) from the processor core to the EMUDAT register are written to the EMUDAT_OUT version of the register. Loads from the EMUDAT register to a different processor registers or memory are read from EMUDAT_IN.

Since the JTAG side of the channel must pull data from the EMUDAT_OUT register, there is a possibility of overwriting existing data before the JTAG ICE has shifted the data out. To fix this issue, there is a status bit EMUDOF, which indicates when this data has been shifted out properly. There is also a status bit on the EMUDAT_IN side, which indicates when new data in in the register the process has not seen yet.

Status bits EMUDOF and EMUDIF indicate whether EMUDAT_OUT and EMUDAT_IN are full (contain valid/new data), respectively:

  • EMUDOF is set by a store to the EMUDAT register by the processor. It is cleared by a JTAG transaction on the EMUDAT_SCAN scan chain.
  • EMUDIF is set by a JTAG transaction on the EMUDAT_SCAN scan chain. It is cleared by a load from the EMUDAT register by the target.

These bits are part of the DBGSTAT register and are duplicated in the JTAG EMUDAT_SCAN scan chain to speed up the data upload/download process. For further details of the DBGSTAT register, refer to the Emulation Chapter

Software Description

On the processor, there is a read operation (check and accept data from JTAG), and a write operation (send data to JTAG) that can operate independently from each other. Unfortunately, there is no interrupt associated with either the EMUDIF or EMUDOF status bits, so polling/looping must be done.

Read operation

Periodically (based on timer, interrupt, or polling in main loop), read the DBGSTAT register and check the EMUDIF bit - This will only be set if the data has been transferred into the EMUDAT_IN register by the JTAG scan chain. Software can then determine if data is valid, and needs to be read out. If it is valid, we read it (which clears the EMUDIF bit), and pass it to the appropriate software layer (depending on what the specific system wants to do). If it is not valid - we don't care and return.

Error checking should also check the EMUDIOVF (EMUDAT_IN Overflow) which notes if a JTAG transaction was performed to EMUDAT_IN while EMUDIF = 1. Although it is always good form to do this, normally this is left out of a system, and need only be checked during JTAG communication development.

Write operation

When the processor has data to send, it checks the EMUDOF status bit (to see if valid data in the EMUDAT_OUT register has not been pulled out by the JTAG yet). If it is full, we spin on that bit. When it eventually is transfered out by JTAG, the bit will be clear, and we can write the valid data to the EMUDAT register (which will set the EMUDOF bit).

Error checking should also check the EMUDOOVF (EMUDAT_OUT Overflow) which notes that a processor store was performed to the EMUDAT register while valid data had not been shifted out of the EMUDAT_SCAN chain, or EMUDOF = 1). Although it is always good form to do this, normally it is left out of a system, and need only be checked during JTAG communication development.

JTAG side

Hardware Description

The EMUDAT_SCAN JTAG chain can be configured as a 32-, 40- or 48-bit register. When configured for the longer 40- and 48-bit lengths, besides the 32-bit data that it carries from/to the 32-bit EMUDAT registers, it also sends the EMUDIF and EMUDOF status bits. In this way the JTAG engine can determine when it is safe to write into the EMUDAT register (when EMUDIF is clear).

On the input side, the EMUDIF bit location serves as a control bit. (The EMUDOF bit position is a “don't care”). This control bit is a write enable for the EMUDAT_SCAN chain to write the EMUDAT_IN register on an JTAG transaction. 1 enables the write, 0 disables the write. When a write does not happen (bit is set to 0), neither the EMUDAT_IN register or the EMUDIF status bit will be effected. In this way, “dummy” JTAG transactions can be done to read the data in the EMUDAT_OUT register and read the status bits without effecting the data in the EMUDAT_IN register, which may not have been read from the processor yet.

When configured as a 32-bit register

Register

When configured as a 40-bit register:

Register

When configured as a 48-bit register:

Register

Software Description

On the JTAG scan chain side, things are much more complicated - since read/write transactions are completed as a single operation.

The sequence is to:

  1. configure the EMUDAT_SCAN as 40 bits (so that it includes the EMUDOF and EMUDIF status bits on the output and the EMUDIF control bit on the input)
  2. normally the host sets the EMUDIF control bit to 0 (disabling the update of the EMUDAT_IN register from the EMUDAT_SCAN chain) -- this way we can read EMUDAT_OUT and the status bits without effecting the EMUDAT_IN register.
  3. only when the host has something to write into the EMUDAT, and the previous transaction EMUDIF status bit read was zero, should the host set the EMUDIF control bit to 1.
  4. If the JTAG scan chain is sending a buffer to the processor, it must do a dummy write transaction to ensure that the last transaction has been emptied from EMUDAT_IN by the processor. This dummy write does do an effective read of EMUDAT_OUT, effectively providing 2x the bandwidth on communication from the processor to the JTAG based system than from the JTAG to the processor.

Using this scheme allows the host JTAG to read the EMUDAT_SCAN chain as fast as possible (valid output will have the EMUDOF status bit set, invalid/old data will not have this bit set, and can be discarded).

Tying the processor and JTAG together

Before reading through the details of this, it is assumed that the reader understands the basics of JTAG, and understands how the scan chain works. If you do not know what shift_dr and capture_dr and update_dr JTAG scan states are, you should read over the JTAG logic section.

As discussed in the previous sections, the act of:

  • a core read of the EMUDAT register (any of the following instruction types: Dreg = EMUDAT ;, Preg = EMUDAT ;, or [--SP] = EMUDAT ;) causes the following:
    • if set the EMUDIF status bit is cleared
    • the previous value in EMUDAT_IN from the last valid JTAG transaction will be stored in the register, or in memory.
  • a core write of the EMUDAT register (any of the following instruction types: EMUDAT = Dreg ;, EMUDAT = Preg ;, EMUDAT = USP ; , or EMUDAT = [SP++] ;) causes the following actions:
    • if clear the EMUDOF status bit is set
    • if the EMUDOF status bit is set, the EMUDIOVF status bit is set.
    • the value is written into the EMUDAT_OUT register for the next JTAG transaction
  • JTAG transaction, follows the basic flow from the JTAG state diagram. When the EMUDAT_SCAN scan chain is selected, the following states will cause various events to happen:
    • capture_dr: clears the EMUDOF status bit, and moves the data from EMUDAT_OUT to the EMUDAT_SCAN scan chain.
    • shift_dr : shifts the EMUDAT_OUT data to the TDO pin, and shifts the data from the TDI pin into the EMUDAT_SCAN scan chain.
    • update_dr:
      • if the EMUDIF control bit is set,
        1. updates the value of EMUDAT_IN from the EMUDAT_SCAN chain
        2. if the EMUDIF status bit is clear, sets the EMUDIF status bit
        3. if the EMIDIF status bit is set, sets the EMUDIOVF status bit
      • if the EMUDIF control but is clear - nothing happens.

High level Details

The communications scheme that best suites JTAG would appear to be a serial device, like a UART with flow control (there is no way to loose characters in either direction, if you are using the provided interfaces). You have a register that has a status bit that says when it is safe to write to (sending information) and a register that has a status bit that says when new valid data is ready to read. This provides a simple read/write interface from the Blackfin processor side.

Although the functions count everything in bytes (8-bits), the native transfer size of the JTAG communications channel is double words (32-bits). Some efficiency can be gained by only using modulo 4 byte buffers.

JTAG Details

The protocol that goes over JTAG must be the same on both the processor side, and the JTAG (host development system) side. Thus the lowest level of communications should just be as raw as possible, while allowing for as high efficiency as possible.

The actual JTAG protocol is kept simple - the expectation is that a existing protocol stack (ppp, kermit, etc) will be sitting on either end to accomplish the specific goal that a higher level may accomplish. The protocol as being a simple string data structure (as may be used in various languages):

 [32 bit length in bytes] [buffer data]

 struct { uint32_t length; unsigned char *buffer; };

All race/locking issues have all been handled in both the gdbproxy/processor code, so as long as JTAG is attached, and the data has somewhere to go, things should be fine using the public interfaces.

Processor Details

On the Blackfin processor, there are two basic functions, read and write, which both take two parameters, a buffer location, and a count. This low level read and write function can be bolted together to make any type of host protocol (complex or easy) you would like.

read interface

SYNOPSIS
#include <bfjc.h>


ssize_t read_jc(void *buf, size_t count, size_t max_attempts);
DESCRIPTION

read_jc() attempts to read up to count bytes from the JTAG communications channel into the buffer starting at buf. The read function polls the EMUDIF status bit max_attempts before it returns. A max_attempts value of 0 means forever. By using max_attempts, the application developer can control the overhead of JTAG communications.

The function returns on either count bytes being received, max_attempts being exceeded, or an error.

If count is zero, read_jc() returns zero and has no other results. If count is greater than SSIZE_MAX, the result is unspecified.

RETURN VALUE

On success, the number of bytes read is returned. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because JTAG is slower than the processor), or because read_jc() was interrupted by a signal. If the JTAG unit never sent any data, and the read_jc() function timed outs, 0 will be returned. On error, -1 is returned.

ERRORS

Error conditions can be one of:

  • either the start of buf or *buf + count is outside your accessible address space
  • An attempt was made to write a buffer that exceeds the implementation-defined maximum buffer size
  • A low-level I/O error occurred

write interface

SYNOPSIS
#include <bfjc.h>

ssize_t write_jc(const void *buf, size_t count, size_t max_attempts);
DESCRIPTION

write_jc() writes up to count bytes to the JTAG communications channel from the buffer starting at buf. The read function polls the EMUDOF status bit max_attempts before it returns. A max_attempts value of 0 means forever. By using max_attempts, the application developer can control the overhead of JTAG communications.

The function returns on either count bytes being sent, max_attempts being exceeded, or an error.

RETURN VALUE

On success, the number of bytes written are returned (zero indicates nothing was written). On error, -1 is returned. If count is zero, 0 will be returned without causing any other effect.

ERRORS

Error conditions can be one of:

  • either the start of buf or *buf + count is outside your accessible address space
  • an attempt was made to write a buffer that exceeds the implementation-defined maximum buffer size
  • a low-level I/O error occurred

Development Host Details

Things are exposed as a standard network port on gdbproxy, which you can telnet to, use netcat on, or kermit on, or really anything. For more details, check out the gdbproxy page.

Since the tool that you may use on your host depends highly on how this is connected on your target, you should check out some the of the examples we have done: