Skip to content

ArduJtag is a lightweight and easy-to-use library for interfacing with JTAG devices using Arduino boards.

License

Notifications You must be signed in to change notification settings

Zamuhrishka/ArduJTAG

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build with PlatformIO

ArduJtag: Simple Library for Working with JTAG

ArduJtag is a lightweight and easy-to-use library for interfacing with JTAG devices using Arduino boards. This library provides a way to communicate with JTAG compatible devices. It is based on the JTAGduino project and was developed during the work on the Diving into JTAG protocol article and used to study this protocol

Features

  • Control JTAG pins (TCK, TMS, TDI, TDO) directly from your Arduino
  • Simple API for sending and receiving data
  • Support for JTAG sequences and operations
  • Configurable communication speed

Install

  • Clone this repository into Arduino/Libraries or use the built-in Arduino IDE Library manager to install a copy of this library.

  • Include in your sketch

#include "Jtag.hpp"

Install Using PlatformIO

Install ArduJtag using the platformio library manager in your editor, or using the PlatformIO Core CLI, or by adding it to your platformio.ini as shown below:

[env]
lib_deps =
    ArduJtag
[env]
lib_deps =
    https://github.com/Zamuhrishka/ArduJtag.git

Usage

To demonstrate the use of this library, I will show how to interact with the STM32F407 microcontroller via the JTAG interface. This microcontroller contains 2 TAP modules connected in series: BoundaryScan and Debug:

STM32F407TAP

The size of the IR register for the BoundaryScan TAP is 5 bits. For the Debug TAP, it is 4 bits.

Write into IR register

For writing into the IR register, the following function is used:

  /**
   * \brief Send an instruction through the JTAG IR (Instruction Register)
   *
   * \param instruction The instruction code to be sent
   * \param length The length of the instruction in bits
   */
  void ir(uint16_t instruction, uint16_t length);

Let's look at what arguments need to be passed to this function to set the BYPASS instruction in the BoundaryScan TAP, and the IDCODE instruction in the Debug TAP. Considering the arrangement of the BoundaryScan TAP and Debug TAP in the scan chain: BoundaryScan TAP is first - Debug TAP is second, and the fact that in JTAG data is transmitted least significant bit first, it turns out that for our purpose we need to write in the IR BoundaryScan TAP the value 0x1F (0b11111), and in the IR Debug TAP - 0x0E (0b1110). As a result, the bit sequence that needs to be set on the TDI line looks like this (remembering that in JTAG data is transmitted least significant bit first):

TDI: 011111111

The values of the arguments:

  uint16_t instruction = 0;
  uint16_t length = 0;
  ir(instruction = 0x1FE, length = 9);

Write into DR register

For writing into DR register the next function used:

  /**
   * \brief Send data through the JTAG DR (Data Register)
   *
   * \param data Pointer to the data array to be sent
   * \param length The length of the data in bits
   * \param output Pointer to the buffer where the response will be stored
   */
  void dr(uint8_t *input, uint32_t length, uint8_t *output);

The formation of the input buffer occurs as follows, suppose you need to send the following bit sequence:

1

Then the input array should look like this:

2

The same transformation applies to the output array.

Let's consider a more specific example. Suppose it is necessary to send the following bit sequence into the DR register:

3

Then the input array should look like this:

4

  uint8_t input = {0x02, 0x00, 0x40, 0x01};
  uint8_t length = 0;
  uint8_t input = {0x00, 0x00, 0x00, 0x00};

  void dr(input, length = 27, output);

Forming Arbitrary Bit Sequences

To form an arbitrary JTAG packet, the following function is intended:

/**
   * \brief Perform a sequence of JTAG operations (a series of bit manipulations on TMS and TDI
   *        reading TDO)
   *
   * \param n Number of operations in the sequence
   * \param tms Array of TMS values for the sequence
   * \param tdi Array of TDI values for the sequence
   * \param tdo Pointer to the array where TDO values will be stored
   * \return JTAG::ERROR Status of the sequence operation
   */
  JTAG::ERROR sequence(size_t n, const uint8_t tms[], const uint8_t tdi[], uint8_t *tdo);

The principle of forming arrays tms, tdi, tdo is exactly the same as for the input and output arrays described in the previous section.

More examples of using this library can be found in examples.

Contributing

Bug reports and/or pull requests are welcome.

Disclaimer

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

About

ArduJtag is a lightweight and easy-to-use library for interfacing with JTAG devices using Arduino boards.

Topics

Resources

License

Stars

Watchers

Forks

Languages