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.
@@ -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,7 @@
1
+ 00000800 PAGE_SIZE
2
+ 20000000 trap
3
+ 20000002 initialize
4
+ 2000000e finalize
5
+ 20000016 erase
6
+ 2000003c program
7
+ 20000084 page_buffer
@@ -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,7 @@
1
+ 00000400 PAGE_SIZE
2
+ 20000000 trap
3
+ 20000002 initialize
4
+ 2000000e finalize
5
+ 20000016 erase
6
+ 2000003c program
7
+ 20000084 page_buffer
@@ -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,7 @@
1
+ 00004000 PAGE_SIZE
2
+ 20000000 trap
3
+ 20000002 initialize
4
+ 2000000e finalize
5
+ 20000016 erase
6
+ 2000004a program
7
+ 200000a0 page_buffer
@@ -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,7 @@
1
+ 00000100 PAGE_SIZE
2
+ 20000000 trap
3
+ 20000002 initialize
4
+ 20000016 finalize
5
+ 2000001e erase
6
+ 20000046 program
7
+ 2000008c page_buffer
@@ -0,0 +1,19 @@
1
+ module GdbFlasher
2
+
3
+ class CortexM < MCU
4
+ protected
5
+
6
+ def initialize_environment
7
+ @connection.write_register 25, 0x01000000
8
+ end
9
+
10
+ def breakpoint_kind
11
+ 2 # Thumb-2 breakpoint
12
+ end
13
+
14
+ def lr_offset
15
+ 1
16
+ end
17
+ end
18
+
19
+ end
@@ -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