gdbflasher 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/gdbflasher +76 -0
- data/gdbflasher.gemspec +19 -0
- data/helper_sources/Makefile +22 -0
- data/helper_sources/stm32f10xx_hd.S +115 -0
- data/helper_sources/stm32f10xx_hd.lds +25 -0
- data/helper_sources/stm32f10xx_md.S +115 -0
- data/helper_sources/stm32f10xx_md.lds +25 -0
- data/helper_sources/stm32f4xx.S +109 -0
- data/helper_sources/stm32f4xx.lds +25 -0
- data/helper_sources/stm32l1xx.S +101 -0
- data/helper_sources/stm32l1xx.lds +25 -0
- data/helpers/stm32f10xx_hd.hex +12 -0
- data/helpers/stm32f10xx_hd.sym +7 -0
- data/helpers/stm32f10xx_md.hex +12 -0
- data/helpers/stm32f10xx_md.sym +7 -0
- data/helpers/stm32f4xx.hex +13 -0
- data/helpers/stm32f4xx.sym +7 -0
- data/helpers/stm32l1xx.hex +12 -0
- data/helpers/stm32l1xx.sym +7 -0
- data/lib/gdbflasher/cortexm.rb +19 -0
- data/lib/gdbflasher/ihex.rb +189 -0
- data/lib/gdbflasher/mcu/stm32f10xx_hd.rb +17 -0
- data/lib/gdbflasher/mcu/stm32f10xx_md.rb +17 -0
- data/lib/gdbflasher/mcu/stm32f4xx.rb +25 -0
- data/lib/gdbflasher/mcu/stm32l1xx.rb +21 -0
- data/lib/gdbflasher/mcu.rb +208 -0
- data/lib/gdbflasher/server_connection.rb +334 -0
- data/lib/gdbflasher/version.rb +3 -0
- data/lib/gdbflasher.rb +21 -0
- metadata +93 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
.set PAGE_SIZE, 256
|
2
|
+
|
3
|
+
.set FLASH_BASE, 0x40023C00
|
4
|
+
|
5
|
+
.set FLASH_ACR, 0x00
|
6
|
+
.set FLASH_PECR, 0x04
|
7
|
+
.set FLASH_PDKEYR, 0x08
|
8
|
+
.set FLASH_PEKEYR, 0x0C
|
9
|
+
.set FLASH_PRGKEYR, 0x10
|
10
|
+
.set FLASH_OPTKEYR, 0x14
|
11
|
+
.set FLASH_SR, 0x18
|
12
|
+
|
13
|
+
.globl trap
|
14
|
+
.globl initialize
|
15
|
+
.globl finalize
|
16
|
+
.globl erase
|
17
|
+
.globl program
|
18
|
+
.globl page_buffer
|
19
|
+
.globl PAGE_SIZE
|
20
|
+
|
21
|
+
.arch armv7-m
|
22
|
+
.syntax unified
|
23
|
+
.thumb
|
24
|
+
.text
|
25
|
+
|
26
|
+
trap:
|
27
|
+
nop
|
28
|
+
|
29
|
+
initialize:
|
30
|
+
ldr R7, =FLASH_BASE
|
31
|
+
|
32
|
+
ldr R0, =0x89ABCDEF
|
33
|
+
str R0, [R7, #FLASH_PEKEYR]
|
34
|
+
ldr R0, =0x02030405
|
35
|
+
str R0, [R7, #FLASH_PEKEYR]
|
36
|
+
|
37
|
+
ldr R0, =0x8C9DAEBF
|
38
|
+
str R0, [R7, #FLASH_PRGKEYR]
|
39
|
+
ldr R0, =0x13141516
|
40
|
+
str R0, [R7, #FLASH_PRGKEYR]
|
41
|
+
|
42
|
+
bx LR
|
43
|
+
|
44
|
+
finalize:
|
45
|
+
mov R0, #7
|
46
|
+
str R0, [R7, #FLASH_PECR]
|
47
|
+
|
48
|
+
bx LR
|
49
|
+
|
50
|
+
erase:
|
51
|
+
mov R1, #0x20C
|
52
|
+
str R1, [R7, #FLASH_PECR]
|
53
|
+
|
54
|
+
1:ldr R1, [R7, #FLASH_SR]
|
55
|
+
tst R1, #1
|
56
|
+
bne 1b
|
57
|
+
|
58
|
+
mov R1, #0
|
59
|
+
str R1, [R0]
|
60
|
+
|
61
|
+
1:ldr R1, [R7, #FLASH_SR]
|
62
|
+
tst R1, #1
|
63
|
+
bne 1b
|
64
|
+
and R0, R1, #0xF00
|
65
|
+
|
66
|
+
mov R1, #4
|
67
|
+
str R1, [R7, #FLASH_PECR]
|
68
|
+
|
69
|
+
bx LR
|
70
|
+
|
71
|
+
program:
|
72
|
+
ldr R1, [R7, #FLASH_SR]
|
73
|
+
tst R1, #1
|
74
|
+
bne program
|
75
|
+
|
76
|
+
ldr R4, =page_buffer
|
77
|
+
mov R2, #0
|
78
|
+
|
79
|
+
1:
|
80
|
+
ldr R3, [R4, R2]
|
81
|
+
str R3, [R0, R2]
|
82
|
+
|
83
|
+
2:ldr R1, [R7, #FLASH_SR]
|
84
|
+
tst R1, #1
|
85
|
+
bne 2b
|
86
|
+
ands R1, R1, #0xF00
|
87
|
+
bne 1f
|
88
|
+
|
89
|
+
add R2, #4
|
90
|
+
cmp R2, #PAGE_SIZE
|
91
|
+
blo 1b
|
92
|
+
|
93
|
+
1:
|
94
|
+
mov R0, R1
|
95
|
+
bx LR
|
96
|
+
|
97
|
+
|
98
|
+
.bss
|
99
|
+
page_buffer:
|
100
|
+
.fill PAGE_SIZE, 1
|
101
|
+
.size page_buffer, . - page_buffer
|
@@ -0,0 +1,25 @@
|
|
1
|
+
OUTPUT_FORMAT(elf32-littlearm)
|
2
|
+
|
3
|
+
MEMORY
|
4
|
+
{
|
5
|
+
sram : ORIGIN = 0x20000000, LENGTH = 10K
|
6
|
+
}
|
7
|
+
|
8
|
+
SECTIONS
|
9
|
+
{
|
10
|
+
.text : {
|
11
|
+
*(.text)
|
12
|
+
|
13
|
+
. = ALIGN(4);
|
14
|
+
|
15
|
+
*(.rodata)
|
16
|
+
} > sram
|
17
|
+
|
18
|
+
. = ALIGN(4);
|
19
|
+
|
20
|
+
.bss : {
|
21
|
+
*(.bss)
|
22
|
+
} > sram
|
23
|
+
|
24
|
+
. = ALIGN(4);
|
25
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
:020000042000DA
|
2
|
+
:1000000000BF1C4F1C4878601C48786070474FF058
|
3
|
+
:10001000800139617047396941F0020139617861C5
|
4
|
+
:1000200041F040013961FA6812F0010FFBD121F073
|
5
|
+
:100030004201396102F01400FA607047396941F0F9
|
6
|
+
:10004000010139610E4C4FF00002A35A8352F96846
|
7
|
+
:1000500011F0010FFBD1F96011F0140104D102F18C
|
8
|
+
:100060000202B2F5006FF0D33A6922F001023A6160
|
9
|
+
:10007000084670470020024023016745AB89EFCD59
|
10
|
+
:0400800084000020D8
|
11
|
+
:0400000520000000D7
|
12
|
+
:00000001FF
|
@@ -0,0 +1,12 @@
|
|
1
|
+
:020000042000DA
|
2
|
+
:1000000000BF1C4F1C4878601C48786070474FF058
|
3
|
+
:10001000800139617047396941F0020139617861C5
|
4
|
+
:1000200041F040013961FA6812F0010FFBD121F073
|
5
|
+
:100030004201396102F01400FA607047396941F0F9
|
6
|
+
:10004000010139610E4C4FF00002A35A8352F96846
|
7
|
+
:1000500011F0010FFBD1F96011F0140104D102F18C
|
8
|
+
:100060000202B2F5806FF0D33A6922F001023A61E0
|
9
|
+
:10007000084670470020024023016745AB89EFCD59
|
10
|
+
:0400800084000020D8
|
11
|
+
:0400000520000000D7
|
12
|
+
:00000001FF
|
@@ -0,0 +1,13 @@
|
|
1
|
+
:020000042000DA
|
2
|
+
:1000000000BF214F214878602148786070474FF049
|
3
|
+
:10001000004038617047F96811F4803FFBD14FF020
|
4
|
+
:10002000F001F9601B4A4FEAC00141EA020139615F
|
5
|
+
:1000300041F480313961F86810F4803FFBD100F061
|
6
|
+
:10004000F0004FF0000139617047F96811F4803F0A
|
7
|
+
:10005000FBD1114939614FF0F001F9600F4C4FF0BD
|
8
|
+
:100060000002A3588350F96811F4803FFBD111F0CE
|
9
|
+
:10007000F00104D102F10402B2F5804FF1D3084639
|
10
|
+
:100080004FF0000139617047003C02402301674591
|
11
|
+
:10009000AB89EFCD0202000001020000A0000020A9
|
12
|
+
:0400000520000000D7
|
13
|
+
:00000001FF
|
@@ -0,0 +1,12 @@
|
|
1
|
+
:020000042000DA
|
2
|
+
:1000000000BF1C4F1C48F8601C48F8601C48386151
|
3
|
+
:100010001C48386170474FF00700786070474FF414
|
4
|
+
:1000200003717960B96911F0010FFBD14FF0000144
|
5
|
+
:100030000160B96911F0010FFBD101F470604FF05C
|
6
|
+
:10004000040179607047B96911F0010FFBD10E4CC2
|
7
|
+
:100050004FF00002A3588350B96911F0010FFBD192
|
8
|
+
:1000600011F4706104D102F10402B2F5807FF1D382
|
9
|
+
:1000700008467047003C0240EFCDAB8905040302FF
|
10
|
+
:0C008000BFAE9D8C161514138C000020E0
|
11
|
+
:0400000520000000D7
|
12
|
+
:00000001FF
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module GdbFlasher
|
2
|
+
class IHex
|
3
|
+
class Record
|
4
|
+
attr_accessor :length, :address, :type, :data
|
5
|
+
|
6
|
+
TYPES = {
|
7
|
+
0 => :data,
|
8
|
+
1 => :eof,
|
9
|
+
4 => :extended_address,
|
10
|
+
5 => :start_address
|
11
|
+
}
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@length = nil
|
15
|
+
@address = nil
|
16
|
+
@type = nil
|
17
|
+
@data = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
@length == @data.length
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse(line)
|
25
|
+
if line.match(/^:([0-9a-fA-F]{2})+$/).nil?
|
26
|
+
raise "Malformed Intel Hex line: #{line}"
|
27
|
+
end
|
28
|
+
|
29
|
+
line.slice! 0
|
30
|
+
|
31
|
+
bytes = Array.new(line.length / 2) { |i| line[i * 2..i * 2 + 1].hex }
|
32
|
+
|
33
|
+
record = Record.new
|
34
|
+
record.length = bytes[0]
|
35
|
+
record.address = (bytes[1] << 8) | bytes[2]
|
36
|
+
record.type = TYPES[bytes[3]]
|
37
|
+
record.data = bytes[4..-2].pack("C*")
|
38
|
+
|
39
|
+
checksum = (~bytes.reduce(:+) + 1) & 0xFF
|
40
|
+
|
41
|
+
if !record.valid? || record.type.nil? || checksum != 0
|
42
|
+
raise "Malformed Intel Hex line: #{line}"
|
43
|
+
end
|
44
|
+
|
45
|
+
record
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Segment
|
50
|
+
attr_accessor :base, :data
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@base = 0
|
54
|
+
@data = ""
|
55
|
+
end
|
56
|
+
|
57
|
+
def size
|
58
|
+
@data.length
|
59
|
+
end
|
60
|
+
|
61
|
+
def intersect(region_base, region_end)
|
62
|
+
if region_base == region_end
|
63
|
+
raise ArgumentError, "Region is empty"
|
64
|
+
end
|
65
|
+
|
66
|
+
segment_range = @base...@base + size
|
67
|
+
region_range = region_base..region_end
|
68
|
+
|
69
|
+
intersection_base = nil, intersection_end = nil
|
70
|
+
|
71
|
+
if segment_range.cover? region_range.min
|
72
|
+
intersection_base = region_range.min
|
73
|
+
elsif region_range.cover? segment_range.min
|
74
|
+
intersection_base = segment_range.min
|
75
|
+
else
|
76
|
+
return Segment.new
|
77
|
+
end
|
78
|
+
|
79
|
+
if segment_range.cover? region_range.max
|
80
|
+
intersection_end = region_range.max
|
81
|
+
elsif region_range.cover? segment_range.max
|
82
|
+
intersection_end = segment_range.max
|
83
|
+
else
|
84
|
+
return Segment.new
|
85
|
+
end
|
86
|
+
|
87
|
+
segment = Segment.new
|
88
|
+
segment.base = intersection_base
|
89
|
+
segment.data = @data[intersection_base - @base..intersection_end - @base]
|
90
|
+
|
91
|
+
segment
|
92
|
+
end
|
93
|
+
|
94
|
+
def pad_segment!(psize, fill_byte = 0x00)
|
95
|
+
if @base % size != 0
|
96
|
+
padding = size - (@base % size)
|
97
|
+
|
98
|
+
@base -= padding
|
99
|
+
@data = ([ fill_byte ] * padding).pack("C*") + @data
|
100
|
+
end
|
101
|
+
|
102
|
+
if @data.size % size != 0
|
103
|
+
padding = size - (@data.size % size)
|
104
|
+
|
105
|
+
@data += ([ fill_byte ] * padding).pack "C*"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
attr_accessor :segments
|
112
|
+
|
113
|
+
def initialize
|
114
|
+
@segments = []
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.load(stream)
|
118
|
+
high_address = 0
|
119
|
+
lines = {}
|
120
|
+
|
121
|
+
stream.each_line do |line|
|
122
|
+
line.rstrip!
|
123
|
+
|
124
|
+
record = Record.parse line
|
125
|
+
|
126
|
+
case record.type
|
127
|
+
when :eof
|
128
|
+
break
|
129
|
+
|
130
|
+
when :extended_address
|
131
|
+
high_address, = record.data.unpack "n"
|
132
|
+
|
133
|
+
when :data
|
134
|
+
lines[(high_address << 16) | record.address] = record.data
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
segment = nil
|
139
|
+
ihex = self.new
|
140
|
+
|
141
|
+
lines.sort_by { |k1,v1,k2,b2| k1 <=> k2 }.each do |address, data|
|
142
|
+
if segment.nil? || segment.base + segment.size != address
|
143
|
+
segment = Segment.new
|
144
|
+
segment.base = address
|
145
|
+
segment.data = data
|
146
|
+
|
147
|
+
ihex.segments << segment
|
148
|
+
else
|
149
|
+
segment.data += data
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
ihex
|
154
|
+
end
|
155
|
+
|
156
|
+
def split_segments!(size, fill_byte = 0x00)
|
157
|
+
pad_segments! size, fill_byte
|
158
|
+
|
159
|
+
i = 0
|
160
|
+
|
161
|
+
while i < @segments.length
|
162
|
+
segment = @segments[i]
|
163
|
+
parts = segment.size / size
|
164
|
+
|
165
|
+
for j in 1...parts do
|
166
|
+
new_segment = Segment.new
|
167
|
+
new_segment.base = segment.base + size * j
|
168
|
+
new_segment.data = segment.data[j * size...(j + 1) * size]
|
169
|
+
|
170
|
+
@segments.insert i + j, new_segment
|
171
|
+
end
|
172
|
+
|
173
|
+
segment.data = segment.data[0...size]
|
174
|
+
|
175
|
+
i += parts
|
176
|
+
end
|
177
|
+
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
def pad_segments!(size, fill_byte = 0x00)
|
182
|
+
@segments.each do |segment|
|
183
|
+
segment.pad_segment! size, fill_byte
|
184
|
+
end
|
185
|
+
|
186
|
+
self
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GdbFlasher
|
2
|
+
class Stm32f10xxHD < CortexM
|
3
|
+
|
4
|
+
SECTORS = (0...256).map { |i| [ 0x08000000 + 2048 * i, 0x08000000 + 2048 * (i + 1) - 1 ] }
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def helper_name
|
9
|
+
"stm32f10xx_hd"
|
10
|
+
end
|
11
|
+
|
12
|
+
def erase(sector_index)
|
13
|
+
call_helper :erase, SECTORS[sector_index][0]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GdbFlasher
|
2
|
+
class Stm32f10xxMD < CortexM
|
3
|
+
|
4
|
+
SECTORS = (0...128).map { |i| [ 0x08000000 + 1024 * i, 0x08000000 + 1024 * (i + 1) - 1 ] }
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def helper_name
|
9
|
+
"stm32f10xx_md"
|
10
|
+
end
|
11
|
+
|
12
|
+
def erase(sector_index)
|
13
|
+
call_helper :erase, SECTORS[sector_index][0]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GdbFlasher
|
2
|
+
class Stm32f4xx < CortexM
|
3
|
+
SECTORS = [
|
4
|
+
[ 0x08000000, 0x08003FFF ], # Sector 0, 16 KiB
|
5
|
+
[ 0x08004000, 0x08007FFF ], # Sector 1, 16 KiB
|
6
|
+
[ 0x08008000, 0x0800BFFF ], # Sector 2, 16 KiB
|
7
|
+
[ 0x0800C000, 0x0800FFFF ], # Sector 3, 16 KiB
|
8
|
+
[ 0x08010000, 0x0801FFFF ], # Sector 4, 64 KiB
|
9
|
+
[ 0x08020000, 0x0803FFFF ], # Sector 5, 64 KiB
|
10
|
+
[ 0x08040000, 0x0805FFFF ], # Sector 6, 64 KiB
|
11
|
+
[ 0x08060000, 0x0807FFFF ], # Sector 7, 64 KiB
|
12
|
+
[ 0x08080000, 0x0809FFFF ], # Sector 8, 64 KiB
|
13
|
+
[ 0x080A0000, 0x080BFFFF ], # Sector 9, 64 KiB
|
14
|
+
[ 0x080C0000, 0x080DFFFF ], # Sector 10, 64 KiB
|
15
|
+
[ 0x080E0000, 0x080FFFFF ], # Sector 11, 64 KiB
|
16
|
+
]
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def helper_name
|
21
|
+
"stm32f4xx"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GdbFlasher
|
2
|
+
class Stm32l1xx < CortexM
|
3
|
+
|
4
|
+
SECTORS = (0...512).map { |i| [ 0x08000000 + 256 * i, 0x08000000 + 256 * (i + 1) - 1 ] }
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def helper_name
|
9
|
+
"stm32l1xx"
|
10
|
+
end
|
11
|
+
|
12
|
+
def erase(sector_index)
|
13
|
+
call_helper :erase, SECTORS[sector_index][0]
|
14
|
+
end
|
15
|
+
|
16
|
+
def blank_byte
|
17
|
+
0x00
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|