add jtag to ESP32

This commit is contained in:
colin 2022-02-02 03:39:59 +00:00
parent 853d12f17c
commit a15c797e93
17 changed files with 862 additions and 0 deletions

Binary file not shown.

View File

@ -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

View File

@ -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
}

BIN
jtag/jtagEsp32Jlink/blink.elf Executable file

Binary file not shown.

View File

@ -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

5
jtag/jtagEsp32Jlink/gdb.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
source ~/develop/esp-idf/export.sh
riscv32-esp-elf-gdb -x gdbinit blink.elf

View File

@ -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

View File

@ -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

View File

@ -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
#
# <NAME>( RegionNumber , ATTRIBUTE )
#
# Where <NAME> 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"
}
}

View File

@ -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
}

5
jtag/jtagEsp32Jlink/openocd.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
source ~/develop/esp-idf/export.sh
openocd -f jlink.cfg -f esp32c3.cfg

View File

@ -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 "<filename> \[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 "<build_dir> 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\]"

View File

@ -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

BIN
jtag/jtagEsp32USB/blink.elf Executable file

Binary file not shown.

2
jtag/jtagEsp32USB/gdb.sh Normal file
View File

@ -0,0 +1,2 @@
source ~/develop/esp-idf/export.sh
riscv32-esp-elf-gdb -x gdbinit blink.elf

View File

@ -0,0 +1,6 @@
target remote :3333
set remote hardware-watchpoint-limit 2
mon reset halt
flushregs
thb app_main
c

View File

@ -0,0 +1,2 @@
source ~/develop/esp-idf/export.sh
openocd -f board/esp32c3-builtin.cfg