-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathembed-mrb.rb
More file actions
executable file
·130 lines (116 loc) · 3.15 KB
/
embed-mrb.rb
File metadata and controls
executable file
·130 lines (116 loc) · 3.15 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
127
128
129
130
#! /usr/bin/env ruby
#
# ./embed-mrb.rb MICROBIT.hex mrbapp.mrb 00060000
#
# constants
DEF_START_ADDR = 0x00060000 # default start address to embed
LINE_BYTES = 16 # bytes per line
LINE_TERM = "\r\n"
FNAME_SUFFIX = "-mruby"
# get arguments
if ARGV.length < 2
puts "Usage: #{$0} hex mrb [addr]"
puts " hex: Target Intel HEX file."
puts " mrb: MRB (mruby binary) file to embed."
puts " addr: Start address to embed MRB. (default: 0x#{DEF_START_ADDR.to_s(16)})"
exit 0
end
$src_hex = ARGV[0] # Source HEX file name
$dst_hex = $src_hex.dup
$dst_hex[-File.extname($dst_hex).length, 0] = FNAME_SUFFIX # Dest. HEX file
$mrb_file = ARGV[1] # MRB file name
$start_addr = ARGV.length > 2 ? ARGV[2].to_i(16) : DEF_START_ADDR # Start address
# add_checksum(bin) #=> Array
# <args>
# bin: Binary array to calculate checksum
# <return>
# binaries array
def add_checksum(bin)
sum = bin.inject(:+) # bin.sum (Ruby 2.5~)
bin << (0x100 - (sum & 0xff))
end
# hex_line(bin) #=> String
# <args>
# bin: Binary array to change HEX string
# <return>
# HEX string with line termination
def hex_line(bin)
hex = ":"
bin.each {|b| hex += sprintf("%02X", b)}
hex + LINE_TERM
end
# make_segment_header(addr) #=> String
# <args>
# addr: segment address
# <return>
# HEX string of segment header
def make_segment_header(addr)
# len, adrH, ADRL, seg
bin = [0x02, 0x00, 0x00, 0x02]
addr >>= 4
bin << ((addr >> 8) & 0xff) # Segment address (H)
bin << (addr & 0xff) # Segment address (L)
add_checksum(bin)
hex_line(bin)
end
# # segment address record
# bin = []
# bin << 0x02 # length
# bin << 0x00 # addr(H)
# bin << 0x00 # addr(L)
# bin << 0x02 # segment address
# bin << (($start_addr >> 12) & 0xff)
# bin << (($start_addr >> 4) & 0xff)
# # sum = bin.inject(:+)
# # bin << 0x100 - (sum & 0xff)
# add_checksum(bin)
# p bin
# p hex = hex_line(bin)
# get_mrb_hex(mrb_file, addr) #=> String
# <args>
# mrb_file: MRB file name.
# addr: Destination address for MRB.
# <return>
# Intel HEX string of MRB.
def get_mrb_hex(mrb_file, addr)
# segment header
hex = make_segment_header(addr)
# p hex
File.open(mrb_file, 'rb') {|f|
offset = 0
until f.eof?
chunk = f.read(LINE_BYTES)
# length, seg addr(H), seg addr(L), data bin
bin = [chunk.length, (offset >> 8) & 0xff, offset & 0xff, 0x00] + chunk.bytes
add_checksum(bin)
# p bin
hex += hex_line(bin)
offset += LINE_BYTES
end
}
hex
rescue => e
p e
end
# # mrb
# mrb = File.open(ARGV[0], 'rb') {|f|
# offset = 0
# until f.eof?
# bin = f.read(LINE_BYTES)
# p bin
# bin = [bin.length, (offset >> 8) & 0xff, offset & 0xff, 0x00] + bin.bytes
# add_checksum(bin)
# hex += hex_line(bin)
# offset += LINE_BYTES
# end
# }
# convert MRB to HEX
mrb_hex = get_mrb_hex($mrb_file, $start_addr)
# Read source HEX file
hex_lines = File.readlines($src_hex)
# Write destination HEX file
outhex = File.open($dst_hex, "w")
outhex.write hex_lines[0..-2].join # original HEX without end record
outhex.write mrb_hex # MRB segment
outhex.write hex_lines[-1] # end record
outhex.close