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 


ESP32 C++ std::thread tutorial

C++ threads std::thread in ESP-IDF is implemented on top of ESP-pthread component 

The C++ threads created using the standard thread class constructor actually use the under the hood ESP-pthread. On the other hand ESP-pthread is actually using FreeRtos Task 



Now we will go through this example of esp-idf Example to use pthread in esp32 https://github.com/espressif/esp-idf/tree/master/examples/system/cpp_pthread 

The example is written in C++ 


The esp pthread configuration structure looks like 

/** pthread configuration structure that influences pthread creation */
typedef struct {
    size_t stack_size;  ///< The stack size of the pthread
    size_t prio;        ///< The thread's priority
    bool inherit_cfg;   ///< Inherit this configuration further
    const char* thread_name;  ///< The thread name.
    int pin_to_core;    ///< The core id to pin the thread to. Has the same value range as xCoreId argument of xTaskCreatePinnedToCore.
} esp_pthread_cfg_t;


To create a std::thread type thread a esp_pthread configuration is needed 

// Create a thread using default values that can run on any core
auto cfg = esp_pthread_get_default_config();

esp_pthread_set_cfg(&cfg);


auto keyword in C++ 

The auto keyword specifies that the type of the variable that is being declared will be automatically deducted from its initializer . it is available from C++ 11


Here I am explaining the code by going through the debug messages after running the program. 


The example first creates a thread that can run at any core 

std::thread any_core(thread_func_any_core);

I (399) pthread: This thread (with the default name) may run on any core.Core id: 0, prio: 5, minimum free stack: 2124 bytes.


Then it creates a thread to be run on core 0 . this thread’s inherit_cfg is set to true . 

std::thread thread_1(spawn_another_thread);

I (409) Thread 1: Core id: 0, prio: 5, minimum free stack: 2144 bytes.


this thread in turn creates another thread which inherits the same configuration of the thread which created it 

std::thread inherits(thread_func_inherited);

I (419) Thread 1: This is the INHERITING thread with the same parameters as our parent, including name. Core id: 0, prio: 5, minimum free stack: 2172 bytes.


Then a thread is created to be run on core 1 only 

std::thread thread_2(thread_func);

I (439) Thread 2: Core id: 1, prio: 5, minimum free stack: 2160 bytes.


The main() of the app has an infinite loop that prints some information. This infinite loop itself is a thread too 

I (429) main: core id: 0, prio: 1, minimum free stack: 3084 bytes.


All the threads sleeps for 5 second 


The example uses stringstream type object to construct debug messages. the constructed message is printed via the ESP_LOGI() function 


Summary 

The C++ std::thread is a popular way to design multithreaded applications. Application developers are more familiar with this API than FreeRTOS API . So it’s a great decision by espressif to port std::thread for ESP32 . Application developers can port C++ std::thread based applications to ESP32 architecture easily. Also if you want to design a C++ based application with thread functionality this is a good design pattern 


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.