Advanced Computer Systems: Embedded Systems - JTAG implementation for LPC2148

Professor: Sivan Toledo

Students: Rony Bershadsky & Nimrod Talmon

Project description

We have an LPC2148 board, called the debugger.
We have an extension board, that is connected to the debugger through it's GPIO's.
On the other side, the extension board is connected through a cable into another LPC2148 board.
The second board, called the target, is controlled via JTAG (through the extension board) by the debugger.
We wrote an example program for the target, and code for the debugger to send JTAG commands to the target.
We are able to get the IDCODE of the target,
to stop and resume the target's core at any PC needed,
to push instructions to the target's CPU,
and to read the target's registers and memory.


The source code of the project is in src.
The debugger program is a command line terminal which let's you do various operations.
halt -> show cpu info -> resume: This stops the target's CPU, print the registers' values and several commands in the area of the PC
(PC - 12, PC - 8, PC - 4, PC, PC + 4, PC + 8, PC + 12) to be exact.
Other than that, there are 3 more sub menus, sorted by their implementation (low level JTAG, ARM core, and ICE):
JTAG: In this sub menu, you can get the target's IDCODE, test the JTAG's bypass (what left on the bus, with 1 clock delay,
change JTAG chain (1 or 2), read 32 bits from the data register (DR), and restart the JTAG state machine.
ICE: In this sub menu, you can halt the target's CPU, and see the contents of the status register and the control register,
and print the contents of the watchpoint 0 registers and watchpoint 1 register.
ARM: In this sub menu, you can get the registers' contents of the CPU, write a magic number into a register and see the result,
resume the target's core, and show the registers' content from the time you halted the CPU.

Note that you must halt the target before using most of the debugging options.

Technical overview

We use 4 GPIO pins on the debugger to connect via the extension board to the target's JTAG pins.
p0.4 controls the JTAG clock (TCK)
p0.5 controls the JTAG output (TDO)
p0.6 controls the JTAG input (TDI)
p0.28 controls the JTAG mode select (TMS)
p0.29 controls the JTAG voltage referenace (VREF)
VREF is used for the debugger to sense when a target is being connected to it.

We use UART to communicate via a terminal with the debugger.
On program's start, the debugger waits until a target is being connected to it, and then starts the terminal commands interpreter.

To talk with ICE, we change to scan chain 2, and talk directly to ICE.
ICE has several registers, including watchpoint registers, which are used also to halt the target's core (just put a breakpoint on every instruction.

To read the CPU's registers and write values to them, we change to scan chain 1, where we can send instructions for the CPU.
This is also the way we can read and write to the memory, and also resume the target, by computing the wanted PC and pushing a branch instruction.


The source code of the project is in src.
It is an open source code (beerware).

The lpc2000/ subdirectory has some headers for the board.
The files makefile, makefile.local, startup.S, lpc2148-flash.ld are used to burn programs to the boards.
The files print.c, uart0.c, systick.c are used as a library for synchronization and UART communication.

jtag_main.c: This is the main file. it has also the implementation of the main menu command line interface.
cmd_jtag.c: This is the implementation of the jtag menu command line interface.
cmd_arm.c: This is the implementation of the arm menu command line interface.
cmd_ice.c: This is the implementation of the ice menu command line interface.
jtag.c: This is the low level jtag implementation.
arm.c: This is the arm core implementation (scan chain 1).
ice.c: This is the ice implementation (scan chain 2).

The target/ subdirectory has one file, running_led.c which is loaded to the target for testing purposes.
This program starts with flashing LED12 on the board for three times, and then flash LED7 to LED13 one at a time.

The JTAG debugger in action