Skip to content

Instantly share code, notes, and snippets.

@natschil
Created December 13, 2023 08:23
Show Gist options
  • Save natschil/12f90320ff3c2a70711f378eef7738cb to your computer and use it in GitHub Desktop.
Save natschil/12f90320ff3c2a70711f378eef7738cb to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import sys,time
import base64
jump_table = bytearray()
irom1 = bytearray()
xip = bytearray()
compiler = ['ARM','GCC'][1]
if compiler == 'ARM':
infile = './bin/Lenze_rf.hex'
SZ = '1454'
print(f'Flashing firmware produced with Keil: {infile}')
elif compiler == 'GCC':
infile = './build/Lenze_RF.hex'
SZ = '0858'
print(f'Flashing firmware produced with GCC: {infile}')
with open(infile) as f:
# hex file order is assumed to be ER_ROM_XIP - JUMP_TABLE - ER_IROM1
sections = ['JUMP_TABLE','ER_IROM1','XIP']
infiles = [jump_table,irom1,xip]
infile_current = -1
inbuf = None
for line in f:
if line[7:9] == '04':
infile_current += 1
print(f'Start of new ihex section found, assuming {sections[infile_current]}')
inbuf = infiles[infile_current]
elif line[7:9] == '00':
inbuf.extend(bytearray.fromhex(line[9:-3]))
c0 = bytearray() # hexf header
c0.extend(bytearray.fromhex(f'03000000FFFFFFFF3818FF1FFFFFFFFF')) # RF only code has only 2 ihex sections
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
c0.extend(bytearray.fromhex(f'00000200FFFF000000000211FFFFFFFF'))
c0.extend(bytearray.fromhex(f'00500000FFFF00000000FF1FFFFFFFFF'))
c0.extend(bytearray.fromhex(f'{SZ}0000FFFF00003818FF1FFFFFFFFF'))
c0[-44:-42] = int.to_bytes(len(xip), 2, 'little') # length ER_ROM_XIP
c0[-28:-26] = int.to_bytes(len(jump_table), 2, 'little') # length JUMP_TABLE
c0[-12:-10] = int.to_bytes(len(irom1), 2, 'little') # length ER_IROM1
c1 = bytearray() # JUMP_TABLE + ER_IROM1
c1.extend(jump_table)
c1.extend(bytearray.fromhex('0' *16))
c1.extend(irom1)
c2 = bytearray()
c2.extend(xip)
c = [c0,c1,c2]
#c_test = c0
#c_test.extend(c1)
#with open('test.hexf', 'w') as f:
# j = 512
# for i in range(0, len(c_test), 16):
# row = ':1' + int.to_bytes(j, 2, 'big').hex().upper() + '000' + c_test[i:i+16].hex().upper()
# f.write(row)
# f.write(hex((sum(bytearray.fromhex(row[1:])) % 256) - (1<<8))[-2:].upper().replace('X','0') + '\n') #UGLY!
# if j == 529:
# j = 1280
# else:
# j += 1
# f.close()
#exit(0)
import serial
uart = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.01, inter_byte_timeout=0.01)
res = uart.read(10)
while not res.endswith(b'cmd>>:'):
uart.write(b'UXTDWU')
time.sleep(0.05)
res = uart.read(10)
if res: print(res)
print('RESET MODE activated. Changing baudrate to 115200')
uart.baudrate = 115200
print('Erase + Write')
cmds = []
cmds.append(b'er512') # erase
cmds.append(b'rdrev+')
cmds.append(b'wrreg4000c890 ab000001 ')
cmds.append(b'wrreg4000c838 ff010005 ')
cmds.append(b'spifs 0 1 3 0 ')
cmds.append(b'sfmod 2 2 ')
cmds.append(b'cpnum ffffffff ')
cmds.append(b'cpbin c0 002000 ' + b'%x' % len(c0) + b' 11002000')
cmds.append(b'cpbin c1 005000 ' + b'%x' % len(c1) + b' 11005000')
cmds.append(b'cpbin c2 020000 ' + b'%x' % len(c2) + b' 11020000')
for cmd in cmds:
uart.write(cmd)
print('sent', cmd)
while not uart.in_waiting:
time.sleep(0.3)
msg = uart.read(uart.in_waiting)
print('Response is:', msg)
if cmd[5:9] in [b' c0 ', b' c1 ', b' c2 ']:
cfile = cmd[7] -48
data = c[cfile]
ldata = uart.write(data)
print('sent c%d (len=%d)' % (cfile, ldata))
while not uart.in_waiting:
time.sleep(0.3)
msg = uart.read(uart.in_waiting)
print('Response is:', msg)
uart.write(b'%08x' % sum(data))
print('sent checksum')
while not uart.in_waiting:
time.sleep(0.3)
msg = uart.read(uart.in_waiting)
print('Response is:', msg)
/* Linker script to configure memory regions. */
MEMORY
{
JUMP_TABLE (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x400
GLOBAL_CONFIG (rwx) : ORIGIN = 0x1FFF0400, LENGTH = 0x400
FLASH (rx) : ORIGIN = 0x1FFF1838, LENGTH = 0x4000
RAM (rwx) : ORIGIN = 0x1FFF6000, LENGTH = 0x2000
XIP (rw) : ORIGIN = 0x11020000, LENGTH = 0x4000
}
ENTRY(Reset_Handler)
SECTIONS
{
.jump_table_mem_area :
{
KEEP(*(.jump_table_mem_area))
} > JUMP_TABLE
.global_config_area :
{
KEEP(*(.global_config_area))
} > GLOBAL_CONFIG
.text :
{
KEEP(*(.vectors))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.xip :
{
*(.xip)
} > XIP
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* Location counter can end up 2byte aligned with narrow Thumb code but
__etext is assumed by startup code to be the LMA of a section in RAM
which must be 4byte aligned */
__etext = ALIGN (4);
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__end__ = .;
PROVIDE(end = .);
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contain any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
*(.stack*)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__initial_sp = ORIGIN(RAM) + LENGTH(RAM);
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment