Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CCS
Manage
Activity
Members
Plan
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Marko Mecina
CCS
Commits
86fd6fff
Commit
86fd6fff
authored
2 months ago
by
Marko Mecina
Browse files
Options
Downloads
Patches
Plain Diff
add stand-alone SREC and segment generator
parent
f01c4cf9
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
Ccs/tools/segment_gen.py
+225
-0
225 additions, 0 deletions
Ccs/tools/segment_gen.py
with
225 additions
and
0 deletions
Ccs/tools/segment_gen.py
0 → 100755
+
225
−
0
View file @
86fd6fff
#!/usr/bin/env python3
"""
Utility functions for generating SREC file and segmented image from IASW binary
"""
import
crcmod
import
io
import
os
import
struct
import
sys
SEG_HEADER_FMT
=
'
>III
'
SEG_HEADER_LEN
=
struct
.
calcsize
(
SEG_HEADER_FMT
)
SEG_SPARE_LEN
=
2
SEG_CRC_LEN
=
2
SKIP_BYTES
=
65536
SREC_MAX_BYTES_PER_LINE
=
250
SREC_BYTES_PER_LINE
=
32
MAX_PKT_LEN
=
504
S13_OVERHEAD_BYTES
=
24
START_ADDR
=
0x60040000
# start address of IASW in RAM
MEM_ADDR
=
0x40000000
# address where the data is uploaded to
SEGID
=
0x200B0101
# ID for data segments, see DBS UM
SEGMENT_LEN
=
464
# segment size, including header and CRC
puscrc
=
crcmod
.
predefined
.
mkPredefinedCrcFun
(
'
crc-ccitt-false
'
)
def
source_to_srec
(
binary
,
outfile
,
memaddr
,
header
=
None
,
bytes_per_line
=
SREC_BYTES_PER_LINE
,
skip_bytes
=
SKIP_BYTES
):
"""
:param binary:
:param outfile:
:param memaddr:
:param header:
:param bytes_per_line:
:param skip_bytes:
:return:
"""
if
bytes_per_line
>
SREC_MAX_BYTES_PER_LINE
:
raise
ValueError
(
"
Maximum number of bytes per line is {}!
"
.
format
(
SREC_MAX_BYTES_PER_LINE
))
if
isinstance
(
binary
,
str
):
binary
=
open
(
binary
,
'
rb
'
).
read
()
if
not
isinstance
(
binary
,
bytes
):
raise
TypeError
data
=
binary
[
skip_bytes
:]
if
header
is
None
:
fname
=
outfile
.
split
(
'
/
'
)[
-
1
][
-
60
:]
header
=
'
S0{:02X}0000{:}
'
.
format
(
len
(
fname
.
encode
(
'
ascii
'
))
+
3
,
fname
.
encode
(
'
ascii
'
).
ljust
(
24
).
hex
().
upper
())
header
+=
'
{:02X}
'
.
format
(
srec_chksum
(
header
[
2
:]))
datalen
=
len
(
data
)
data
=
io
.
BytesIO
(
data
)
sreclist
=
[]
terminator
=
'
S705{:08X}
'
.
format
(
memaddr
)
terminator
+=
'
{:02X}
'
.
format
(
srec_chksum
(
terminator
[
2
:]))
while
data
.
tell
()
<
datalen
:
chunk
=
data
.
read
(
bytes_per_line
)
chunklen
=
len
(
chunk
)
line
=
'
{:02X}{:08X}{:}
'
.
format
(
chunklen
+
5
,
memaddr
,
chunk
.
hex
().
upper
())
# add chksum according to SREC standard
line
=
'
S3
'
+
line
+
'
{:02X}
'
.
format
(
srec_chksum
(
line
))
sreclist
.
append
(
line
)
memaddr
+=
chunklen
with
open
(
outfile
,
'
w
'
)
as
fd
:
fd
.
write
(
header
+
'
\n
'
)
fd
.
write
(
'
\n
'
.
join
(
sreclist
)
+
'
\n
'
)
fd
.
write
(
terminator
)
print
(
'
SREC written to file:
"
{}
"
, skipped first {} bytes.
'
.
format
(
os
.
path
.
abspath
(
outfile
),
skip_bytes
))
def
srec_chksum
(
x
:
str
):
"""
SREC line checksum
"""
return
sum
(
bytes
.
fromhex
(
x
))
&
0xff
^
0xff
def
srec_to_segments
(
fname
,
memaddr
,
segid
,
linesperpack
=
50
,
max_pkt_size
=
MAX_PKT_LEN
):
# payload_len = max_pkt_size - S13_OVERHEAD_BYTES - SEG_CRC_LEN - SEG_SPARE_LEN - SEG_HEADER_LEN
payload_len
=
SEGMENT_LEN
-
SEG_CRC_LEN
-
SEG_SPARE_LEN
-
SEG_HEADER_LEN
segments
=
[]
f
=
open
(
fname
,
'
r
'
).
readlines
()[
1
:]
lines
=
[
p
[
12
:
-
3
]
for
p
in
f
]
startaddr
=
int
(
f
[
0
][
4
:
12
],
16
)
upload_bytes
=
b
''
linecount
=
0
bcnt
=
0
pcnt
=
0
while
linecount
<
len
(
f
)
-
1
:
linepacklist
=
[]
for
n
in
range
(
linesperpack
):
if
linecount
>=
(
len
(
lines
)
-
1
):
break
if
(
len
(
''
.
join
(
linepacklist
))
+
len
(
lines
[
linecount
]))
//
2
>
payload_len
:
# ensure max_pkt_size
break
linepacklist
.
append
(
lines
[
linecount
])
linelength
=
len
(
lines
[
linecount
])
//
2
if
int
(
f
[
linecount
+
1
][
4
:
12
],
16
)
!=
(
int
(
f
[
linecount
][
4
:
12
],
16
)
+
linelength
):
linecount
+=
1
newstartaddr
=
int
(
f
[
linecount
][
4
:
12
],
16
)
break
else
:
linecount
+=
1
newstartaddr
=
int
(
f
[
linecount
][
4
:
12
],
16
)
linepack
=
bytes
.
fromhex
(
''
.
join
(
linepacklist
))
dlen
=
len
(
linepack
)
bcnt
+=
dlen
# segment header, see IWF DBS HW SW ICD
data
=
struct
.
pack
(
SEG_HEADER_FMT
,
segid
,
startaddr
,
dlen
//
4
)
+
linepack
+
bytes
(
SEG_SPARE_LEN
)
data
=
data
+
puscrc
(
data
).
to_bytes
(
SEG_CRC_LEN
,
'
big
'
)
segments
.
append
((
memaddr
,
data
))
# collect all uploaded segments for CRC at the end
upload_bytes
+=
data
pcnt
+=
1
startaddr
=
newstartaddr
memaddr
+=
len
(
data
)
endsegment
=
bytes
(
SEG_HEADER_LEN
)
segments
.
append
((
memaddr
,
endsegment
))
# return total length of uploaded data (without termination segment) and CRC over entire image, including segment headers
return
segments
,
len
(
upload_bytes
),
puscrc
(
upload_bytes
)
def
segment_data
(
data
,
segid
,
addr
,
seglen
=
SEGMENT_LEN
):
"""
Split data into segments (as defined in IWF DPU HW SW ICD) with segment header and CRC.
Segment data has to be two-word aligned.
:param data:
:param segid:
:param addr:
:param seglen:
:return: list of segments
"""
if
isinstance
(
data
,
str
):
data
=
open
(
data
,
'
rb
'
).
read
()
if
not
isinstance
(
data
,
bytes
):
raise
TypeError
datalen
=
len
(
data
)
if
datalen
%
4
:
raise
ValueError
(
'
Data length is not two-word aligned
'
)
data
=
io
.
BytesIO
(
data
)
segments
=
[]
segaddr
=
addr
while
data
.
tell
()
<
datalen
:
chunk
=
data
.
read
(
seglen
-
(
SEG_HEADER_LEN
+
SEG_SPARE_LEN
+
SEG_CRC_LEN
))
chunklen
=
len
(
chunk
)
if
chunklen
%
4
:
raise
ValueError
(
'
Segment data length is not two-word aligned
'
)
sdata
=
struct
.
pack
(
SEG_HEADER_FMT
,
segid
,
segaddr
,
chunklen
//
4
)
+
chunk
+
bytes
(
SEG_SPARE_LEN
)
sdata
+=
puscrc
(
sdata
).
to_bytes
(
SEG_CRC_LEN
,
'
big
'
)
segments
.
append
(
sdata
)
segaddr
+=
chunklen
upload_bytes
=
b
''
.
join
(
segments
)
# add 12 byte termination segment
segments
.
append
(
bytes
(
SEG_HEADER_LEN
))
return
segments
,
len
(
upload_bytes
),
puscrc
(
upload_bytes
)
def
run
(
binary
):
# generate SREC file
srec_fn
=
binary
+
"
.srec
"
source_to_srec
(
binary
,
srec_fn
,
START_ADDR
,
skip_bytes
=
SKIP_BYTES
)
# generate segments from SREC file
segments
,
ul_size
,
ul_crc
=
srec_to_segments
(
srec_fn
,
MEM_ADDR
,
SEGID
)
segdir
=
os
.
path
.
abspath
(
binary
)
+
"
_segments
"
os
.
makedirs
(
segdir
,
exist_ok
=
True
)
# write segments and meta data
meta
=
[
"
# IDX
\t
ADDR
\t
CRC
"
]
for
i
,
seg
in
enumerate
(
segments
,
1
):
with
open
(
os
.
path
.
join
(
segdir
,
'
seg_{:04d}.bin
'
.
format
(
i
)),
'
wb
'
)
as
fd
:
fd
.
write
(
seg
[
1
])
meta
.
append
(
'
{:04d}
\t
{:08X}
\t
{:04X}
'
.
format
(
i
,
seg
[
0
],
int
.
from_bytes
(
seg
[
1
][
-
2
:],
'
big
'
)))
with
open
(
os
.
path
.
join
(
segdir
,
'
segments.dat
'
),
'
w
'
)
as
fd
:
fd
.
write
(
'
\n
'
.
join
(
meta
))
print
(
'
Segments written to:
"
{}
"'
.
format
(
segdir
))
print
(
'
{} bytes total, CRC = {:04X}
'
.
format
(
ul_size
,
ul_crc
))
if
__name__
==
"
__main__
"
:
binary
=
sys
.
argv
[
1
]
run
(
binary
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment