ESP32 JTAG debugging Setup Using JLink

After Flashing firmware to a microcontroller we normally test & debug the behavior of the application using either an oscilloscope, logic analyzer, or seeing and probing everything manually. Another popular mechanism is to connect a USB UART module to a dedicated UART peripheral and see everything on the PC side using Serial Terminal Software. 

But ...
- What if we need to deep dive and see what is happening inside the processor? 
- What if we want to debug through breakpoints set at source code and navigate through the code just like a Regular Software Engineer Does? 

If your answer is yes then this post might be helpful. 

Microcontrollers are resource-constrained small computers and debugging at the CPU level is not so common . over the years' semiconductor manufacturers have jointly developed a protocol named JTAG to establish a common standard that we all can follow to debug these tiny computers. Not all the mcus in the market have the JTAG stack embedded inside the silicon but nowadays it has become more mainstream. We will first discuss the common concepts behind JTAG and then look into how we can set up everything. Our Target platform will be ESP32. 

JTAG stands for Joint Test Action Group 

The CPU inside an MCU is equipped with an On-Chip Debug Module. This on-chip debug module understands JTAG protocol and can communicate with the CPU under the rules set by JTAG specification. For example, our target MCU ESP32 has an on-chip debug module. 



Then this on-chip debug module is routed to JTAG pins which are exposed at the external side of an MCU. The naming convention and behavior of these pins are as per the JTAG standard.



JTAG specification allows us to 
  • Program the microcontroller 
  • Halt the CPU
  • inspect Microcontroller Registers and memory 
  • Define breakpoints 
  • Allows single stepping through the code 
  • Allows sending debug string messages [ e.g. ARM CPU has ITM (instrumentation trace macro-cell) ] 
  • Tracing 
Client and Server Model 

From a high-level point of view, there are 2 entities: At one end we have the microcontroller and at the other end we have our development machine ready to debug the target MCU. We need to visualize The Host side PC as a client and the microcontroller as a server. 


Required Tools 

By this time we have well understood the system-level topologies, now let's look into what kind of software we need. We will be using GDB ( GNU Debugger ) as our debugger software.  

GDB has a GDBClient program for almost Every kind of CPU architecture. During the installation of ESP-IDF, it got automatically installed in our system. 

At the microcontroller end, The on-chip-debug module itself will not act as a server, we would need 2 more components in between. one is a hardware component named JTAG-Adapter and another one is a software component named OpenOCD. Have a look at the following diagram to understand the whole idea 

The OpenOCD got also installed during esp-idf setup. you can look into my previous blog post on setting up ESP-IDF SDK setup from here ESP-IDF setup in Ubuntu

J-Link by Segger Embedded is a very common & popular JTAG adapter. we will use it in our setup. 

JLink & ESP32 JTAG connection

A JTAG Port has a fixed set of PIN allotments. There are a couple of variants, of them we will follow the 20-pin option 

Connect your ESP32 to the JLINK as per the following table 

JLink

ESP32

VTref

3.3V

nTRST

EN

TDI

GPIO12

TMS

GPIO14

TCK

GPIO13

RTCK

GND

TDO

GPIO15

Pin No 4 [GND] 

GND


My Connection Setup Looked like this 

I followed the following link 

You may get more help on the connection from this link ESP32-to-JTAG-connection

Now Plugin JLink to your USB port

JLink Driver Installation

I assume that you have not installed JLink Before so let's install the driver for our ubuntu host

First Download jlink deb format installer from J-LinkSoftwareAndDocumentationPack

it will get downloaded to your Downloads folder, so CD into it and use dpkg to install 

~/Downloads$ sudo dpkg -i JLink_Linux_V650b_x86_64.deb 

(Reading database ... 206817 files and directories currently installed.)
Preparing to unpack JLink_Linux_V650b_x86_64.deb ...
Removing /opt/SEGGER/JLink ...
Unpacking jlink (6.502) over (6.502) ...
Setting up jlink (6.502) ...


Check JLink Rules 


~$ ls /etc/udev/rules.d/


60-vboxdrv.rules                   70-snap.electronic-wechat.rules
70-snap.canonical-livepatch.rules  99-jlink.rules
70-snap.core.rules                 99-USBAsp.rules


If Jlink rules are automatically added like above then JLink is installed properly.

Now connect your ESP32 devkit to host over USB


Program ESP32 over JTAG & OpenOCD


The focus of this post is to debug ESP32 via JTAG but we can also Program the microcontroller via JTAG port. When we setup ESP-IDF first we got many examples as part of the SDK. we will program the usual Blink example application. 


CD into the project and load esp-idf environment 


~/esp/esp-idf/examples/get-started/blink$ . ~/esp/esp-idf/export.sh 


This will load esp-idf compiler toolchains and openocd executables in our shell environment 


Check JTAG connection with ESP32 via OpenOCD


Then run the following command to test jLink Connection to ESP32 


~/esp/esp-idf/examples/get-started/blink$ openocd -f interface/jlink.cfg -f board/esp-wroom-32.cfg


Open On-Chip Debugger  v0.10.0-esp32-20190708 (2019-07-08-11:03)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 20000 kHz
Info : Configured 2 cores
esp32 interrupt mask on
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V9 compiled Jun  2 2222 22:22:22
Info : Hardware version: 9.40
Info : VTarget = 3.291 V
Info : Reduced speed from 20000 kHz to 15000 kHz (maximum).
Info : Reduced speed from 20000 kHz to 15000 kHz (maximum).
Info : clock speed 20000 kHz
Info : JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : esp32: Debug controller 0 was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32: Core 0 was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32: Debug controller 1 was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32: Core 1 was reset (pwrstat=0x5F, after clear 0x0F).
Info : Listening on port 3333 for gdb connections


If you get an output like the above then connections are okay and openocd has been able to communicate with the on-chip debug module of esp32

Program ESP32 using JLink

You can also program the application binary over JTAG connection, we will build and program the simple “blink” example application. 


Build the program first using idf.py 


~/esp/esp-idf/examples/get-started/blink$ idf.py build 


Now program it 


~/esp/esp-idf/examples/get-started/blink$ openocd -f interface/jlink.cfg -f board/esp-wroom-32.cfg -c "program_esp32 build/blink.bin 0x10000 verify reset exit" 


Here the ideal 0x10000 address was set


If the setup is okay then you will see output like this 


** Programming Started **
auto erase enabled
Info : Target halted. PRO_CPU: PC=0x400916EE (active)    APP_CPU: PC=0x40000400
Info : Flash mapping 0: 0x10020 -> 0x3f400020, 24 KB
Info : Flash mapping 1: 0x20018 -> 0x400d0018, 74 KB
Info : Target halted. PRO_CPU: PC=0x400916EE (active)    APP_CPU: PC=0x40000400
Info : Auto-detected flash size 4096 KB
Info : Using flash size 4096 KB
Info : Target halted. PRO_CPU: PC=0x400916EE (active)    APP_CPU: PC=0x40000400
Info : Target halted. PRO_CPU: PC=0x400916EE (active)    APP_CPU: PC=0x40000400
wrote 151552 bytes from file build/blink.bin in 5.383243s (27.493 KiB/s)
** Programming Finished **
** Verify Started **
Info : Target halted. PRO_CPU: PC=0x400916EE (active)    APP_CPU: PC=0x40000400
read 148384 bytes from file build/blink.bin and flash bank 0 at offset 0x00010000 in 2.188784s (66.204 KiB/s)
contents match
** Verified OK **
** Resetting Target **


Now you will see that the board’s default LED(connected to GPIO2) is blinking 



JTAG Debugging

Now that we have programmed esp32 via JTAG , we can now move into the actual debugging process that we have been craving for since the start of the process

you have already seen that ESP-IDF has GDB client executable xtensa-esp32-elf-gdb in place. In this post, we will go through a simple usage of GDB. We will Halt the processor at a breakpoint.

Let's First Create a file named "gdbinit"

~/esp/esp-idf/examples/get-started/blink$ cat > gdbinit


put the following content

target remote :3333
set remote hardware-watchpoint-limit 2
mon reset halt
flushregs
thb app_main
c


Here thb app_main line sets a breakpoint at app_main() function

Now you have to open 2 terminals 

Both the terminal should have esp-idf environment exported, 


Let’s open a new terminal [CTRL + T] 

~/esp/esp-idf/examples/get-started/blink$ . /home/ayx/esp/esp-idf/export.sh


Now in this terminal we will connect to ESP32 over JTAG and start the ESP32’s GDB server . 


~/esp/esp-idf/examples/get-started/blink$ openocd -f interface/jlink.cfg -f board/esp-wroom-32.cfg


Open On-Chip Debugger  v0.10.0-esp32-20190708 (2019-07-08-11:03)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 20000 kHz
Info : Configured 2 cores
esp32 interrupt mask on
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V9 compiled Jun  2 2222 22:22:22
Info : Hardware version: 9.40
Info : VTarget = 3.280 V
Info : Reduced speed from 20000 kHz to 15000 kHz (maximum).
Info : Reduced speed from 20000 kHz to 15000 kHz (maximum).
Info : clock speed 20000 kHz
Info : JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : Target halted. PRO_CPU: PC=0x400D399C (active)    APP_CPU: PC=0x400E2922
Info : Detected debug stubs @ 3ffb28f0 on core0 of target 'esp32'
Info : Listening on port 3333 for gdb connections


Here you can see that ESP32’s GDB server is listening on port 3333 for GDB connection 

This is the same command that we used for checking JTAG connection

Now keep this terminal alive and open another terminal [CTRL +T] 


Again export the environment 


~/esp/esp-idf/examples/get-started/blink$ . /home/ayx/esp/esp-idf/export.sh


Now we will use xtensa-esp32-elf-gdb use to connect to the ESP32 GDB server & debug our blink example code 


~/esp/esp-idf/example/get-started/blink$ xtensa-esp32-elf-gdb -x gdbinit build/blink.elf


You will see both the terminal’s output getting changed



As seen in the above picture you can see that The bottom terminal CPU is halted at a breakpoint 

As the processor is halted the blink should also stop.


There are gdb commands to step through the code, for example


" To execute one line of code, type "step" or "s". If the line to be executed is a function call, gdb will step into that function and start executing its code one line at a time. If you want to execute the entire function with one keypress, type "next" or "n" "


reference: gdb-quickstart


This concludes our JTAG Openocd and GDB setup. in a later post, I will show how we can make use of JTAG tracing and get us free from allocating a UART peripheral just for Debug purposes. Keeping debug log only available via JTAG makes the application more production friendly as one then does not need to disable uart based debugging before product release and face untested timing scenarios



1 comment:

Categories

Pages

Firmware Engineer

My photo
Works on Firmware, Embedded Linux, Smart Metering, RTOS, IoT backend

Contact Form

Name

Email *

Message *

Copyrighted by Hassin. Powered by Blogger.