-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathload.py
More file actions
executable file
·127 lines (106 loc) · 4.73 KB
/
load.py
File metadata and controls
executable file
·127 lines (106 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python
import sys, os, io, time
import subprocess
import serial
from elftools.elf.elffile import ELFFile
SERIAL_PORT = '/dev/ttyUSB2'
SERIAL_BAUD = 115200
ENTRY_THREAD_NAME = 'app_thread'
THREAD_PC_OFFSET = 1
MAX_NAME_LENGTH = 31
def __find_address(elffile, name):
dwarfinfo = elffile.get_dwarf_info()
for CU in dwarfinfo.iter_CUs():
for DIE in CU.iter_DIEs():
try:
if DIE.tag == 'DW_TAG_subprogram' and DIE.attributes['DW_AT_name'].value == name:
return int(DIE.attributes['DW_AT_low_pc'].value) + THREAD_PC_OFFSET
except KeyError: continue
raise RuntimeError('Symbol "%s" not found' % name)
def __main():
# Get the LD parameters
if len(sys.argv) < 7:
raise ValueError('Command line:\n\tappname hexpath stacklen ldexe ldscript ldoself ldmap ldobjelf ldobj*\nGiven:\n\t' + str(sys.argv))
appname = sys.argv[1].strip()[:MAX_NAME_LENGTH]
hexpath = sys.argv[2]
stacklen = int(sys.argv[3][3:], 16) if sys.argv[3].strip().lower()[0:2] == '0x' else int(sys.argv[3])
ldexe = sys.argv[4]
ldscript = sys.argv[5]
ldoself = sys.argv[6]
ldmap = sys.argv[7]
ldobjelf = sys.argv[8]
ldobjs = sys.argv[9:]
# Get the length of each section
pgmlen, bsslen, datalen = 0, 0, 0
with open(ldobjelf, 'rb') as f:
elffile = ELFFile(f)
for section in elffile.iter_sections():
if section.name == '.text': pgmlen = int(section['sh_size'])
elif section.name == '.bss': bsslen = int(section['sh_size'])
elif section.name == '.data': datalen = int(section['sh_size'])
# Open the serial port
ser = serial.Serial(SERIAL_PORT, SERIAL_BAUD)
sio = io.TextIOWrapper(buffer = io.BufferedRWPair(ser, ser, 1),
newline = '\r\n',
line_buffering = True,
encoding = 'ascii')
try:
sio.write(unicode('\n\n'))
time.sleep(0.1)
while ser.inWaiting():
ser.flushInput()
time.sleep(0.1)
sio.write(unicode('app_install\n'))
print '"' + sio.readline() + '"'
# Send the section sizes and app name
sizestr = '%0.8X,%0.8X,%0.8X,%0.8X,%0.2X%s' % (pgmlen, bsslen, datalen, stacklen, len(appname), appname)
print sizestr
sio.write(unicode(sizestr + '\n'))
# Receive the allocated addresses
addrs = sio.readline().split(',')
pgmadr = int(addrs[0].strip(), 16)
bssadr = int(addrs[1].strip(), 16)
dataadr = int(addrs[2].strip(), 16)
datapgmadr = int(addrs[3].strip(), 16)
# Link to the OS symbols
sectopt = [ '--section-start', '.text=0x%0.8X' % pgmadr,
'--section-start', '.bss=0x%0.8X' % bssadr,
'--section-start', '.data=0x%0.8X' % dataadr ]
args = [ ldexe, '--script', ldscript, '--just-symbols', ldoself, '-Map', ldmap, '-o', ldobjelf ] + sectopt + ldobjs
print args
subprocess.call(args)
subprocess.call(['make'])
with open(ldobjelf, 'rb') as f:
elffile = ELFFile(f)
threadadr = __find_address(elffile, ENTRY_THREAD_NAME)
print 'app_thread = 0x%0.8X' % threadadr
# Read the generated IHEX file and remove unused records
with open(hexpath, 'r') as f:
hexdata = f.readlines()
hexdata = [ line.strip() for line in hexdata if not line[7:9] in [ '05', '03' ] and len(line) >= 11 ]
hexdata = [ line for line in hexdata if len(line) > 0 ]
if len([ None for line in hexdata if line[7:9] == '01' ]) != 1 and hexdata[-1][7:9] != '01':
raise RuntimeError('The IHEX must contain a single EOF record, as last record')
# Insert the entry point thread record
chks = threadadr & 0xFFFFFFFF
chks = (chks >> 24) + (chks >> 16) + (chks >> 8) + (chks & 0xFF)
chks = 0x100 - (0x04 + 0x00 + 0x00 + 0x05 + chks) & 0xFF
hexdata[0:0] = [ ':04000005%0.8X%0.2X' % (threadadr, chks) ]
# Send IHEX records
for i in range(len(hexdata)):
line = sio.readline().strip()
print line
if line != ',':
raise RuntimeError('Error while loading line %d ("%s", received "%s")' % (i, hexdata[i], line))
sio.write(unicode(hexdata[i] + '\n'))
print hexdata[i]
line = sio.readline().strip()
print line
if line != '$':
raise RuntimeError('Error while terminating programming (received "%s")' % line)
ser.close()
except:
ser.close()
raise
if __name__ == '__main__':
__main()