mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
New tools...
This commit is contained in:
1 parent
4d471dc33d
commit
09f893b126
11 files changed
+484
No files matched your search
Whitespace-only changes.
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit
|
||||
# debugger/programmer
|
||||
#
|
||||
# This new interface driver creates a ST-Link wrapper for ARM-DAP named "dapdirect"
|
||||
# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support "dapdirect"
|
||||
#
|
||||
# SWIM transport is natively supported
|
||||
#
|
||||
|
||||
adapter driver st-link
|
||||
st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757
|
||||
|
||||
# transport select dapdirect_jtag
|
||||
# transport select dapdirect_swd
|
||||
# transport select swim
|
||||
|
||||
# Optionally specify the serial number of usb device
|
||||
# e.g.
|
||||
# adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
echo "WARNING: interface/stlink-v1.cfg is deprecated, please switch to interface/stlink.cfg"
|
||||
source [find interface/stlink.cfg]
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
echo "WARNING: interface/stlink-v2-1.cfg is deprecated, please switch to interface/stlink.cfg"
|
||||
source [find interface/stlink.cfg]
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
echo "WARNING: interface/stlink-v2.cfg is deprecated, please switch to interface/stlink.cfg"
|
||||
source [find interface/stlink.cfg]
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit
|
||||
# debugger/programmer
|
||||
#
|
||||
|
||||
adapter driver hla
|
||||
hla layout stlink
|
||||
hla device_desc "ST-LINK"
|
||||
hla vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757
|
||||
|
||||
# Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2
|
||||
# devices seem to have serial numbers with unreadable characters. ST-LINK/V2
|
||||
# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
|
||||
# number reset issues.
|
||||
# eg.
|
||||
#adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
|
||||
@@ -0,0 +1,359 @@
|
||||
#OpenOCD script for Action Dynamic DP32G030 ARM Cortex M0 CPU (UV-5R, UV-k5 Ham HTs)
|
||||
#For use with cheap ST-Link USB debug probe
|
||||
source target/swj-dp.tcl
|
||||
|
||||
set _CHIP_NAME DP32G0xx
|
||||
set _ENDIAN little
|
||||
set _WORKAREASIZE 0x1000
|
||||
set _FLASH_SIZE 0x10000
|
||||
set _CPUTAPID 0x0BB11477
|
||||
set _TARGETNAME $_CHIP_NAME.cpu
|
||||
set _FLASHNAME $_CHIP_NAME.flash
|
||||
set _SECTOR_SIZE 512
|
||||
set _MASKING_CFG 2 ;#1:2kB, 2:4kB, 3:8kB
|
||||
|
||||
adapter speed 960
|
||||
adapter srst delay 100
|
||||
reset_config srst_nogate
|
||||
|
||||
# Create a new dap, with name chip and role CPU, -enable let's OpenOCD to know to add it to the scan
|
||||
swj_newdap $_CHIP_NAME cpu -expected-id $_CPUTAPID -enable
|
||||
|
||||
# Create the DAP instance, this must be explicitly created according to the OpenOCD docs
|
||||
dap create $_CHIP_NAME.dap -chain-position $_CHIP_NAME.cpu
|
||||
|
||||
# Set up the GDB target for the CPU
|
||||
target create $_CHIP_NAME.cpu cortex_m -endian $_ENDIAN -dap $_CHIP_NAME.dap
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
# Declare internal bank
|
||||
flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME
|
||||
|
||||
proc check_readiness {} {
|
||||
while {[read_memory 0x4006F014 32 1] & 0x2} {}
|
||||
}
|
||||
|
||||
proc rom_mask_off {} {
|
||||
echo "\nChecking ROM masking"
|
||||
check_readiness
|
||||
set status [read_memory 0x4006F020 32 1]
|
||||
if {($status & 0x3) != 0} {
|
||||
echo [format "\nROM masking is set to 0b%03b. Unsetting..." $status]
|
||||
write_memory 0x4006F020 32 [expr {[read_memory 0x4006F020 32 1] & 0x3}]
|
||||
check_readiness
|
||||
write_memory 0x4006F020 32 0
|
||||
check_readiness
|
||||
write_memory 0x4006F020 32 4
|
||||
}
|
||||
return [read_memory 0x4006F020 32 1]
|
||||
}
|
||||
|
||||
proc rom_mask_on {} {
|
||||
global _MASKING_CFG
|
||||
echo "\nChecking ROM masking"
|
||||
check_readiness
|
||||
set status [read_memory 0x4006F020 32 1]
|
||||
if {($status & 0x3) != $_MASKING_CFG} {
|
||||
echo [format "\nROM masking is set to 0b%03b. Setting ON..." $status]
|
||||
write_memory 0x4006F020 32 [expr {[read_memory 0x4006F020 32 1] & 0x3}]
|
||||
check_readiness
|
||||
write_memory 0x4006F020 32 $_MASKING_CFG
|
||||
check_readiness
|
||||
write_memory 0x4006F020 32 [expr {4 | $_MASKING_CFG}]
|
||||
}
|
||||
return [read_memory 0x4006F020 32 1]
|
||||
}
|
||||
|
||||
proc unlock_rom {} {
|
||||
write_memory 0x4006F01c 32 0xAA
|
||||
check_readiness
|
||||
}
|
||||
|
||||
proc lock_rom {} {
|
||||
write_memory 0x4006F018 32 0x55
|
||||
check_readiness
|
||||
}
|
||||
|
||||
proc select_region {target_r} {
|
||||
#Region 0 is main user ROM area, 1 is NVRAM area
|
||||
write_memory 0x4006F000 32 [expr {(0x31 & [read_memory 0x4006F000 32 1]) | (($target_r & 0x1) << 1)}]
|
||||
check_readiness
|
||||
}
|
||||
|
||||
proc wipe_sector_range {st_sec sec_count} {
|
||||
set last [expr {$st_sec + $sec_count}]
|
||||
set reg [expr {[read_memory 0x4006F000 32 1] & 0x7FFFFFFF}]
|
||||
write_memory 0x4006F000 32 [expr {$reg | 0x8}] ;#set writing mode ERASE
|
||||
|
||||
for {set i $st_sec} {$i < $last} {incr i} {
|
||||
check_readiness
|
||||
echo -n [format "\rErasing sector 0x%02x = offset 0x%04x" [expr {$i}] [expr {$i*512}] ]
|
||||
write_memory 0x4006F004 32 [expr {$i << 7}] ;#set address in flash
|
||||
write_memory 0x4006F010 32 0x01 ;#do it
|
||||
}
|
||||
check_readiness
|
||||
write_memory 0x4006F000 32 $reg
|
||||
}
|
||||
|
||||
proc wipe_rom {} {
|
||||
#This will wipe everything including bootloader
|
||||
global _SECTOR_SIZE
|
||||
global _FLASH_SIZE
|
||||
unlock_rom
|
||||
select_region 0
|
||||
if {[rom_mask_off] != 4} {
|
||||
echo "\nROM Masking failed to disable!"
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
wipe_sector_range 0 [expr {$_FLASH_SIZE / $_SECTOR_SIZE}]
|
||||
}
|
||||
|
||||
proc binary_to_int {data} {
|
||||
# Complète la chaîne à 4 octets si nécessaire
|
||||
set data $data[string repeat \xFF [expr {4 - [string length $data]}]]
|
||||
|
||||
# Initialise le résultat à 0
|
||||
set result 0
|
||||
|
||||
# Parcourt les octets et assemble l'entier
|
||||
for {set i 0} {$i < 4} {incr i} {
|
||||
# Récupère l'octet à la position $i
|
||||
set byte [scan [string index $data $i] %c]
|
||||
# Décale l'octet en fonction de l'ordre Little Endian
|
||||
set result [expr {$result | ($byte & 0xFF) << (8 * $i)}]
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
proc write_image {filename offset} {
|
||||
global _SECTOR_SIZE
|
||||
global _FLASH_SIZE
|
||||
set fs [file size $filename]
|
||||
set fd [open $filename "rb"]
|
||||
set reg [expr {[read_memory 0x4006F000 32 1] & 0x7FFFFFFF}]
|
||||
write_memory 0x4006F000 32 [expr {$reg | 0x4}] ;#set writing mode PROGRAM
|
||||
while {![eof $fd]} {
|
||||
if {($offset+4) > $_FLASH_SIZE} {
|
||||
echo "\nData exceeds main storage capacity!"
|
||||
write_memory 0x4006F000 32 $reg
|
||||
lock_rom
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
check_readiness
|
||||
set data [read $fd 4]
|
||||
set data $data[string repeat \xFF [expr {4-[string length $data]}]] ;#padding
|
||||
#binary scan $data i i_data
|
||||
set i_data [binary_to_int $data]
|
||||
write_memory 0x4006F004 32 [expr {($offset>>2)+0xC000}] ;#set destination offset
|
||||
write_memory 0x4006F008 32 $i_data ;#set word
|
||||
write_memory 0x4006F010 32 0x01 ;#set OPSTART=1
|
||||
while {([read_memory 0x4006F014 32 1] & 4) == 0} {}
|
||||
echo -n [format "\rProgrammed up to 0x%04x (FLASH_ADDR=0x%04x)" $offset [expr {($offset>>2)+0xC000}]]
|
||||
incr offset 4
|
||||
}
|
||||
check_readiness
|
||||
write_memory 0x4006F000 32 $reg ;#reset writing mode to OFF
|
||||
}
|
||||
|
||||
proc flash_blocks {filename address nblocks offset} {
|
||||
#Intended for speed. Due to tight timings, sometimes it works, sometimes it does not. Needs clocks adjusting there.
|
||||
global _SECTOR_SIZE
|
||||
global _FLASH_SIZE
|
||||
|
||||
if {($nblocks != 0) & [expr {$nblocks & 1}]} {
|
||||
set nblocks [expr {$nblocks + 1}]
|
||||
}
|
||||
set addr [expr {$_SECTOR_SIZE * ($address >> 9)}]
|
||||
set fs [expr {((($_SECTOR_SIZE*$nblocks)/2 + $_SECTOR_SIZE-1)&(0x10000000-$_SECTOR_SIZE))}]
|
||||
set fd [open $filename "rb"]
|
||||
|
||||
read $fd $addr
|
||||
set addr [expr {$addr + $offset}] ;#apply ROM offset
|
||||
set reg [expr {[read_memory 0x4006F000 32 1] & 0x7FFFFFFF}]
|
||||
|
||||
echo -n [format "\tWiping %02d sectors, starting at %02d " [expr {$nblocks / 2}] [expr {$addr >> 9}]]
|
||||
|
||||
wipe_sector_range [expr {$addr >> 9}] [expr {$nblocks / 2}] ;#wipe related sectors
|
||||
echo "\nRegion cleared OK"
|
||||
|
||||
echo [format "%02d bytes to push" $fs]; ##DEBUG
|
||||
write_memory 0x4006F000 32 [expr {$reg | 0x4}] ;#set writing mode PROGRAM
|
||||
|
||||
while {$fs > 0} {
|
||||
write_memory 0x4006F004 32 [expr {0xC000+(($addr)>>2)}] ;#set block starting offset
|
||||
set i_buffer {}
|
||||
for {set blk 0} {$blk < $_SECTOR_SIZE/2} {incr blk 4} {
|
||||
set data [read $fd 4]
|
||||
set data $data[string repeat \xFF [expr {4-[string length $data]}]] ;#padding to desired ending block
|
||||
if {($addr+$_SECTOR_SIZE/2) >= $_FLASH_SIZE} {
|
||||
echo [format "\nMain firmware image upper boundary reached (%d)!" $addr]
|
||||
write_memory 0x4006F000 32 $reg ;#reset writing mode to OFF
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
binary scan $data i i_data
|
||||
lappend i_buffer [expr {$i_data & 0xFFFFFFFF}]
|
||||
incr fs -4
|
||||
}
|
||||
echo [format "\nWriting at offset 0x%04x" [expr {$addr}]]
|
||||
##for {set bi 0} {$bi < 64} {incr bi} {echo -n [format "%08x" [lindex $i_buffer $bi]]}; #DEBUG
|
||||
write_memory 0x4006F008 32 [lindex $i_buffer 0] ;#prepare 1st word: we need to be quick beyond this point
|
||||
check_readiness
|
||||
write_memory 0x4006F010 32 0x01
|
||||
for {set bi 1} {$bi < 64} {incr bi} {while {([read_memory 0x4006F014 32 1] & 0x4) == 4} {write_memory 0x4006F008 32 [lindex $i_buffer $bi]}}
|
||||
check_readiness
|
||||
incr addr $_SECTOR_SIZE/2 ;# Next block
|
||||
}
|
||||
write_memory 0x4006F000 32 $reg ;#reset writing mode to OFF
|
||||
echo [format "\nLast write was 0x%08x " [lindex $i_buffer 63]]
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
|
||||
proc toggle_pin_gpioa {pin} {
|
||||
write_memory 0x40060000 16 [expr {[read_memory 0x40060000 16 1] ^(1<<$pin) }]
|
||||
}
|
||||
|
||||
proc toggle_pin_gpiob {pin} {
|
||||
write_memory 0x40060800 16 [expr {[read_memory 0x40060800 16 1] ^(1<<$pin) }]
|
||||
}
|
||||
|
||||
proc toggle_pin_gpioc {pin} {
|
||||
write_memory 0x40061000 16 [expr {[read_memory 0x40061000 16 1] ^(1<<$pin) }]
|
||||
}
|
||||
|
||||
proc set_pin_gpioa {pin value} {
|
||||
if {$value == 0} {
|
||||
write_memory 0x40060000 16 [expr {[read_memory 0x40060000 16 1] &~(1<<$pin) }]
|
||||
} else {
|
||||
write_memory 0x40060000 16 [expr {[read_memory 0x40060000 16 1] |(1<<$pin) }]
|
||||
}
|
||||
}
|
||||
|
||||
proc set_pin_gpiob {pin value} {
|
||||
if {$value == 0} {
|
||||
write_memory 0x40060800 16 [expr {[read_memory 0x40060800 16 1] &~(1<<$pin) }]
|
||||
} else {
|
||||
write_memory 0x40060800 16 [expr {[read_memory 0x40060800 16 1] |(1<<$pin) }]
|
||||
}
|
||||
}
|
||||
|
||||
proc set_pin_gpioc {pin value} {
|
||||
if {$value == 0} {
|
||||
write_memory 0x40061000 16 [expr {[read_memory 0x40061000 16 1] &~(1<<$pin) }]
|
||||
} else {
|
||||
write_memory 0x40061000 16 [expr {[read_memory 0x40061000 16 1] |(1<<$pin) }]
|
||||
}
|
||||
}
|
||||
|
||||
##Quansheng UVK5-specific snippets
|
||||
|
||||
proc uv_fastflash_bl {filename} {
|
||||
write_memory 0x4006F024 32 0x4E02A300 ;#force stock timings, just in case
|
||||
write_memory 0x4006F028 32 0x210360
|
||||
write_memory 0x4006F000 32 0x1
|
||||
check_readiness
|
||||
select_region 0
|
||||
if {[rom_mask_off] != 4} {
|
||||
echo "\nROM Masking failed to disable!"
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
reset halt
|
||||
unlock_rom
|
||||
|
||||
flash_blocks $filename 0 16 0
|
||||
|
||||
#just relock flashROM
|
||||
lock_rom
|
||||
}
|
||||
|
||||
proc uv_fastflash_fw {filename} {
|
||||
#Make sure bootloader is hidden
|
||||
if {[rom_mask_on] != 6} {
|
||||
echo "\nROM Masking failed to enable!"
|
||||
close $fd
|
||||
return
|
||||
}
|
||||
reset halt
|
||||
unlock_rom
|
||||
|
||||
flash_blocks $filename 0 [expr {[file size $filename] >> 8}] 0
|
||||
reset
|
||||
echo "\nCPU reset: Transceiver should boot now."
|
||||
}
|
||||
|
||||
proc uv_flash_bl {filename} {
|
||||
#Securely rewrites bootloader (slowly)
|
||||
|
||||
if {[file size $filename] > 0x1000} {
|
||||
echo [format "Bootloader image is too large to fit!]
|
||||
return
|
||||
}
|
||||
select_region 0
|
||||
if {[rom_mask_off] != 4} {
|
||||
echo "\nROM Masking failed to disable!"
|
||||
return
|
||||
}
|
||||
reset halt
|
||||
unlock_rom
|
||||
|
||||
wipe_sector_range 0 8
|
||||
echo "\nRegion cleared OK"
|
||||
|
||||
write_image $filename 0
|
||||
|
||||
if {[rom_mask_on] != 6} {
|
||||
echo "\nROM Masking failed to enable!"
|
||||
lock_rom
|
||||
return
|
||||
}
|
||||
#relock flashROM, in case conventional method for fw is preferred
|
||||
lock_rom
|
||||
echo "\nBootloader code programmed.\nYou can use uv_flash_fw to program main firmware, or just use stock tool to do it."
|
||||
}
|
||||
|
||||
proc uv_flash_fw {filename} {
|
||||
#Securely rewrites main firmware (slowly)
|
||||
|
||||
select_region 0
|
||||
#Make sure bootloader is hidden
|
||||
if {[rom_mask_on] != 6} {
|
||||
echo "\nROM Masking failed to enable!"
|
||||
return
|
||||
}
|
||||
reset halt
|
||||
unlock_rom
|
||||
|
||||
wipe_sector_range 0 120
|
||||
echo "\nRegion cleared OK"
|
||||
|
||||
write_image $filename 0
|
||||
|
||||
#relock flashROM, then reset CPU
|
||||
lock_rom
|
||||
reset
|
||||
echo "\nCPU reset: Transceiver should boot now."
|
||||
}
|
||||
|
||||
proc uv_flashlight_toggle {} {
|
||||
toggle_pin_gpioc 3 ;# toggles PORTC.3
|
||||
}
|
||||
|
||||
proc uv_flashlight_on {} {
|
||||
set_pin_gpioc 3 1 ;# set PORTC.3 high
|
||||
}
|
||||
|
||||
proc uv_flashlight_off {} {
|
||||
set_pin_gpioc 3 0 ;# set PORTC.3 to low
|
||||
}
|
||||
|
||||
proc uv_backlight_toggle {} {
|
||||
toggle_pin_gpiob 6 ;# toggles PORTB.6
|
||||
}
|
||||
|
||||
init
|
||||
#reset halt
|
||||
@@ -0,0 +1,34 @@
|
||||
# ARM Debug Interface V5 (ADI_V5) utility
|
||||
# ... Mostly for SWJ-DP (not SW-DP or JTAG-DP, since
|
||||
# SW-DP and JTAG-DP targets don't need to switch based
|
||||
# on which transport is active.
|
||||
#
|
||||
# declare a JTAG or SWD Debug Access Point (DAP)
|
||||
# based on the transport in use with this session.
|
||||
# You can't access JTAG ops when SWD is active, etc.
|
||||
|
||||
# params are currently what "jtag newtap" uses
|
||||
# because OpenOCD internals are still strongly biased
|
||||
# to JTAG .... but for SWD, "irlen" etc are ignored,
|
||||
# and the internals work differently
|
||||
|
||||
# for now, ignore non-JTAG and non-SWD transports
|
||||
# (e.g. initial flash programming via SPI or UART)
|
||||
|
||||
# split out "chip" and "tag" so we can someday handle
|
||||
# them more uniformly irlen too...)
|
||||
|
||||
if [catch {transport select}] {
|
||||
echo "Error: unable to select a session transport. Can't continue."
|
||||
shutdown
|
||||
}
|
||||
|
||||
proc swj_newdap {chip tag args} {
|
||||
if [using_hla] {
|
||||
eval hla newtap $chip $tag $args
|
||||
} elseif [using_jtag] {
|
||||
eval jtag newtap $chip $tag $args
|
||||
} elseif [using_swd] {
|
||||
eval swd newdap $chip $tag $args
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# ARM Debug Interface V5 (ADI_V5) utility
|
||||
# ... Mostly for SWJ-DP (not SW-DP or JTAG-DP, since
|
||||
# SW-DP and JTAG-DP targets don't need to switch based
|
||||
# on which transport is active.
|
||||
#
|
||||
# declare a JTAG or SWD Debug Access Point (DAP)
|
||||
# based on the transport in use with this session.
|
||||
# You can't access JTAG ops when SWD is active, etc.
|
||||
|
||||
# params are currently what "jtag newtap" uses
|
||||
# because OpenOCD internals are still strongly biased
|
||||
# to JTAG .... but for SWD, "irlen" etc are ignored,
|
||||
# and the internals work differently
|
||||
|
||||
# for now, ignore non-JTAG and non-SWD transports
|
||||
# (e.g. initial flash programming via SPI or UART)
|
||||
|
||||
# split out "chip" and "tag" so we can someday handle
|
||||
# them more uniformly irlen too...)
|
||||
|
||||
if [catch {transport select}] {
|
||||
echo "Error: unable to select a session transport. Can't continue."
|
||||
shutdown
|
||||
}
|
||||
|
||||
proc swj_newdap {chip tag args} {
|
||||
if [using_jtag] {
|
||||
eval jtag newtap $chip $tag $args
|
||||
} elseif [using_swd] {
|
||||
eval swd newdap $chip $tag $args
|
||||
} else {
|
||||
echo "Error: transport '[ transport select ]' not supported by swj_newdap"
|
||||
shutdown
|
||||
}
|
||||
}
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
openocd -f ./interface/stlink.cfg -f ./target/dp32g030.cfg -c "init; reset halt; uv_flash_bl bootloader.bin; shutdown"
|
||||
Reference in new issue
Block a user