Misc. fixes and improvements
Abstracted break and continue, added missing constant for WDT, improved command routine compatibility.
This commit is contained in:
parent
b04dc85f36
commit
aa18c27fff
45
iapy.py
45
iapy.py
@ -4,23 +4,38 @@ import time
|
|||||||
# get the current inferior, i.e. the connection to target
|
# get the current inferior, i.e. the connection to target
|
||||||
inferior = gdb.selected_inferior()
|
inferior = gdb.selected_inferior()
|
||||||
|
|
||||||
|
def target_break():
|
||||||
|
if inferior.threads()[0].is_running():
|
||||||
|
gdb.execute(interrupt)
|
||||||
|
|
||||||
|
def target_continue():
|
||||||
|
t = inferior.threads()
|
||||||
|
if not(inferior.threads()[0].is_running()):
|
||||||
|
gdb.execute('continue')
|
||||||
|
|
||||||
def target_u32read(address, endian='little'):
|
def target_u32read(address, endian='little'):
|
||||||
|
target_break()
|
||||||
value = inferior.read_memory(address, 4)
|
value = inferior.read_memory(address, 4)
|
||||||
return int.from_bytes(value, byteorder=endian)
|
return int.from_bytes(value, byteorder=endian)
|
||||||
|
|
||||||
def target_u32write(address, value, endian='little'):
|
def target_u32write(address, value, endian='little'):
|
||||||
|
target_break()
|
||||||
data = value.to_bytes(4, byteorder=endian) # Adjust byteorder as needed
|
data = value.to_bytes(4, byteorder=endian) # Adjust byteorder as needed
|
||||||
inferior.write_memory(address, data)
|
inferior.write_memory(address, data)
|
||||||
|
|
||||||
def target_regset(name, value):
|
def target_regset(name, value):
|
||||||
|
target_break()
|
||||||
gdb.execute(f'set ${name} = {value}')
|
gdb.execute(f'set ${name} = {value}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def target_prepare():
|
def target_prepare():
|
||||||
"""
|
"""
|
||||||
Prepares the target for IAP operations.
|
Prepares the target for IAP operations.
|
||||||
This implementation is an example for the LPC546xx series of chips.
|
This implementation is an example for the LPC546xx series of chips.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
LPC546XX_WDT_MODE = 0x4000C000
|
||||||
LPC546XX_WDT_PERIOD_MAX = 0xFFFFFF
|
LPC546XX_WDT_PERIOD_MAX = 0xFFFFFF
|
||||||
LPC546XX_WDT_PROTECT = (1 << 4)
|
LPC546XX_WDT_PROTECT = (1 << 4)
|
||||||
LPC546XX_MAINCLKSELA = 0x40000280
|
LPC546XX_MAINCLKSELA = 0x40000280
|
||||||
@ -28,7 +43,10 @@ def target_prepare():
|
|||||||
LPC546XX_AHBCLKDIV = 0x40000380
|
LPC546XX_AHBCLKDIV = 0x40000380
|
||||||
LPC546XX_FLASHCFG = 0x40000400
|
LPC546XX_FLASHCFG = 0x40000400
|
||||||
|
|
||||||
gdb.execute('interrupt')
|
gdb.execute('set mem inaccessible-by-default off')
|
||||||
|
target_break()
|
||||||
|
gdb.Breakpoint("*0x00020000")
|
||||||
|
gdb.Breakpoint("*0x00020001")
|
||||||
# check if watchdog timer's on
|
# check if watchdog timer's on
|
||||||
wdt_mode = target_u32read(LPC546XX_WDT_MODE)
|
wdt_mode = target_u32read(LPC546XX_WDT_MODE)
|
||||||
# if WDT on, we can't disable it, but we may be able to set a long period
|
# if WDT on, we can't disable it, but we may be able to set a long period
|
||||||
@ -44,8 +62,10 @@ def target_prepare():
|
|||||||
# recommended default configuration
|
# recommended default configuration
|
||||||
target_u32write(LPC546XX_FLASHCFG, 0x1A)
|
target_u32write(LPC546XX_FLASHCFG, 0x1A)
|
||||||
|
|
||||||
|
|
||||||
def iap_command(a0, a1=0, a2=0, a3=0, a4=0):
|
def iap_command(a0, a1=0, a2=0, a3=0, a4=0):
|
||||||
gdb.execute('interrupt')
|
print(f"IAPy: Command {a0} {a1} {a2} {a3} {a4}")
|
||||||
|
target_break()
|
||||||
# setup request
|
# setup request
|
||||||
target_u32write(0x2000ffa0, a0)
|
target_u32write(0x2000ffa0, a0)
|
||||||
target_u32write(0x2000ffa4, a1)
|
target_u32write(0x2000ffa4, a1)
|
||||||
@ -61,17 +81,25 @@ def iap_command(a0, a1=0, a2=0, a3=0, a4=0):
|
|||||||
target_u32write(0x2000ffd0, 0xAAAAAAAA)
|
target_u32write(0x2000ffd0, 0xAAAAAAAA)
|
||||||
|
|
||||||
# call setup
|
# call setup
|
||||||
|
target_break()
|
||||||
target_regset('lr', 0x00020001)
|
target_regset('lr', 0x00020001)
|
||||||
target_regset('r0', 0x2000ffa0)
|
target_regset('r0', 0x2000ffa0)
|
||||||
target_regset('r1', 0x2000ffc0)
|
target_regset('r1', 0x2000ffc0)
|
||||||
target_regset('pc', 0x03000205)
|
# set PC
|
||||||
target_regset('primask', 1)
|
gdb.execute('jump *0x03000205')
|
||||||
target_regset('msp', 0x2000ffa0)
|
# use PSP instead because MSP is most-likely not accessible
|
||||||
|
target_regset('psp', 0x2000ffa0)
|
||||||
|
target_regset('control', 0x2)
|
||||||
|
|
||||||
# execute and wait
|
# execute and wait
|
||||||
gdb.execute('continue')
|
target_continue()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# restore execution to MSP
|
||||||
|
target_break()
|
||||||
|
target_regset('msp', 0x2000ffa0)
|
||||||
|
target_regset('control', 0x0)
|
||||||
|
|
||||||
# gather results
|
# gather results
|
||||||
res0 = target_u32read(0x2000ffc0)
|
res0 = target_u32read(0x2000ffc0)
|
||||||
res1 = target_u32read(0x2000ffc4)
|
res1 = target_u32read(0x2000ffc4)
|
||||||
@ -88,7 +116,4 @@ def iap_flash_sector_erase(start_sector, end_sector, sysclk=12000):
|
|||||||
iap_command(50, start_sector, end_sector)
|
iap_command(50, start_sector, end_sector)
|
||||||
# erase sectors
|
# erase sectors
|
||||||
iap_command(52, start_sector, end_sector, sysclk)
|
iap_command(52, start_sector, end_sector, sysclk)
|
||||||
gdb.execute('interrupt')
|
target_break()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user