2
\$\begingroup\$

Reading the Macraigor API for the usbWiggler

MacraigorApi_ JtagScanlO

BOOLEAN_TYPE MacraigorApi_JTAGScanIO(
                               char *shift_register,
                               unsigned_int length_in_bits,
                               MEMORY_BUFFER_TYPE *data_in_ptr,
                               MEMORY_BUFFER_TYPE *data_out_ptr)

Use JTAG to scan the stream of bits contained in *data_in_ptr array to the shift_register of the currently selected CPU and at the same time collect the bits arriving from the CPU in *data_out_ptr array, leaving the CPU in "RunTestidle" state at the end of the operation Returns TRUE if command completed successfully

shift_register ["IR"/"DR"] - destination shift register (IR= JTAG Instruction register, DR= JTAG Data Register

length_in_bits [1 - ... ] number of bits to shift in/out of the CPU

data_in_ptr pointer to array containing the bits to be shifted into the CPU, in the format [8,7,6,5,4,3,2,1,0] [15,14,13,12,11,10,9,8] ... where at the end of the scan operation bit O will be the bit closest to SDO and bit N will be the bit closest to SDI

data_out_ptr pointer to array containing bit scanned in from CPU in the same format as data_in_ptr, where bit byte Obit O contains the first bit scanned in from the CPU

I'm not sure I understand this description clearly. So playing with the C++ code and Cortex M3 I did this:

int scanBits = 0x292;
unsigned char data_in[256];
unsigned char *data_in_ptr = &data_in[0];
unsigned char data_out[256];
unsigned char *data_out_ptr = &data_out[0];
MacraigorApi_JTAGScanIO("DR",
                        scanBits, 
                        (MEMORY_BUFFER_TYPE *)data_in_ptr,
                        (MEMORY_BUFFER_TYPE *)data_out_ptr);

And the data_out_ptr showed me a result like this:

1110010001001111111111111111111111111111111001001101001010101010011001
0010110000000000000000000000000000000000000000001100011111110100110111
1110111111011111101111000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000100110000010001001111101010100
0010000110000000100000010001001110001001000000001000000100010011111101
1100011100000000000011000111111101000110000000000000110001111111010011
1100000000000000000000000000000000001000000001000000100010101001010100
0000000000001100011111110011011100000000010000101010101011100001111111
0000000000100000000101100011000010100000000001100011111110011001100000
000000000000000000000000000000000000000000101000100111110010000

Can someone explain to me in simpler words what this API description mean? I'm new to this field so a lot of the jargon here is not as clear to me.

Also I'm kind of confused on this, How can I, from this stream of bits, get what data was on a X address?

\$\endgroup\$
  • 2
    \$\begingroup\$ Which CPU are you writing to the JTAG of? That will determine the legal IR states, where you will be able to make more sense of the DR scans. \$\endgroup\$ – Sean Houlihane Sep 2 '16 at 16:24
  • \$\begingroup\$ @SeanHoulihane Cortex M3 \$\endgroup\$ – M. A. Kishawy Sep 2 '16 at 16:24
2
\$\begingroup\$

The Cortex M3 will almost always be implemented with a CoreSight DAP providing the eternal debug port. Simplistically, you use the JTAG to set control registers in the DAP, and the DAP performs memory mapped accesses into the SoC to implement your requests.

The IR values are documented in the CoreSight Component TRM. This is effectively the first level of addressing. DP accesses allow you to set the AP select register. AP accesses allow you to set the transfer address register, and perform reads and writes.

Bear in mind that for a read, you need to request the read, then issue another transaction to retrieve the result - the on-chip accesses are asynchronous to the JTAG transaction. You would then see APACC-address, APACC-read, APACC-result for a single 32 bit memory transaction.

At the API level, you might want to add a level of abstraction. Switching between the CoreSight APACC and DPACC requires shifting a 6 bit string into the instruction register, but once the DP registers are initialised, most transactions only need to use the APACC instruction register state with a 35 bit payload.

Your stream of APACC transactions will use data bits [1:0] as an address to the AP registers, bit2 as read/write, and [35:3] as the payload.

One of the DPACC transactions (selected by the first 2 DR bit values as an address) is a static ID register, you should make sure this doing what you expect before trying to do anything more complex.

This overview white paper has a slightly more verbose description of the debug connections (from page 8).

DP    //Debug port (JTAG or Serial wire, external interface)   
AP    //Access Port (APB in this case, on-chip bus master)   
DPACC //JTAG state, transactions are handled by the DP (r/w with 2 bit address)   
APACC //JTAG state, transactions are handled by the AP (r/w with 2 bit address)
\$\endgroup\$
  • \$\begingroup\$ Thanks. I'm trying to make sense of what you are saying by first understanding all these abbreviation you introduced me to. Google is not as friendly when it comes to finding the meaning for these techy abbreviations. Also I'm trying to connect this to the code I'm trying to write/edit. Any idea how would what you said translate into code with Macraigor API. \$\endgroup\$ – M. A. Kishawy Sep 2 '16 at 17:43
  • 1
    \$\begingroup\$ Added a bit more detail, the two docs I linked ought to provide some technical background. \$\endgroup\$ – Sean Houlihane Sep 2 '16 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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