gdbflasher 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|