iapy/iapy.py

95 lines
2.8 KiB
Python

import gdb
import time
# get the current inferior, i.e. the connection to target
inferior = gdb.selected_inferior()
def target_u32read(address, endian='little'):
value = inferior.read_memory(address, 4)
return int.from_bytes(value, byteorder=endian)
def target_u32write(address, value, endian='little'):
data = value.to_bytes(4, byteorder=endian) # Adjust byteorder as needed
inferior.write_memory(address, data)
def target_regset(name, value):
gdb.execute(f'set ${name} = {value}')
def target_prepare():
"""
Prepares the target for IAP operations.
This implementation is an example for the LPC546xx series of chips.
"""
LPC546XX_WDT_PERIOD_MAX = 0xFFFFFF
LPC546XX_WDT_PROTECT = (1 << 4)
LPC546XX_MAINCLKSELA = 0x40000280
LPC546XX_MAINCLKSELB = 0x40000284
LPC546XX_AHBCLKDIV = 0x40000380
LPC546XX_FLASHCFG = 0x40000400
gdb.execute('interrupt')
# check if watchdog timer's on
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_mode and not(wdt_mode & LPC546XX_WDT_PROTECT)):
target_u32write(LPC546XX_WDT_CNT, LPC546XX_WDT_PERIOD_MAX)
# SYSCLK: 12MHz FRO
target_u32write(LPC546XX_MAINCLKSELA, 0)
# use MAINCLKSELA
target_u32write(LPC546XX_MAINCLKSELB, 0)
# div by 1
target_u32write(LPC546XX_AHBCLKDIV, 0)
# recommended default configuration
target_u32write(LPC546XX_FLASHCFG, 0x1A)
def iap_command(a0, a1=0, a2=0, a3=0, a4=0):
gdb.execute('interrupt')
# setup request
target_u32write(0x2000ffa0, a0)
target_u32write(0x2000ffa4, a1)
target_u32write(0x2000ffa8, a2)
target_u32write(0x2000ffac, a3)
target_u32write(0x2000ffb0, a4)
# clear result
target_u32write(0x2000ffc0, 0xAAAAAAAA)
target_u32write(0x2000ffc4, 0xAAAAAAAA)
target_u32write(0x2000ffc8, 0xAAAAAAAA)
target_u32write(0x2000ffcc, 0xAAAAAAAA)
target_u32write(0x2000ffd0, 0xAAAAAAAA)
# call setup
target_regset('lr', 0x00020001)
target_regset('r0', 0x2000ffa0)
target_regset('r1', 0x2000ffc0)
target_regset('pc', 0x03000205)
target_regset('primask', 1)
target_regset('msp', 0x2000ffa0)
# execute and wait
gdb.execute('continue')
time.sleep(0.5)
# gather results
res0 = target_u32read(0x2000ffc0)
res1 = target_u32read(0x2000ffc4)
res2 = target_u32read(0x2000ffc8)
res3 = target_u32read(0x2000ffcc)
res4 = target_u32read(0x2000ffd0)
return res0,res1,res2,res3,res4
def iap_flash_sector_erase(start_sector, end_sector, sysclk=12000):
print(f"IAPy: Erasing sectors {start_sector} to {end_sector}")
target_prepare()
# prepare sectors
iap_command(50, start_sector, end_sector)
# erase sectors
iap_command(52, start_sector, end_sector, sysclk)
gdb.execute('interrupt')