8/24/2021

ESP32 OpenOCD 설정 과 VS Code 설정

1. ESP32 OpenOCD 설정 

이전까지 내가 가지고 있던 OpenOCD는 FT2232 기반으로 다른 보드에서 각각 동작되는 것들을 리눅스에서 해왔지만, 
최근 Window 기반으로 이를 해결해야할 것 같아 관련자료들을 정리해본다.

ESP32 OpenOCD 관련내용 과 gdbgui 연결 
바로 이전 ESP32로 구성한 것이며, 반드시 참조 


JTAG과 OpenOCD 이해와 이전 Raspberry Pi 적용사항 (반드시 확인)
A. JTAG의 기본이해 와 OpenOCD관련내용
B. Raspberry PI OpenOCD 관련내용 과 VS Code/ VS Community 연결

OpenOCD User Guide 와 GDB Command
A. OpenOCD User Guide 반드시 확인 
B. OpenOCD에서 처음 gdb 직접연결하여 테스트 할 경우 각 gdb 명령어들 설명 


1.1 ESP Prog Board

기존에 내가 사용하던 FT2232H와 동일하며, 2개 포트를 하나는 Serial 는 다른 하나는 JTAG으로 사용한다.
세부내용은 이전의 FT2232관련 OpenOCD 참조 

https://github.com/espressif/esp-dev-kits/blob/master/docs/_static/esp-prog/block.png




  1. Interface 0 / A: JTAG
  2. interface 1 / B: UART

  • USB Serial Port 설정 
  1. 장치관리자->범용 직렬버스 컨트롤러
  2. USB Serial Converter B 선택 후 속성 
  3. 고급-> VCP 드라이버 설치 


속성에서 고급 과 Power Menagement 탭이 없다면, 다시시작한 후 다시 진행
USB Serial Converter B (Serial)이므로 VCP설정 



  • USB Serial Converter B기반의 Serial Port 설정완료 
  1. 포트-> USB Serial Port (COM6) 확인 후  USB Serial Convert B 연결확인 (Serial 용) 
  2. 포트-> USB Serial Port (COMx) 확인 후  USB Serial Convert A 있을 경우 삭제(JTAG 용)
  3. 포트-> USB Serial Port의 Port를 변경하고자 할 경우 포트설정이용
  4. 장치관리자->보기->숨겨진장치 표시 (설정되어진 Serial 포트 확인가능)
 


FTDI Driver가  반드시 상위 USB Serial Port로 잡혀야하며, 내 두번째 노트북에서는 Serial이 자꾸 Dual RS232 Serial로 잡혀서 동작이 전혀 안됨 
이부분을 아래 Tool 혹은 Driver를 변경하여 해결진행 

  • Window LibUSB 설정 (JTAG 설정)
Download
  1. Download 후 실행
  2. Option->List All Devices 선택 
  3. Dual RS232 HS Interface 0 선택
  4. FTDIBUS -> WinUSB로 변경 


  • USBDriverTool 
상위와 동일한 기능이며, OpenOCD 내부에도 동일한 Tool이 존재 
세부사용은 상위 Raspberry PI OpenOCD 관련내용 과 VS Code/ VS Community 연결 참조
이게 더 편한 것 같음 


1.2 ESP32 OpenOCD 설정 

상위 ESP-IDF를 설치를 진행했다면, esp tool 내에 openocd도 함께 들어있으며, VS Code에서도 쉽게 OpenOCD를 Start/Stop를 진행가능하다.

  1. View->Command Palette 실행 
  2. 창에서 ESP 치면 ESP 관련 Command들이 나오며 그중 OpenOCD 선택
  3. View->Output 선택 후 Output의 우측 메뉴에 "OpenOCD" 현재상태 확인가능   

하지만 나의 경우는 OpenOCD의 세부설정을 위해서 별도로 bat 파일을 만들어서 동작하도록 별도로 또 구성하였다. 


  • esp_openocd.bat
아래와 같이 별도의 TCL script 별도설정을 해주어 동작하며, 아래의 appimage_offset은 본인의 Partition Table에서 참고 
TITLE OpenOCD for ESP32 Prog 
rem Author: Jeonghun Lee
rem TEST OpenOCD
set SCR_PATH=%userprofile%\.espressif\tools\openocd-esp32\v0.10.0-esp32-20200709\openocd-esp32\share\openocd\scripts
set BIN_PATH=%userprofile%\.espressif\tools\openocd-esp32\v0.10.0-esp32-20200709\openocd-esp32\bin
set SET_ESP32_FLASH="init; halt; esp appimage_offset 0x50000"
set SET_ESP32_OS="set ESP32_RTOS \"FreeRTOS\" "
%BIN_PATH%\openocd.exe  -f  %SCR_PATH%\board\esp32-wrover-kit-3.3v.cfg -c %SET_ESP32_FLASH% -c %SET_ESP32_OS%

ESP32 OpenOCD의 관련설정 내용

  • SET_ESP32_FLASH 설정
esp32에서 내부 partition을 사용하고 있다면, 별도의 실행할 offset을 넣어 상위와 같이 설정 
재미있는것은 SPI ROM인데, profile 해보면 이 영역이 NOR Flash처럼 XIP(Execute In Place)도 되는 것으로 나온다. 
SW영역에서 그렇게 표시되어있는데, 이부분은 ESP 내부 Flash만 되는지 외부 Flash도 지원가능한지 반드시 추후에 확인 

현재 MTDI의 설정에 따라 내부 LDO로  FLASH 전원 3.3 or 1.8로 변경되며 관련설정은 별도가능 (ESP32_FLASH_VOLTAGE 값 참조)

ESP32 전용 내부변수들( 이를 이해하려면 아래내용들을 분석하면 쉽게이해)
상위 SET_ESP32_OS 에 설정을 별도로 했으며, 관련내용들 


1.3 ESP32 OpenOCD Configuration 분석 

상위에서 사용하는 esp32-wrover-kit-3.3v.cfg 을 세부적으로 분석 및 수정방법 

  • board/esp32-wrover-kit-3.3v.cfg
Main을 보면 다시 2개를 참조하며, ESP32_FLASH_VOLTAGE를 설정하고 구성됨
# Example OpenOCD configuration file for ESP32-WROVER-KIT board.
#
# For example, OpenOCD can be started for ESP32 debugging on
#
#   openocd -f board/esp32-wrover-kit-3.3v.cfg
#

# Source the JTAG interface configuration file
source [find interface/ftdi/esp32_devkitj_v1.cfg]
set ESP32_FLASH_VOLTAGE 3.3


# Source the ESP32 configuration file
source [find target/esp32.cfg]

  • interface/ftdi/esp32_devkitj_v1.cfg
ESP32 Prog Board의 설정 구성이며, FT2232 설정과 유사하며 이는 FTDI 사용법을 알면 쉽게 설정도 변경가능하다.
#
# Driver for the FT2232H JTAG chip on the Espressif DevkitJ board
# (and most other FT2232H and FT232H based boards)
#
 

interface ftdi
ftdi_vid_pid 0x0403 0x6010 0x0403 0x6014

# interface 1 is the uart
ftdi_channel 0

# TCK, TDI, TDO, TMS: ADBUS0-3
# LEDs: ACBUS4-7

ftdi_layout_init 0x0008 0xf00b
ftdi_layout_signal LED -data 0x1000
ftdi_layout_signal LED2 -data 0x2000
ftdi_layout_signal LED3 -data 0x4000
ftdi_layout_signal LED4 -data 0x8000

# ESP32 series chips do not have a TRST input, and the SRST line is connected
# to the EN pin. 
# The target code doesn't handle SRST reset properly yet, so this is
# commented out:
# ftdi_layout_signal nSRST -oe 0x0020

reset_config none

# The speed of the JTAG interface, in KHz. If you get DSR/DIR errors (and they
# do not relate to OpenOCD trying to read from a memory range without physical
# memory being present there), you can try lowering this.
#
# On DevKit-J, this can go as high as 20MHz if CPU frequency is 80MHz, or 26MHz
# if CPU frequency is 160MHz or 240MHz.
adapter_khz 20000

ESP32 JTAG Speed
JTAG을 연결하면 간혹 DSR/DIR Error가 발생하는데, 이는 OpenOCD와 관련이 없다고 한다.
처음 이 문제를 JTAG Speed 문제, 즉 JTAG의 속도가 너무 부족하여 동작안되는 줄 알았는데, 알아보니 아니다.
JTAG의 속도는 20Mhz or 26Mhz 설정이며,  존재하지 않은 Memory 영역을 접근했을때 문제가 발생하는 것이라고 한다.  

  • target/esp32.cfg
ESP32의 전반적인 설정이며, TAP으로 얻는 정보들을 확인 및 관련부분 설정과정이며 이전 OpenOCD를 보면 쉽게 이해가능하다.(esp_common 생략)
# The ESP32 only supports JTAG.
transport select jtag

# Source the ESP common configuration file
source [find target/esp_common.cfg]

if { [info exists CHIPNAME] } {
	set _CHIPNAME $CHIPNAME
} else {
	set _CHIPNAME esp32
}

if { [info exists CPUTAPID] } {
	set _CPUTAPID $CPUTAPID
} else {
	set _CPUTAPID 0x120034e5
}

if { [info exists ESP32_ONLYCPU] } {
	set _ONLYCPU $ESP32_ONLYCPU
} else {
	set _ONLYCPU 3
}

if { [info exists ESP32_FLASH_VOLTAGE] } {
	set _FLASH_VOLTAGE $ESP32_FLASH_VOLTAGE
} else {
	set _FLASH_VOLTAGE 3.3
}

set _TARGETNAME $_CHIPNAME
set _CPU0NAME cpu0
set _CPU1NAME cpu1
set _TAPNAME $_CHIPNAME.$_CPU0NAME

jtag newtap $_CHIPNAME $_CPU0NAME -irlen 5 -expected-id $_CPUTAPID
if { $_ONLYCPU != 1 } {
	jtag newtap $_CHIPNAME $_CPU1NAME -irlen 5 -expected-id $_CPUTAPID
} else {
	jtag newtap $_CHIPNAME $_CPU1NAME -irlen 5 -disable -expected-id $_CPUTAPID
}

if { $_RTOS == "none" } {
	target create $_TARGETNAME esp32 -endian little -chain-position $_TAPNAME
} else {
	target create $_TARGETNAME esp32 -endian little -chain-position $_TAPNAME -rtos $_RTOS
}

configure_esp_workarea $_TARGETNAME 0x40090000 0x3400 0x3FFC0000 0x6000
configure_esp_flash_bank $_TARGETNAME $_TARGETNAME $_FLASH_SIZE

esp32 flashbootstrap $_FLASH_VOLTAGE
xtensa maskisr on
if { $_SEMIHOST_BASEDIR != "" } {
	esp semihost_basedir $_SEMIHOST_BASEDIR
}
if { $_FLASH_SIZE == 0 } {
	gdb_breakpoint_override hard
}

# special function to program ESP32, it differs from the original 'program' that
# it verifies written image by reading flash directly, instead of reading memory mapped flash regions
proc program_esp32 {filename args} {
	program_esp $filename $args
}

add_help_text program_esp32 "write an image to flash, address is only required for binary images. verify, reset, exit are optional"
add_usage_text program_esp32 "<filename> \[address\] \[verify\] \[reset\] \[exit\]"

1.4 OpenOCD 와 SDKCONFIG 설정 

ESP32의 경우 Linux Kernel 처럼 Kconfig 기반으로 menuconfig로 설정가능하며 이때 나오는 결과 설정값이 sdkconfig 이며, 이를 쉽게 변경가능하다. 
VS Code의 경우 GUI로 멋지게 제공을 해주고 있으므로 쉽게 설정가능하다. 

  • OpenOCD사용시 SDKCONFIG 설정변경값
기본적으로 OpenOCD기반으로 Debugger로 이용시 설정해야하는 설정들 
  1. CONFIG_ESP_DEBUG_OCDAWARE 
  2. CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
  https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/tips-and-quirks.html#support-options-for-openocd-at-compile-time


HEAP TRACE와 APP TRACE는 ESP-IDF Extension에서 세부사항을 확인가능 

  • APP TRACE 관련예제
이전에 간단하게 App Trace 테스트 구동 했으며, Heap trace는 추후 테스트 진행

  • HEAP_TRACE 기능제공 (SDKCONFIG 설정변경)
heap tracing 방법은 2가지로 제공해주고 있으며, 각각 sdkconfig 설정기반으로 본인이 선택

  • APP_TRACE  기능제공 (SDKCONFIG 설정변경)
두 개의 Trace가 다 Trace Log기반으로 동작이 되므로 관련부분은 상위 메뉴얼 참조 
APP TRACE의 경우 세부분석은 SYSTEM VIEW가 별도로 필요 (아직사용못해봄) 



2. VS Code 내부 설정 


  • VS Code Setup Manual 
ESP-IDF 설치 방법 (내부에 Git/Python을 비롯하여 전부 포함되어있음)


2.1 VS Code의 MS-CPPTool 기반설정  

상위에서 이미 CPPTool은 이미 설치가 되어있고, 아래와 같이 Run and Debug에서 launch.json만 설정해주면 된다.
OpenOCD와 동작은되는데, 이상하게 Breakpoint가 동작이 안되며, Exception이 발생하여 진행하기 힘들다.
예제프로그램으로 하면 괜찮을 것 같은데, 아직 해보지는 않음 


  • launch.json 설정 
launch.json 생성 후 자동으로 c_cpp_properties.json 자동생성 이게 다시 build/compile_commands.json 관리 
  {
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "ESP32 Debugger",             //launch.json 의 Name 
            "type": "cppdbg",                      //cppdbg 기반으로 작동  
            "request": "launch",
            
             //만약 인식을 못한다면, \\build\\xxxx.elf" 변경을 해보도록 하자 Window에서 매번 PATH문제 발생 
            "program": "${workspaceRoot}/build/xxxxx.elf",

            "miDebuggerServerAddress": "localhost:3333",    // GDB:3333/ TCL:6666/ Telnet:4444 (OpenOCD 참조) 
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:/Users/jhlee/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb.exe",
            
            "setupCommands": [
                {
                     //gdbinit 정보를 넣으려고 했는데, 동작이 제대로 안됨 
                    "description": "gdb에 자동 서식 지정 사용",
                    "text": "symbol-file d:\\project\\mod\\mod610_sw\\build\\xxxxx.elf",
                    "ignoreFailures": true
                }
            ]

        }
    ]
}  

  • 상위 설정기반으로 진행방법 
  1. OpenOCD Start  (상위 batch 파일참조)
  2. VS Code의 Run and Debug->launch.json 설정 (상위참조)
  3. Run and Debug에서 Debug 실행진행 




  • OpenOCD Server 확인 
  1. port 4444 for Telnet communication
  2. port 6666 for TCL communication 
  3. port 3333 for gdb

2.2 ESP-IDF Debug Adapter 기반설정 (이방법 추천) 

View->Output -> ESP-IDF Debug Adapter가 존재하며, 이를 Run and Debug에 연결을하여 launch.json을 생성한다. 
이를 생성을 하게되면, 자동으로 task.json 과 setting.json이 생성이 되어진다. 
이는 예전에 Linux에서 동작하는 것으로 관련설정과 task.json을 쉽게 볼수 있다. 

상위에 내가 별도로 만든 OpenOCD batch 파일 설정도 필요가 없으며, 내부설정해서 모두 해결하면된다.

실행을 해보면 처음 breakpoint는 한번은 동작은하는데, 다음부터 exception 때문에 잘 동작이 되지 않는다. 
이전에 Linux에서도 사용했는데, 그때는 gdbgui로 집중해서 사용했던것 같다. 
 

  • lauch.json 생성
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "espidf",         //espidf 기반으로 작동 (VS Code ESP IDF를 이미 설치)  
      "name": "Launch-name", 
      "request": "launch",
       "gdbinitFile":"${workspaceFolder}/gdbinit",   
    }
  ]
}
  • gdbinit 생성
 //gdbinit 생성 후 elf에서 symbol을 찾도록 연결 
target remote :3333
set remote hardware-watchpoint-limit 2           //ESP32가 2 까지만,   
symbol-file ./build/xxxxx.elf                    //반드시 Symbol Table 연결 
mon reset halt
flushregs
thb app_main
c
  • launch.json 생성 및 관련설정 
상위설정은 기본으로 auto이며, 이외  별도로 세부설정가능 아래 링크참조 

  • 기본동작 및 확인 
본인의 Thread 갯수가 맞는 지 부터 확인 (elf 심볼테이블 매치)



아래사항들 확인 각 로그확인 
  1. View->OUTPUT ESP-IDF Debug adapter 선택 로그확인 
  2. View->OUTPUT 의 OpenOCD 선택 로그확인 (특히 Symbols 부분)
  3. View->DEBUG CONSOLE을 확인

이전과의 다른점은 Call Stack에서 각 Thread의 이름을 알수 있으며, 개별 Thread Control도 가능하며, 제어가 가능하다는 부분이다.

  • 참고
WATCH POINT를 사용하고자 하면 원하는 변수를 넣으면 감시가 된다. (물론 SDKCONFIG설정필요)


  • VSCode의 동작 
아래처럼 동작하지만 PERIPHERALS/REGISTERS/MEMORY/DiSASSEMBLEY는 없음 


  • esp-idf-vscode-generated.gdb 
gdbinit 처럼 생성된 파일로 gdb를 초기설정값 
target remote :3333
mon reset halt
flushregs
thb app_main

gdbinit 처럼 gdb 초기화 부분 
  https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/tips-and-quirks.html#what-is-the-meaning-of-debugger-s-startup-commands

  • ESP32의 제약사항 
ESP32의 경우 HW-BP(breakpoint)는 2개까지 지원되며, HW-BP기반으로 SW-BP 생성하여 FLASH(32개)와 IRAM (32개) 사용가능하지만
gdb는 SW-BP를 사용하지 못한다고 한다. 


  • Terminal->Run Task 이용하여 각 Task 실행 
기존에 제공해주는 메뉴와 비슷하며, 거의 별도로 사용할 일은 없을 것 같다. 
Linux에서는 별도로 Task를 만들어 내마음대로 구성을 했지만, 현재 ESP-IDF 에서 기본으로 각 메뉴로 제공해주고 있다. 

  • VS Code IDF Setting 
View -> Command Palette -> Preferences: Open Settings (UI))
Extensions->ESP-IDF 세부참조확인 
.vscode/task.json 참조 


상위대로하면, WATCH기능과 BreakPoints기반으로 디버깅이 가능하며 Call Stack도 분석이 가능하며 나름 어느 정도 쓸만한 것으로 보인다.

  • VS Code ESP-IDF 단점 
  1. Disasemble 
  2. Memory Read/Write 
  3. Peripheral 
상위와 같은 정보를 제공을 못해주고 있으며, 다소 불안전한 모습으로 동작한다.
사용하면 사용할 수로 많은 부분이 JTAG 디버거 기능으로 부족하다고 느끼는 바이다.


3. VS Code 기반의 ESP-IDF 의 TIPs

ESP-IDF VS Code Extension 설치 후 하단에 아래 아이콘이 생성되며 각각의 idf.py 의 기능을 손쉽게 사용가능하다.


얼마전에 새로 업데이트가 되어 새로운 기능들이 추가되고 있으며, 약간씩 변경될지도 모른다.



ESP-IDF Monitor 혹은 VS Code에서 제공해주는 기능은 PowerShell 기반으로 동작이 되며 이를 응용하여 간단하게 확장하여 사용가능하다.

  • ESP-IDF Monitor 의 경우 (tee를 이용)

Ctrl+C로 정지 후 아래와 같이 tee를 이용하여 log capture를 하자 PS에서 tee가 될줄은 정말 몰랐는데, PS(Power Shell)이 가만보면 
Linux 환경을 비롯하여 기능들을 최대한 지원해주려고 하는 것으로 보인다.
 C:\Users\jhlee\.espressif\python_env\idf4.2_py3.8_env\Scripts\python.exe C:\Users\jhlee\esp\esp-idf\tools\idf.py -p COM6 monitor | tee debug.log  

  • ESP-IDF Terminal 사용할 경우
기존 리눅스 처럼 idf.py 기반으로 메뉴를 사용가능하지만, menuconfig는 제대로 동작이 안됨
그래서 별도로 VS Code에서 GUI로 제공해줌 

 idf.py --help
......
  add-dependency           Add dependency to the manifest file. For now we only support adding dependencies on the default service.
  all                      Aliases: build. Build the project.
  app                      Build only the app.
  app-flash                Flash the app only.
  bootloader               Build only bootloader.
  bootloader-flash         Flash bootloader only.
  clean                    Delete build output files from the build directory.
  confserver               Run JSON configuration server.
  create-manifest          Create manifest for specified component.
  create-remote-component  Register a new component on the component service.
  delete-version           Delete version in dist directory from the component service.
  efuse_common_table       Generate C-source for IDF's eFuse fields.
  efuse_custom_table       Generate C-source for user's eFuse fields.
  encrypted-app-flash      Flash the encrypted app only.
  encrypted-flash          Flash the encrypted project.
  erase_flash              Erase entire flash chip.
  erase_otadata            Erase otadata partition.
  flash                    Flash the project.
  fullclean                Delete the entire build directory contents.
  gdb                      Run the GDB.
  gdbgui                   GDB UI in default browser.
  gdbtui                   GDB TUI mode.
  menuconfig               Run "menuconfig" project configuration tool.
  monitor                  Display serial output.
  openocd                  Run openocd from current path
  pack-component           Create component archive.
  partition_table          Build only partition table.
  partition_table-flash    Flash partition table only.
  post_debug               Utility target to read the output of async debug action and stop them.
  python-clean             Delete generated Python byte code from the IDF directory
  read_otadata             Read otadata partition.
  reconfigure              Re-run CMake.
  set-target               Set the chip target to build.
  show_efuse_table         Print eFuse table.
  size                     Print basic size information about the app.
  size-components          Print per-component size information.
  size-files               Print per-source-file size information.
  upload-component         Upload component in dist directory to the component service.
  upload-component-status  Check status of component upload


댓글 없음 :