diff --git a/jtag/jtagEsp32Jlink/JLink_Linux_V760f_x86_64.deb b/jtag/jtagEsp32Jlink/JLink_Linux_V760f_x86_64.deb new file mode 100644 index 0000000..4cb27e3 Binary files /dev/null and b/jtag/jtagEsp32Jlink/JLink_Linux_V760f_x86_64.deb differ diff --git a/jtag/jtagEsp32Jlink/Readmd.md b/jtag/jtagEsp32Jlink/Readmd.md new file mode 100644 index 0000000..61b6a25 --- /dev/null +++ b/jtag/jtagEsp32Jlink/Readmd.md @@ -0,0 +1,63 @@ +# USE jtag for openocd in ESP32 + +## board + +ESP-C3-32S-Kit https://docs.ai-thinker.com/_media/esp32/docs/esp-c3-32s-kit-v1.0_规格书.pdf + +## install JLink deb software and driver + +## build esp32-c3 binary + +```bash +# At esp-idf +source export.sh +cd examples/get-started/blink +idf.py set-target esp32-c3 +idf.py menuconfig # config the io and LED mode +idf.py build +idf.py -p (PORT) flash # to flash to module to verify the effect of binary by USART port +``` + +## 配置ESP32 + +由于 ESP32-C3 默认选用 内置的 USB_SERIAL_JTAG 外设。此时需要烧录 efuse 来选择外接 JTAG 适配器,有以下两种方式: + +* 烧毁 DIS_USB_JTAG eFuse: 将永久禁用 USB_SERIAL_JTAG 和 CPU 的 JTAG 端口之间的连接。 然后可以将 JTAG 接口连接到 GPIO4 - GPIO7。 请注意,USB_SERIAL_JTAG 的 USB CDC 功能仍然可用,即仍然可以通过 USB CDC 进行烧录和 log 查看。 +* 烧毁 JTAG_SEL_ENABLE eFuse: 将启用由 Strapping 引脚 GPIO10 选择的 JTAG 接口。 如果 ESP32-C3 复位时 Strapping 引脚为低电平,则 JTAG 接口将使用 GPIO4 - GPIO7。 如果 Strapping 引脚为高电平,则 USB_SERIAL_JTAG 将用作 JTAG 接口。 + +`espefuse.py burn_efuse JTAG_SEL_ENABLE -p /dev/ttyUSB0` +然后你会得到一个需要输入BURN 的确认信息,如下: + +```bash +Connecting.... +Detecting chip type... ESP32-C3 +espefuse.py v3.3-dev +The efuses to burn: + from BLOCK0 + - JTAG_SEL_ENABLE + +Burning efuses: + + - 'JTAG_SEL_ENABLE' (Disables USB JTAG. JTAG access via pads is controlled separately) 0b0 -> 0b1 + +Check all blocks for burn... +idx, BLOCK_NAME, Conclusion +[00] BLOCK0 is not empty + (written ): 0x000000000000008000000000000000000000800000000000 + (to write): 0x000000000000000000000000000000000000020000000000 + (coding scheme = NONE) +. +This is an irreversible operation! +Type 'BURN' (all capitals) to continue. +``` + +## usage + +* 链接JLink的 jtag 四个IO,`TMS` `TDI` `TDO` `TCK` +* 默认固件开发板的JTAG IO不能用于其他功能,必须是闲置状态 +* Must use esp's `openocd` by source export.sh in esp-idy, after esp-idf installed. + +## cmd + +* `./openocd.sh` start openocd +* `./gdb.sh` start gdb diff --git a/jtag/jtagEsp32Jlink/bitsbytes.tcl b/jtag/jtagEsp32Jlink/bitsbytes.tcl new file mode 100644 index 0000000..52ca83d --- /dev/null +++ b/jtag/jtagEsp32Jlink/bitsbytes.tcl @@ -0,0 +1,59 @@ +#---------------------------------------- +# Purpose - Create some $BIT variables +# Create $K and $M variables +# and some bit field extraction variables. +# Creat helper variables ... +# BIT0.. BIT31 + +for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { + set vn [format "BIT%d" $x] + global $vn + set $vn [expr (1 << $x)] +} + +# Create K bytes values +# __1K ... to __2048K +for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { + set vn [format "__%dK" $x] + global $vn + set $vn [expr (1024 * $x)] +} + +# Create M bytes values +# __1M ... to __2048K +for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { + set vn [format "__%dM" $x] + global $vn + set $vn [expr (1024 * 1024 * $x)] +} + +proc create_mask { MSB LSB } { + return [expr (((1 << ($MSB - $LSB + 1))-1) << $LSB)] +} + +# Cut Bits $MSB to $LSB out of this value. +# Example: % format "0x%08x" [extract_bitfield 0x12345678 27 16] +# Result: 0x02340000 + +proc extract_bitfield { VALUE MSB LSB } { + return [expr [create_mask $MSB $LSB] & $VALUE] +} + + +# Cut bits $MSB to $LSB out of this value +# and shift (normalize) them down to bit 0. +# +# Example: % format "0x%08x" [normalize_bitfield 0x12345678 27 16] +# Result: 0x00000234 +# +proc normalize_bitfield { VALUE MSB LSB } { + return [expr [extract_bitfield $VALUE $MSB $LSB ] >> $LSB] +} + +proc show_normalize_bitfield { VALUE MSB LSB } { + set m [create_mask $MSB $LSB] + set mr [expr $VALUE & $m] + set sr [expr $mr >> $LSB] + echo [format "((0x%08x & 0x%08x) -> 0x%08x) >> %2d => (0x%x) %5d " $VALUE $m $mr $LSB $sr $sr] + return $sr +} diff --git a/jtag/jtagEsp32Jlink/blink.elf b/jtag/jtagEsp32Jlink/blink.elf new file mode 100755 index 0000000..cf09fb3 Binary files /dev/null and b/jtag/jtagEsp32Jlink/blink.elf differ diff --git a/jtag/jtagEsp32Jlink/esp32c3.cfg b/jtag/jtagEsp32Jlink/esp32c3.cfg new file mode 100644 index 0000000..4b97eb1 --- /dev/null +++ b/jtag/jtagEsp32Jlink/esp32c3.cfg @@ -0,0 +1,134 @@ +# The ESP32-C3 only supports JTAG. +transport select jtag + +set CPU_MAX_ADDRESS 0xFFFFFFFF +source [find bitsbytes.tcl] +source [find memory.tcl] +source [find mmr_helpers.tcl] +# Source the ESP common configuration file +source [find target/esp_common.cfg] + +# Target specific registers +set EFUSE_MAC_ADDR_REG 0x60008844 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME esp32c3 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x00005c25 +} + +set _TARGETNAME $_CHIPNAME +set _CPUNAME cpu +set _TAPNAME $_CHIPNAME.$_CPUNAME + +jtag newtap $_CHIPNAME $_CPUNAME -irlen 5 -expected-id $_CPUTAPID + +proc esp32c3_wdt_disable { } { + # Halt event can occur during config phase (before "init" is done). + # Ignore it since mww commands don't work at that time. + if { [string compare [command mode] config] == 0 } { + return + } + + # Timer Group 0 & 1 WDTs + mww 0x6001f064 0x50D83AA1 + mww 0x6001F048 0 + mww 0x60020064 0x50D83AA1 + mww 0x60020048 0 + # RTC WDT + mww 0x600080a8 0x50D83AA1 + mww 0x60008090 0 + # SWD + mww 0x600080b0 0x8F1D312A + mww 0x600080ac 0x84B00000 +} + +proc esp32c3_soc_reset { } { + # This procedure does "digital system reset", i.e. resets + # all the peripherals except for the RTC block. + # It is called from reset-assert-post target event callback, + # after assert_reset procedure was called. + # Since we need the hart to to execute a write to RTC_CNTL_SW_SYS_RST, + # temporarily take it out of reset. Save the dmcontrol state before + # doing so. + riscv dmi_write 0x10 0x80000001 + # If SBA is used to trigger the reset, the debug module gets stuck + # in a busy state waiting for the bus write to complete (HW quirk?), + # so trigger the reset by CPU instead. + riscv set_prefer_sba off + mww 0x60008000 0x9c00a000 + # Workaround for stuck in cpu start during calibration. + # By writing zero to TIMG_RTCCALICFG_REG, we are disabling calibration + mww 0x6001F068 0 + # Wait for the reset to happen + sleep 10 + poll + # Restore SBA setting + riscv set_prefer_sba on + # Disable the watchdogs again + esp32c3_wdt_disable + # Put the hart back into reset state. Note that we need to keep haltreq set. + riscv dmi_write 0x10 0x80000003 +} + +proc esp32c3_memprot_is_enabled { } { + # IRAM0 PMS lock, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG + if { [mmr_get_bit 0x600C10A8 0] != 0 } { + return 1 + } + # DRAM0 PMS lock, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG + if { [mmr_get_bit 0x600C10C0 0] != 0 } { + return 1 + } + return 0 +} + + +if { $_RTOS == "none" } { + target create $_TARGETNAME esp32c3 -chain-position $_TAPNAME +} else { + target create $_TARGETNAME esp32c3 -chain-position $_TAPNAME -rtos $_RTOS +} + +$_TARGETNAME configure -event reset-assert-post { esp32c3_soc_reset } +$_TARGETNAME configure -event halted { + esp32c3_wdt_disable +} +$_TARGETNAME configure -event examine-end { + # Need this to handle 'apptrace init' syscall correctly because semihosting is not enabled by default + arm semihosting enable + arm semihosting_resexit enable +} +$_TARGETNAME configure -event gdb-attach { + # 'halt' is necessary to auto-probe flash bank when GDB is connected and generate proper memory map + halt + if { [esp32c3_memprot_is_enabled] } { + # 'reset halt' to disable memory protection and allow flasher to work correctly + echo "Memory protection is enabled. Reset target to disable it..." + reset halt + } + # by default mask interrupts while stepping + riscv maskisr steponly +} + +# stub flasher may need a lot of memory in case of compressed writes to flash (~107KB): +# - for apptrace: 2x16KB up buffers + 32KB down buffer +# - for uncompression: 32KB for unzip buffer size + 11KB for inflator data structs +# TODO: In general when up buffers are swapped apptrace copies `host->target` data from new up buffer to down buffer to free space for `target->host` data. +# In case of flash writes we use apptrace transfers in one direction only. So we can avoid copying and re-use up buffer instead of down one. +configure_esp_workarea $_TARGETNAME 0x40380000 0x4000 0x3FC84000 0x20000 +configure_esp_flash_bank $_TARGETNAME $_TARGETNAME $_FLASH_SIZE + +if { $_FLASH_SIZE == 0 } { + gdb_breakpoint_override hard +} + +riscv set_reset_timeout_sec 2 +riscv set_command_timeout_sec 5 +riscv set_prefer_sba on diff --git a/jtag/jtagEsp32Jlink/gdb.sh b/jtag/jtagEsp32Jlink/gdb.sh new file mode 100755 index 0000000..fde0e62 --- /dev/null +++ b/jtag/jtagEsp32Jlink/gdb.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +source ~/develop/esp-idf/export.sh +riscv32-esp-elf-gdb -x gdbinit blink.elf diff --git a/jtag/jtagEsp32Jlink/gdbinit b/jtag/jtagEsp32Jlink/gdbinit new file mode 100644 index 0000000..f5cea0b --- /dev/null +++ b/jtag/jtagEsp32Jlink/gdbinit @@ -0,0 +1,7 @@ +target remote :3333 +set remote hardware-watchpoint-limit 2 +mon reset halt +flushregs +thb app_main +directory /home/colin/develop/esp-idf +c diff --git a/jtag/jtagEsp32Jlink/jlink.cfg b/jtag/jtagEsp32Jlink/jlink.cfg new file mode 100644 index 0000000..db08136 --- /dev/null +++ b/jtag/jtagEsp32Jlink/jlink.cfg @@ -0,0 +1,16 @@ +# +# SEGGER J-Link +# +# http://www.segger.com/jlink.html +# + +adapter driver jlink +adapter speed 1000 + + +# The serial number can be used to select a specific device in case more than +# one is connected to the host. +# +# Example: Select J-Link with serial number 123456789 +# +# adapter serial 123456789 diff --git a/jtag/jtagEsp32Jlink/memory.tcl b/jtag/jtagEsp32Jlink/memory.tcl new file mode 100644 index 0000000..3066c11 --- /dev/null +++ b/jtag/jtagEsp32Jlink/memory.tcl @@ -0,0 +1,187 @@ +# MEMORY +# +# All Memory regions have two components. +# (1) A count of regions, in the form N_NAME +# (2) An array within info about each region. +# +# The ARRAY +# +# ( RegionNumber , ATTRIBUTE ) +# +# Where is one of: +# +# N_FLASH & FLASH (internal memory) +# N_RAM & RAM (internal memory) +# N_MMREGS & MMREGS (for memory mapped registers) +# N_XMEM & XMEM (off chip memory, ie: flash on cs0, sdram on cs2) +# or N_UNKNOWN & UNKNOWN for things that do not exist. +# +# We have 1 unknown region. +set N_UNKNOWN 1 +# All MEMORY regions must have these attributes +# CS - chip select (if internal, use -1) +set UNKNOWN(0,CHIPSELECT) -1 +# BASE - base address in memory +set UNKNOWN(0,BASE) 0 +# LEN - length in bytes +set UNKNOWN(0,LEN) $CPU_MAX_ADDRESS +# HUMAN - human name of the region +set UNKNOWN(0,HUMAN) "unknown" +# TYPE - one of: +# flash, ram, mmr, unknown +# For harvard arch: +# iflash, dflash, iram, dram +set UNKNOWN(0,TYPE) "unknown" +# RWX - access ablity +# unix style chmod bits +# 0 - no access +# 1 - execute +# 2 - write +# 4 - read +# hence: 7 - readwrite execute +set RWX_NO_ACCESS 0 +set RWX_X_ONLY $BIT0 +set RWX_W_ONLY $BIT1 +set RWX_R_ONLY $BIT2 +set RWX_RW [expr $RWX_R_ONLY + $RWX_W_ONLY] +set RWX_R_X [expr $RWX_R_ONLY + $RWX_X_ONLY] +set RWX_RWX [expr $RWX_R_ONLY + $RWX_W_ONLY + $RWX_X_ONLY] +set UNKNOWN(0,RWX) $RWX_NO_ACCESS + +# WIDTH - access width +# 8,16,32 [0 means ANY] +set ACCESS_WIDTH_NONE 0 +set ACCESS_WIDTH_8 $BIT0 +set ACCESS_WIDTH_16 $BIT1 +set ACCESS_WIDTH_32 $BIT2 +set ACCESS_WIDTH_ANY [expr $ACCESS_WIDTH_8 + $ACCESS_WIDTH_16 + $ACCESS_WIDTH_32] +set UNKNOWN(0,ACCESS_WIDTH) $ACCESS_WIDTH_NONE + +proc iswithin { ADDRESS BASE LEN } { + return [expr ((($ADDRESS - $BASE) >= 0) && (($BASE + $LEN - $ADDRESS) > 0))] +} + +proc address_info { ADDRESS } { + + foreach WHERE { FLASH RAM MMREGS XMEM UNKNOWN } { + if { info exists $WHERE } { + set lmt [set N_[set WHERE]] + for { set region 0 } { $region < $lmt } { incr region } { + if { iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN) } { + return "$WHERE $region"; + } + } + } + } + + # Return the 'unknown' + return "UNKNOWN 0" +} + +proc memread32 {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memread32: $msg" + } +} + +proc memread16 {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memread16: $msg" + } +} + +proc memread8 {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memread8: $msg" + } +} + +proc memwrite32 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 32 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite32: $msg" + } +} + +proc memwrite16 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 16 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite16: $msg" + } +} + +proc memwrite8 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 8 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite8: $msg" + } +} + +proc memread32_phys {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 32 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memread32: $msg" + } +} + +proc memread16_phys {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 16 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memread16: $msg" + } +} + +proc memread8_phys {ADDR} { + set foo(0) 0 + if ![ catch { mem2array foo 8 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memread8: $msg" + } +} + +proc memwrite32_phys {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 32 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memwrite32: $msg" + } +} + +proc memwrite16_phys {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 16 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memwrite16: $msg" + } +} + +proc memwrite8_phys {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 8 $ADDR 1 phys } msg ] { + return $foo(0) + } else { + error "memwrite8: $msg" + } +} diff --git a/jtag/jtagEsp32Jlink/mmr_helpers.tcl b/jtag/jtagEsp32Jlink/mmr_helpers.tcl new file mode 100644 index 0000000..2d1809b --- /dev/null +++ b/jtag/jtagEsp32Jlink/mmr_helpers.tcl @@ -0,0 +1,91 @@ + +proc proc_exists { NAME } { + set n [info commands $NAME] + set l [string length $n] + return [expr $l != 0] +} + +# Give: REGISTER name - must be a global variable. +proc show_mmr32_reg { NAME } { + + global $NAME + # we want $($NAME) + set a [set [set NAME]] + + if ![catch { set v [memread32 $a] } msg ] { + echo [format "%15s: (0x%08x): 0x%08x" $NAME $a $v] + + # Was a helper defined? + set fn show_${NAME}_helper + if [ proc_exists $fn ] { + # Then call it + $fn $NAME $a $v + } + return $v; + } else { + error [format "%s (%s)" $msg $NAME ] + } +} + + +# Give: NAMES - an array of names accessible +# in the callers symbol-scope. +# VAL - the bits to display. + +proc show_mmr32_bits { NAMES VAL } { + + upvar $NAMES MYNAMES + + set w 5 + foreach {IDX N} $MYNAMES { + set l [string length $N] + if { $l > $w } { set w $l } + } + + for { set x 24 } { $x >= 0 } { incr x -8 } { + echo -n " " + for { set y 7 } { $y >= 0 } { incr y -1 } { + set s $MYNAMES([expr $x + $y]) + echo -n [format "%2d: %-*s | " [expr $x + $y] $w $s ] + } + echo "" + + echo -n " " + for { set y 7 } { $y >= 0 } { incr y -1 } { + echo -n [format " %d%*s | " [expr !!($VAL & (1 << ($x + $y)))] [expr $w -1] ""] + } + echo "" + } +} + + +proc show_mmr_bitfield { MSB LSB VAL FIELDNAME FIELDVALUES } { + set width [expr (($MSB - $LSB + 1) + 7) / 4] + set nval [show_normalize_bitfield $VAL $MSB $LSB ] + set name0 [lindex $FIELDVALUES 0 ] + if [ string compare $name0 _NUMBER_ ] { + set sval [lindex $FIELDVALUES $nval] + } else { + set sval "" + } + echo [format "%-15s: %d (0x%0*x) %s" $FIELDNAME $nval $width $nval $sval ] +} + +# Give: ADDR - address of the register. +# BIT - bit's number. + +proc mmr_get_bit { ADDR BIT } { + set val [memread32 $ADDR] + set bit_val [expr $val & [expr 1 << $BIT]] + return $bit_val +} + + +# Give: ADDR - address of the register. +# MSB - MSB bit's number. +# LSB - LSB bit's number. + +proc mmr_get_bitfield { ADDR MSB LSB } { + set rval [memread32 $ADDR] + return normalize_bitfield $rval $MSB $LSB +} diff --git a/jtag/jtagEsp32Jlink/openocd.sh b/jtag/jtagEsp32Jlink/openocd.sh new file mode 100755 index 0000000..f875f5f --- /dev/null +++ b/jtag/jtagEsp32Jlink/openocd.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +source ~/develop/esp-idf/export.sh +openocd -f jlink.cfg -f esp32c3.cfg \ No newline at end of file diff --git a/jtag/jtagEsp32Jlink/target/esp_common.cfg b/jtag/jtagEsp32Jlink/target/esp_common.cfg new file mode 100644 index 0000000..4063442 --- /dev/null +++ b/jtag/jtagEsp32Jlink/target/esp_common.cfg @@ -0,0 +1,269 @@ +# Common ESP chips definitions + +if { [info exists ESP_RTOS] } { + set _RTOS "$ESP_RTOS" +} else { + set _RTOS "FreeRTOS" +} + +if { [info exists ESP_SEMIHOST_BASEDIR] } { + set _SEMIHOST_BASEDIR "$ESP_SEMIHOST_BASEDIR" +} else { + # by default current dir (when OOCD has been started) + set _SEMIHOST_BASEDIR "." +} + +if { [info exists ESP_FLASH_SIZE] } { + set _FLASH_SIZE $ESP_FLASH_SIZE +} else { + set _FLASH_SIZE "auto" +} + +proc configure_esp_workarea { TGT CODE_ADDR CODE_SZ DATA_ADDR DATA_SZ } { + #WARNING: be careful when selecting working ares for code and data, they should not overlap due to ESP32 physical memory mappings + $TGT configure -work-area-phys $CODE_ADDR -work-area-virt $CODE_ADDR -work-area-size $CODE_SZ -work-area-backup 1 + # since ESP32 cannot use single address space for code and data we need additional working area to keep data + $TGT configure -alt-work-area-phys $DATA_ADDR -alt-work-area-virt $DATA_ADDR -alt-work-area-size $DATA_SZ -alt-work-area-backup 1 +} + +proc configure_esp_workarea_backups { wab_list awab_list } { + set index 0 + foreach tgt [target names] { + $tgt configure -work-area-backup [lindex $wab_list $index] + $tgt configure -alt-work-area-backup [lindex $awab_list $index] + incr $index + } +} + +proc configure_esp_flash_bank { TGT DRV SIZE } { + set _SIZE SIZE + if { $SIZE == 0 } { + echo "WARNING: ESP flash support is disabled!" + return + } else { + if { $SIZE == "auto" } { + # special value for flash driver + set _SIZE 0 + } + } + # whole flash for programming purposes + # TODO: remove it when support for GDB's 'load' comand is implemented + flash bank $TGT.flash $DRV 0x0 $_SIZE 0 0 $TGT + # So define mapped flash regions as separate flashes + # OOCD creates memory map using registered flash banks + flash bank $TGT.irom $DRV 0x0 0 0 0 $TGT + flash bank $TGT.drom $DRV 0x0 0 0 0 $TGT +} + +# special function to program ESP chip, it differs from the original 'program' that +# it verifies written image by reading flash directly, instead of reading memory mapped flash regions +proc program_esp {filename args} { + set exit 0 + set compress 0 + set restore_clock 0 + + set flash_list_size [llength [flash list]] + if { $flash_list_size == 0} { + program_error "** ESP flash programming is not supported yet! **" $exit + } + + foreach arg $args { + if {[string equal $arg "verify"]} { + set verify 1 + } elseif {[string equal $arg "reset"]} { + set reset 1 + } elseif {[string equal $arg "exit"]} { + set exit 1 + } elseif {[string equal $arg "compress"]} { + set compress 1 + } elseif {[string equal $arg "restore_clock"]} { + set restore_clock 1 + } else { + set address $arg + } + } + + # make sure init is called + if {[catch {init}] != 0} { + program_error "** OpenOCD init failed **" 1 + } + + # reset target and call any init scripts + if {[catch {reset init}] != 0} { + program_error "** Unable to reset target **" $exit + } + + set wab_list {} + set awab_list {} + foreach tgt [target names] { + lappend wab_list [$tgt cget -work-area-backup] + $tgt configure -work-area-backup 0 + lappend awab_list [$tgt cget -alt-work-area-backup] + $tgt configure -alt-work-area-backup 0 + } + + if {$compress == 1} { + eval esp compression "on" + } else { + eval esp compression "off" + } + + # start programming phase + echo "** Programming Started **" + if {[info exists address]} { + set flash_args "$filename $address" + } else { + set flash_args "$filename" + } + + if {[catch {eval esp flash_stub_clock_boost "on"}] != 0} { + program_error "** Clock configuration set failed **" $exit + } + + if {[catch {eval flash write_image erase $flash_args}] == 0} { + echo "** Programming Finished **" + if {[info exists verify]} { + # verify phase + echo "** Verify Started **" + if {[catch {eval esp verify_bank_hash 0 $flash_args}] == 0} { + echo "** Verified OK **" + } else { + configure_esp_workarea_backups $wab_list $awab_list + if {$restore_clock == 1} { + eval esp flash_stub_clock_boost "off" + } + program_error "** Verify Failed **" $exit + } + } + + configure_esp_workarea_backups $wab_list $awab_list + + if {$restore_clock == 1} { + if {[catch {eval esp flash_stub_clock_boost "off"}] != 0} { + program_error "** Clock configuration restore failed **" $exit + } + } + + if {[info exists reset]} { + # reset target if requested + echo "** Resetting Target **" + reset run + } + } else { + configure_esp_workarea_backups $wab_list $awab_list + if {$restore_clock == 1} { + eval esp flash_stub_clock_boost "off" + } + program_error "** Programming Failed **" $exit + } + + if {$exit == 1} { + shutdown + } + return +} + +add_help_text program_esp "write an image to flash, address is only required for binary images. verify, reset, exit, compress, restore_clock are optional" +add_usage_text program_esp " \[address\] \[verify\] \[reset\] \[exit\] \[compress\] \[restore_clock\]" + +proc program_esp_bins {build_dir filename args} { + set exit 0 + set compress 0 + set restore_clock 0 + + foreach arg $args { + if {[string equal $arg "reset"]} { + set reset 1 + } elseif {[string equal $arg "verify"]} { + set verify 1 + } elseif {[string equal $arg "exit"]} { + set exit 1 + } elseif {[string equal $arg "compress"]} { + set compress 1 + } elseif {[string equal $arg "restore_clock"]} { + set restore_clock 1 + } else { + echo "** Unsupported arg $arg, skipping **" + } + } + + # Open and Read file + set fp [open [file join $build_dir $filename] r] + set file_data [read $fp] + close $fp + + # Decode JSON to dict + set flasher_args [json::decode $file_data] + + set flash_files [dict get $flasher_args flash_files] + + foreach addr [dict keys $flash_files] { + set bin_file [dict get $flash_files $addr] + set bin_file_path [file join $build_dir $bin_file] + + echo "Flashing $bin_file_path at $addr" + + if {[info exists verify]} { + set flash_args "$bin_file_path $addr verify" + } else { + set flash_args "$bin_file_path $addr" + } + + if {$compress == 1} { + append flash_args " compress" + } + + if {$restore_clock == 1} { + append flash_args " restore_clock" + } + + if {[ catch { eval program_esp $flash_args} ] == 0} { + echo "** Flashing done for $bin_file **" + } else { + echo "** Flashing Failed **" + return -1 + } + } + + # Reset + if {[info exists reset]} { + echo "** Resetting Target **" + reset run + } + + # Exit + if {$exit == 1} { + shutdown + } + + return 0 +} + +add_help_text program_esp_bins "write all the images at address specified in flasher_args.json generated while building idf project" +add_usage_text program_esp_bins " flasher_args.json \[verify\] \[reset\] \[exit\] \[compress\] \[restore_clock\]" + +proc esp_get_mac {args} { + global EFUSE_MAC_ADDR_REG + foreach arg $args { + if {[string equal $arg "format"]} { + set format 1 + } + } + + if { [string equal [target current] esp32c3] } { + mem2array mac 8 $EFUSE_MAC_ADDR_REG 6 + } else { + xtensa set_permissive 1 + mem2array mac 8 $EFUSE_MAC_ADDR_REG 6 + xtensa set_permissive 0 + } + + if {[info exists format]} { + format %02x:%02x:%02x:%02x:%02x:%02x $mac(5) $mac(4) $mac(3) $mac(2) $mac(1) $mac(0) + } else { + format 0x0000%02x%02x%02x%02x%02x%02x $mac(5) $mac(4) $mac(3) $mac(2) $mac(1) $mac(0) + } +} + +add_help_text esp_get_mac "Print MAC address of the chip. Use a `format` argument to return formatted MAC value" +add_usage_text esp_get_mac "\[format\]" diff --git a/jtag/jtagEsp32USB/Readme.md b/jtag/jtagEsp32USB/Readme.md new file mode 100644 index 0000000..788dfc9 --- /dev/null +++ b/jtag/jtagEsp32USB/Readme.md @@ -0,0 +1,16 @@ +# USE USB for openocd in ESP32 + +## board + +ESP-C3-32S-Kit https://docs.ai-thinker.com/_media/esp32/docs/esp-c3-32s-kit-v1.0_规格书.pdf + + +## usage + +* 连接usb的io18和io19,并确保这两个IO没有被连接到其他地方 +* 配置esp32-c3打开usb及jtag + +## cmd + +* `source openocd.sh` 启动openocd +* `source gdb.sh` 启动gdb diff --git a/jtag/jtagEsp32USB/blink.elf b/jtag/jtagEsp32USB/blink.elf new file mode 100755 index 0000000..cf09fb3 Binary files /dev/null and b/jtag/jtagEsp32USB/blink.elf differ diff --git a/jtag/jtagEsp32USB/gdb.sh b/jtag/jtagEsp32USB/gdb.sh new file mode 100644 index 0000000..8c7dfc5 --- /dev/null +++ b/jtag/jtagEsp32USB/gdb.sh @@ -0,0 +1,2 @@ +source ~/develop/esp-idf/export.sh +riscv32-esp-elf-gdb -x gdbinit blink.elf diff --git a/jtag/jtagEsp32USB/gdbinit b/jtag/jtagEsp32USB/gdbinit new file mode 100644 index 0000000..11d978e --- /dev/null +++ b/jtag/jtagEsp32USB/gdbinit @@ -0,0 +1,6 @@ +target remote :3333 +set remote hardware-watchpoint-limit 2 +mon reset halt +flushregs +thb app_main +c diff --git a/jtag/jtagEsp32USB/openocd.sh b/jtag/jtagEsp32USB/openocd.sh new file mode 100644 index 0000000..3ffe049 --- /dev/null +++ b/jtag/jtagEsp32USB/openocd.sh @@ -0,0 +1,2 @@ +source ~/develop/esp-idf/export.sh +openocd -f board/esp32c3-builtin.cfg