stm32 0.0.1

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/stm32_cli.rb +177 -0
  3. data/lib/stm32.rb +417 -0
  4. metadata +86 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 069d773b51764deb1d1f3e16dfc7c44efa9c42f0
4
+ data.tar.gz: 715b55b8a41a363284ceca662418f4c43c9c7b86
5
+ SHA512:
6
+ metadata.gz: 97b5432c8983db33acdcc1c87e26c5906b4865bac5d97d24b6ad021031a65877ff4d136e54f063dd39f9aa3c4999e82c9b6aeba544e0bc0a0f166beff9d83a0d
7
+ data.tar.gz: 342295cacada68c8f24a3bf707e89928e8c41c4924aa3991579a5fc14e0d93c43aa8cf7d594b9abffdf23badea8751be2d1e3be2fcbee3318ad5924bf5ab4c84
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env ruby
2
+ #encoding: UTF-8
3
+
4
+ require 'optparse'
5
+ require 'yaml'
6
+ require 'pp'
7
+
8
+ require 'io/wait'
9
+
10
+ local=false
11
+ require 'srec'
12
+
13
+ if File.file? './lib/stm32.rb'
14
+ require './lib/stm32.rb'
15
+ puts "using local lib"
16
+ local=true
17
+ else
18
+ require 'stm32'
19
+ end
20
+
21
+ def isprint(c)
22
+ /[[:print:]]/ === c.chr
23
+ end
24
+
25
+
26
+ options = {}
27
+ CONF_FILE='/etc/stm32.conf'
28
+
29
+ options=options.merge YAML::load_file(CONF_FILE) if File.exist?(CONF_FILE)
30
+ options=options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
31
+
32
+ options[:dev] = "/dev/ttyUSB0" if not options[:dev]
33
+ OptionParser.new do |opts|
34
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
35
+
36
+ opts.on("-v", "--[no-]verbose", "Run verbosely; creates protocol log on console (false)") do |v|
37
+ options[:verbose] = v
38
+ end
39
+ opts.on("-d", "--[no-]debug", "Produce Debug dump on verbose log (false)") do |v|
40
+ options[:debug] = v
41
+ end
42
+
43
+ opts.on("--dev dev", "serial device to use (/dev/ttyUSB0)") do |v|
44
+ options[:dev] = v
45
+ end
46
+ end.parse!
47
+
48
+ #pp options
49
+
50
+ stm=Stm32.new options
51
+
52
+ stm.get_port()
53
+ if stm.boot
54
+ stm.get_info
55
+ printf "BOOTED OK!\r\n>"
56
+ else
57
+ puts "Error: Boot failed! retry!\r\n"
58
+ end
59
+
60
+ #pp stm.run
61
+ port=stm.get_port
62
+ $stdout.sync = true
63
+ oldstate=:unknown
64
+ oldaddr=0x08000000
65
+ begin
66
+ state = `stty -g`
67
+ loop do
68
+ curstate=stm.get_state
69
+ if oldstate!=curstate
70
+ if curstate==:running
71
+ system("stty raw -echo -icanon isig") # turn raw input on
72
+ else
73
+ system "stty #{state}" # turn raw input off
74
+ end
75
+ oldstate=curstate
76
+ end
77
+ if port.ready_for_read?
78
+ ch = port.readbyte
79
+ if ch==0x0a and stm.get_state==:running
80
+ printf "\n\r"
81
+ elsif ch==0x0d and stm.get_state==:running
82
+
83
+ elsif ch>0x1f and stm.get_state==:running
84
+ printf "%c",ch
85
+ else
86
+ printf "[%02x]",ch
87
+ end
88
+ elsif $stdin.ready?
89
+ if curstate==:running #terminal mode
90
+ c = $stdin.getc
91
+ if c.ord==0x02
92
+ system "stty #{state}" # turn raw input off
93
+ if stm.boot
94
+ printf "BOOTED OK!\r\n>"
95
+ else
96
+ puts "Error: Boot failed! retry!\r\n"
97
+ end
98
+ #system("stty raw -echo -icanon isig") # turn raw input on
99
+ else
100
+ port.write c
101
+ end
102
+ else #debugger
103
+ c = $stdin.gets.chop
104
+ a=c.split " "
105
+ if a[0]=="g"
106
+ if stm.run
107
+ puts "RUN OK!\r\n"
108
+ else
109
+ puts "Error: Run failed! retry!\r\n"
110
+ end
111
+ #system("stty raw -echo -icanon isig") # turn raw input on
112
+ elsif a[0]=="i"
113
+ stm.get_info
114
+ elsif a[0]=="e"
115
+ if a[1]
116
+ b=a[1].hex
117
+ else
118
+ b=0
119
+ end
120
+ stm.erase [b]
121
+ elsif a[0]=="w" or a[0]=="wf"
122
+ if a[1]
123
+ addr=a[1].hex
124
+ else
125
+ addr=oldaddr
126
+ end
127
+ if a[2]
128
+ data=[a[2].to_i,0x11,0x22,0x33]
129
+ else
130
+ data=[1,2,3,4]
131
+ end
132
+ addr |= 0x08000000 if a[0]=="wf"
133
+ stm.write addr,data
134
+ oldaddr=addr
135
+ elsif a[0]=="f"
136
+ stm.flash("/home/arisi/projects/mygit/arisi/ctex/bin/sol_STM32L_mg11.srec")
137
+ elsif a[0]=="q"
138
+ break
139
+ elsif a[0]=="r" or a[0]=="rf"
140
+ if a[1]
141
+ addr=a[1].hex
142
+ else
143
+ addr=oldaddr
144
+ end
145
+ addr |= 0x08000000 if a[0]=="rf"
146
+ if a[2]
147
+ len=a[2].hex
148
+ else
149
+ len=0x100
150
+ end
151
+ buf=stm.read addr,len
152
+ #printf "0x%08X:",addr
153
+ if not buf
154
+ puts "Illegal address!"
155
+ else
156
+ buf.each_with_index do |b,i|
157
+ if i&0xf==0x0
158
+ printf "\n0x%08X: ",addr+i
159
+ end
160
+ printf "%02X ",b
161
+ end
162
+ printf "\n";
163
+ oldaddr=addr
164
+ end
165
+ #system("stty raw -echo -icanon isig") # turn raw input on
166
+ else
167
+ puts "Commands: g(o), i(d), w(rite), r(ead), e(rase), q(uit)"
168
+ end
169
+ printf "\r\n>"
170
+ end
171
+ else
172
+ sleep 0.01
173
+ end
174
+ end
175
+ ensure
176
+ system "stty #{state}" # turn raw input off
177
+ end
@@ -0,0 +1,417 @@
1
+ #!/usr/bin/env ruby
2
+ #encoding: UTF-8
3
+
4
+ require 'json'
5
+ require 'serialport'
6
+ #require 'srec'
7
+
8
+ class IO
9
+ def ready_for_read?
10
+ result = IO.select([self], nil, nil, 0)
11
+ result && (result.first.first == self)
12
+ end
13
+ end
14
+
15
+
16
+ class Stm32
17
+ @port=nil
18
+ @dev=nil
19
+ @state=nil
20
+ @cpu_info={}
21
+ @debug=true
22
+ @@Clist_def=[0x00,0x01,0x02,0x11,0x21,0x31,0x44,0x63,0x73,0x82,0x92]
23
+ @@Commands={
24
+ get: {index:0},
25
+ getver: {index:1},
26
+ getid: {index:2},
27
+ read: {index:3},
28
+ go: {index:4},
29
+ write: {index:5},
30
+ erase: {index:6},
31
+ }
32
+ @@Cpu_ids={
33
+ 0x416 => {
34
+ family: :L1,
35
+ ram_s:0x20000800,
36
+ ram_e:0x20004000,
37
+ flash_s:0x8000000,
38
+ flash_e:0x08020000,
39
+ flash_bsize:0x100,
40
+ serno:0x1ff80050,
41
+ flash_initial:0
42
+ },
43
+ 0x413 => {family: :F4,ram_s:0x20002000,ram_e:0x20020000,flash_s:0x8000000,flash_e:0x08100000,flash_blk:16384,serno:0x1fff7a10,flash_initial:0xff},
44
+ }
45
+
46
+ def initialize(hash={})
47
+ @clist=@@Clist_def
48
+ @debug=hash[:debug]
49
+ if not hash[:dev]
50
+ puts "Error: No serial Device??"
51
+ return nil
52
+ end
53
+ if not File.chardev? hash[:dev]
54
+ puts "Error: '#{hash[:dev]}'' is not serial Device??"
55
+ return nil
56
+ end
57
+ begin
58
+ @port = SerialPort.new hash[:dev],115200,8,1,SerialPort::NONE
59
+ #$sp.read_timeout = 100
60
+ @port.flow_control= SerialPort::NONE
61
+ @port.binmode
62
+ @port.sync = true
63
+ rescue => e
64
+ puts "Error: Cannot open serial device: #{e}"
65
+ pp e.backtrace
66
+ return nil
67
+ end
68
+ @dev=hash[:dev]
69
+ puts "Open Serial OK!" if @debug
70
+ end
71
+ def get_port()
72
+ @port
73
+ end
74
+ def get_dev()
75
+ @dev
76
+ end
77
+ def get_state()
78
+ @state
79
+ end
80
+ def get_cpu(k)
81
+ @cpu_info[k]
82
+ end
83
+
84
+ def flush_chars tout=0.1
85
+ while ch=wait_char(tout) do
86
+ puts "\nWarning: Flushed #{ch.to_s(16)}\n"
87
+ end
88
+ end
89
+
90
+ def send_cmd cmd,ack=true
91
+ if not @@Commands[cmd] or not @@Commands[cmd][:index]
92
+ puts "Error: Unknown command #{cmd}"
93
+ end
94
+ if not c=@clist[@@Commands[cmd][:index]]
95
+ puts "Error: Unsupported command #{cmd}"
96
+ end
97
+ retries=0
98
+ flush_chars 0.001
99
+ while retries<2 do
100
+ ch=send_buf [c,0xff-c],ack
101
+ if ack
102
+ if not ch
103
+ return :tout
104
+ elsif ch== :nack
105
+ printf("SYNC\r\n") if @debug
106
+ send_buf [32],false #synch!
107
+ flush_chars 0.1
108
+ else
109
+ return ch
110
+ end
111
+ else
112
+ return :ack
113
+ end
114
+ end
115
+ :nack
116
+ end
117
+
118
+ def send_addr a,ack=true
119
+ buf=[0,0,0,0]
120
+ check=0
121
+ 4.times do |i|
122
+ c=a&0xff
123
+ a>>=8
124
+ buf[3-i] = c
125
+ check ^=c
126
+ end
127
+ buf << check
128
+ send_buf buf,ack
129
+ end
130
+
131
+ def send_buf_with_check buf,tout=0.1
132
+ check=0
133
+ buf.each do |b|
134
+ check ^=b
135
+ end
136
+ buf << check
137
+ send_buf buf,true,tout
138
+ end
139
+
140
+ def send_buf buf,ack=false,tout=0.1
141
+ bytes=buf.pack("c*")
142
+ printf "> " if @debug
143
+ bytes.split("").each do |ch|
144
+ @port.write ch
145
+ printf("%02X ",ch.ord) if @debug
146
+ sleep 0.0001
147
+ end
148
+ puts "" if @debug
149
+ if ack
150
+ ch=wait_char tout
151
+ if ch
152
+ if ch==0x1f
153
+ printf("< NACK: %02X\n",ch) if @debug
154
+ return nil
155
+ else
156
+ printf("< ACK: %02X\n",ch) if @debug
157
+ return :ack
158
+ end
159
+ return ch
160
+ else
161
+ puts "< TOUT"
162
+ return nil
163
+ end
164
+ end
165
+ return true
166
+ end
167
+
168
+ def wait_char tout=1
169
+ cnt=0
170
+ while cnt<tout*100
171
+ if @port.ready_for_read?
172
+ return @port.readbyte
173
+ end
174
+ sleep 0.01
175
+ cnt+=1
176
+ end
177
+ return nil
178
+ end
179
+
180
+ def boot
181
+ retries=0
182
+ delay=0.001
183
+ while retries<10
184
+ #$sp.rts=1 #if retries>5 #power off --really cold boot
185
+ #sleep 0.5
186
+ @port.rts=0 #if retries>5 #power off --really cold boot
187
+ @port.dtr=0
188
+ sleep delay
189
+ @port.flush_input
190
+ @port.flush_output
191
+ @port.rts=0 #power on
192
+ sleep delay
193
+ @port.dtr=1 #reset up -> start to run
194
+ ch=wait_char delay
195
+
196
+ if ch and ch==0
197
+ printf("OK: [%02x]", ch ) if @debug
198
+ sleep delay
199
+ end
200
+ send_buf [0x7f]
201
+ if ch=wait_char
202
+ if ch==0x79
203
+ puts "Booted OK, retries=#{retries}\n" if @debug
204
+ @state=:booted
205
+ return true
206
+ else
207
+ printf "Error:got strange ack: %02X '%c'\n",ch,ch
208
+ end
209
+ else
210
+ puts "Error: no cmd ack"
211
+ end
212
+ retries+=1
213
+ delay*=2
214
+ end
215
+ puts "Error:not booted, gave up\n"
216
+ return false
217
+ end
218
+
219
+ def wait_chars len,tout=0.1
220
+ ret=[]
221
+ len.times do
222
+ if ch=wait_char(tout)
223
+ ret << ch
224
+ else
225
+ puts "Warning: Short Data! #{ret}"
226
+ return nil
227
+ end
228
+ end
229
+ return ret
230
+ end
231
+
232
+ def cmd c
233
+ boot if @state!=:booted
234
+ puts "cmd: #{c}" if @debug
235
+ send_cmd c
236
+ if c==:write #no reply expected
237
+ return
238
+ end
239
+ if len=wait_char
240
+ len+=1
241
+ if buf=wait_chars(len)
242
+ if @debug
243
+ printf "len=#{len}:"
244
+ buf.each do |b|
245
+ printf "%02X ",b
246
+ end
247
+ printf "\n"
248
+ end
249
+ if ack=wait_char
250
+ if ack==0x79
251
+ return buf
252
+ else
253
+ puts "Error: no ack for cmd #{c} #{ack}"
254
+ end
255
+ else
256
+ puts "Error: tout at ack for #{c}"
257
+ end
258
+ else
259
+ puts "Error: timeout for #{c}"
260
+ end
261
+ end
262
+ end
263
+
264
+
265
+ def get_info
266
+ if buf=cmd(:get)
267
+ puts "BL ver: #{buf[0].to_s(16)}"
268
+ @clist=buf[1..-1]
269
+ #puts "Command list updated to #{@clist}"
270
+ end
271
+ if buf=cmd(:getid)
272
+ @cpu=buf[0]*0x100 + buf[1]
273
+ puts "Cpu ID: #{@cpu.to_s(16)}"
274
+ if @@Cpu_ids[@cpu]
275
+ @cpu_info=@@Cpu_ids[@cpu]
276
+ printf "Family: %s\n", @cpu_info[:family]
277
+ printf "Ram: %08X .. %08X %5.1fk\n", @cpu_info[:ram_s],@cpu_info[:ram_e],(@cpu_info[:ram_e]-@cpu_info[:ram_s])/1024.0
278
+ printf "Flash: %08X .. %08X %5.1fk\n", @cpu_info[:flash_s],@cpu_info[:flash_e],(@cpu_info[:flash_e]-@cpu_info[:flash_s])/1024.0
279
+ addr=@cpu_info[:serno]
280
+ base=addr&(0xffffff00)
281
+ oset=addr&(0xff)
282
+ buf=read base,oset+0x10
283
+ serno=""
284
+ 10.times do |i|
285
+ serno += sprintf("%02X",buf[oset+i])
286
+ end
287
+ @serno=serno
288
+ puts "Serno: '#{serno}'."
289
+ end
290
+ end
291
+ end
292
+
293
+ def read addr,len
294
+ if send_cmd(:read)
295
+ if send_addr addr
296
+ ch=send_buf [(len-1),0xff - (len-1)],true
297
+ if buf=wait_chars(len,0.1)
298
+ if @debug
299
+ printf "len=#{len}:"
300
+ buf.each do |b|
301
+ printf "%02X ",b
302
+ end
303
+ printf "\n"
304
+ end
305
+ return buf
306
+ end
307
+ end
308
+ end
309
+ return nil
310
+ end
311
+
312
+ def write addr,data
313
+ return(nil) if not data or data==[]
314
+ len=data.length
315
+ if len>0x100
316
+ puts "Too big block to write #{len}"
317
+ return nil
318
+ end
319
+ if send_cmd(:write)
320
+ if send_addr addr
321
+ list=[data.length-1]
322
+ list+=data
323
+ if ack=send_buf_with_check(list,3)
324
+ #puts "Write Result: #{ack}"
325
+ return ack
326
+ end
327
+ end
328
+ end
329
+ puts "Error: Write fails!"
330
+ flush_chars # failed write may have produced some nacks
331
+ return nil
332
+ end
333
+
334
+ def erase blocks
335
+ return if not blocks or blocks==[]
336
+ list=[blocks.length-1].pack("n").unpack("cc")
337
+ blocks.each do |b|
338
+ list+=[b].pack("n").unpack("cc")
339
+ end
340
+ if send_cmd(:erase)
341
+ if ack=send_buf_with_check(list,3)
342
+ #puts "Erase #{list.size} Pages Result: #{ack}"
343
+ return ack
344
+ end
345
+ end
346
+ return nil
347
+ end
348
+
349
+ def run addr=0x08000000
350
+ printf "try to Run @ %x",addr
351
+ if @state!=:booted
352
+ if not boot
353
+ puts "Error: Cannot run, as cannot get booted"
354
+ return nil
355
+ end
356
+ end
357
+ retries=0
358
+ while retries<4 do
359
+ if send_cmd :go
360
+ if send_addr addr
361
+ if ch=wait_char
362
+ puts "Started Running, retries: #{retries} got #{ch}\n" if @debug
363
+ if ch==0
364
+ @state=:running
365
+ return true
366
+ end
367
+ else
368
+ puts "Started Running???, retries: #{retries} -- no start char\n"
369
+ end
370
+ end
371
+ end
372
+ puts "run failed, retry boot and run"
373
+ if not boot
374
+ puts "Error: Cannot run, as cannot get booted"
375
+ return nil
376
+ end
377
+ retries+=1
378
+ end
379
+ boot #return to bootstrap mode
380
+ return false
381
+ end
382
+
383
+ def flash fn
384
+ s=Srec.new file: fn
385
+ bsize=get_cpu(:flash_bsize)
386
+ fs=get_cpu(:flash_s)
387
+ fe=get_cpu(:flash_e)
388
+ b= s.to_blocks fs,fe,bsize
389
+ puts "#{b.size} blocks of #{bsize} bytes"
390
+ list=[]
391
+ b.each do |blk,data|
392
+ list << blk
393
+ end
394
+ start=Time.now.to_i
395
+ if erase list
396
+ dur=Time.now.to_i-start
397
+ puts "Erased in #{dur}s"
398
+ cnt=0
399
+ start=Time.now.to_i
400
+ b.each do |blk,data|
401
+ addr=blk*bsize+fs
402
+ if write addr,data
403
+ printf("\r#{cnt}/#{b.length} %.0f%%",100.0*cnt/b.length) if cnt%10==0
404
+ else
405
+ puts "Error: Write fails at #{addr}"
406
+ break
407
+ end
408
+ cnt+=1
409
+ end
410
+ dur=Time.now.to_i-start
411
+ puts "\nFlashed in #{dur}s"
412
+ else
413
+ puts "Error: Erase failed"
414
+ end
415
+ end
416
+
417
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stm32
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ari Siitonen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: srec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: minimal-http-ruby
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.0.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.0.3
53
+ description: Pure Ruby Driver and Flash programmer for stm32 bootstrap -- cli included
54
+ email: jalopuuverstas@gmail.com
55
+ executables:
56
+ - stm32_cli.rb
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - bin/stm32_cli.rb
61
+ - lib/stm32.rb
62
+ homepage: https://github.com/arisi/stm32
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.2.2
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Pure Ruby Driver and Flash programmer for stm32 bootstrap
86
+ test_files: []