sd 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/sd-util.rb +77 -0
  2. data/lib/sd.rb +246 -0
  3. metadata +49 -0
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ #encoding: UTF-8
3
+
4
+ require 'optparse'
5
+ require 'yaml'
6
+
7
+ lib="sd"
8
+ if File.file? "./lib/#{lib}.rb"
9
+ require "./lib/#{lib}.rb"
10
+ puts "using local #{lib}"
11
+ local=true
12
+ else
13
+ require lib
14
+ end
15
+
16
+
17
+ options={}
18
+
19
+
20
+ $sd=Sd.new options
21
+
22
+ if not $sd.init
23
+ exit -1
24
+ else
25
+ pp $sd.ident
26
+ end
27
+ #cmd :send_status
28
+
29
+ b=4
30
+
31
+ if false
32
+ tb=1000
33
+ mul=5000
34
+ erase 0,tb*mul
35
+
36
+ rers=wers=0
37
+ start=Time.now.to_f
38
+ (0..tb).each do |j|
39
+ start2=Time.now.to_f
40
+ buf=[]
41
+ $blklen.times do |i|
42
+ buf << ((i+j)&0xff)
43
+ end
44
+ a=$blklen*j*mul
45
+ printf "%08X (%.3fMb) [%d]",a,a/1000000.0,j*mul
46
+ write a,buf
47
+ d=cmd :read_single_block,a
48
+ now=Time.now.to_f
49
+ if buf==d
50
+ printf "OK %.2f %.2f\n",now-start,now-start2
51
+ else
52
+ puts "ER"
53
+ wers+=1
54
+ end
55
+ end
56
+ puts "Verify:"
57
+ start=Time.now.to_f
58
+ (0..tb).each do |j|
59
+ start2=Time.now.to_f
60
+ buf=[]
61
+ $blklen.times do |i|
62
+ buf << ((i+j)&0xff)
63
+ end
64
+ a=$blklen*j*mul
65
+ printf "%08X ",a
66
+ d=cmd :read_single_block,a
67
+ now=Time.now.to_f
68
+ if buf==d
69
+ printf "OK %.2f %.2f\n",now-start,now-start2
70
+ else
71
+ puts "ER"
72
+ rers+=1
73
+ end
74
+ end
75
+ puts "Write Errs: #{wers}, Read Errs: #{rers}"
76
+ end
77
+
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env ruby
2
+ #encoding: UTF-8
3
+
4
+ require 'pp'
5
+ require 'time'
6
+ require 'pi_piper'
7
+ include PiPiper
8
+
9
+ class Sd
10
+ Cmds={
11
+ send_op_cond: {op: 1, retlen: 1},
12
+ send_csd: {op: 9, retlen: 1, data: :read, datalen:18},
13
+ send_cid: {op: 10, retlen: 1, data: :read, datalen:18},
14
+ send_status: {op: 13, retlen: 2},
15
+ set_blocklen: {op: 16, retlen: 1},
16
+ read_single_block: {op: 17, retlen: 1, data: :read},
17
+ write_block: {op: 24, retlen: 1, data: :write},
18
+ erase_start: {op: 32, retlen: 1},
19
+ erase_end: {op: 33, retlen: 1},
20
+ erase: {op: 38, retlen: 1, data: :busy},
21
+ send_scr: {op: 51, retlen: 1, data: :read, datalen:10},
22
+ app_cmd: {op: 55, retlen: 1},
23
+ read_ocr: {op: 58, retlen: 5},
24
+ }
25
+
26
+ def initialize(hash={})
27
+ hash[:blklen] = 512 if not hash[:blklen]
28
+ hash[:do] = 10 if not hash[:do]
29
+ hash[:di] = 9 if not hash[:di]
30
+ hash[:clk]= 11 if not hash[:clk]
31
+ hash[:cs] = 22 if not hash[:cs]
32
+ @blklen=hash[:blklen]
33
+ @options=hash
34
+ @cs =PiPiper::Pin.new(:pin => hash[:cs], :direction => :out)
35
+ @do =PiPiper::Pin.new(:pin => hash[:do], :direction => :out)
36
+ @clk=PiPiper::Pin.new(:pin => hash[:clk],:direction => :out)
37
+ @di =PiPiper::Pin.new(:pin => hash[:di], :direction => :in,:pull => :down)
38
+ @cs.on
39
+ @clk.off
40
+ @do.off
41
+ @SPI_CLOCK=2500000
42
+ end
43
+
44
+ def outbytes c,l,retlen=1
45
+ ret=[]
46
+ data=[]
47
+ cmd_data=[]
48
+ @cs.off
49
+ PiPiper::Spi.begin do
50
+ clock(2500000)
51
+ l.each do |b|
52
+ cmd_data << write(b)
53
+ end
54
+ write(0xff)
55
+ retlen.times do
56
+ data << write(0xff)
57
+ end
58
+ if c and c[:data] == :busy
59
+ tries=0
60
+ while (start=write(0xff))==0 do
61
+ if tries>10000
62
+ puts "Error: busy stuck (#{c},#{l})"
63
+ break
64
+ end
65
+ tries+=1
66
+ sleep 0.01
67
+ end
68
+ #puts "took #{tries} to unbusy"
69
+ elsif c and c[:data] == :read
70
+ data=[]
71
+ tries=0
72
+ while (start=write(0xff))!=0xfe do
73
+ if tries>1000
74
+ puts "Error: data read stuck with [0x#{start.to_s(16)}] (#{c},#{l}) tried #{tries}"
75
+ break
76
+ end
77
+ tries+=1
78
+ sleep 0.001
79
+ end
80
+ if start==0xfe
81
+ if c[:datalen]
82
+ c[:datalen].times do
83
+ data << write(0xff)
84
+ end
85
+ else
86
+ (@blklen).times do
87
+ data << write(0xff)
88
+ end
89
+ end
90
+ write(0xff)
91
+ write(0xff)
92
+ end
93
+ end
94
+ end
95
+ @cs.on
96
+ data
97
+ end
98
+
99
+ def cmd cmd,val=0,retlen=nil
100
+ if not Cmds[cmd]
101
+ puts "Error: Unknown Command to SD: #{cmd}"
102
+ end
103
+ c=Cmds[cmd][:op]
104
+ retlen=Cmds[cmd][:retlen] if not retlen
105
+ l=[c|0x40]
106
+ l+=[val].pack("N").unpack("CCCC")
107
+ l<<1
108
+ data=outbytes Cmds[cmd],l,retlen
109
+ if @options[:verbose]
110
+ printf("%20.20s (%2d %08X): ",cmd,c,val)
111
+ data.each_with_index do |b,i|
112
+ printf("%02X ",b)# if i<30
113
+ end
114
+ puts ""
115
+ end
116
+ data
117
+ end
118
+
119
+ def hdump l
120
+ print "["
121
+ l.each do |b|
122
+ printf "%02X ", b
123
+ end
124
+ print "]\n"
125
+ end
126
+
127
+ def bdump l
128
+ print "["
129
+ l.each do |b|
130
+ printf "%08d ", b.to_s(2)
131
+ end
132
+ print "]\n"
133
+ end
134
+
135
+ def pickbits l,so,eo
136
+ sz=l.size*8
137
+ b=[]
138
+ s=sz-so-1
139
+ e=sz-eo-1
140
+ (s .. e).each do |bit|
141
+ byte=bit/8
142
+ oset=bit%8
143
+ bval= 1<<oset
144
+ v=(l[byte]&bval)==bval
145
+ if v
146
+ b=[1]+b
147
+ else
148
+ b=[0]+b
149
+ end
150
+ end
151
+ val=0
152
+ b.each do |bit|
153
+ val*=2
154
+ if bit==1
155
+ val|=1
156
+ end
157
+ end
158
+ #printf "%d:%d 0x%X (%d)\n",so,eo,val,val
159
+ val
160
+ end
161
+
162
+ def ident
163
+ info={}
164
+ ret=cmd :send_cid
165
+ if ret and ret!=[]
166
+ serno=""
167
+ ret[8...8+5].each do |b|
168
+ serno+=sprintf("%02X",b)
169
+ end
170
+ info=info.merge({
171
+ mid: ret[0].to_s(16),
172
+ oem:ret[1...1+2].pack("c*"),
173
+ pnm:ret[3...3+5].pack("c*"),
174
+ rev: ret[7],
175
+ serno: serno,
176
+ date: sprintf("%d/%d",2000+ret[14]/0x10,ret[14]&0xf),
177
+ })
178
+ end
179
+ ret=cmd :send_csd
180
+ if ret and ret!=[]
181
+ info[:block_size]=2**(pickbits ret[0..-3],83,80)
182
+ info[:block_count]=pickbits ret[0..-3],73,62
183
+ info[:capacity]=info[:block_count]*524288
184
+ info[:capacity_gb]=sprintf("%.1f",info[:block_count]*524288/(1000.0**3.0))
185
+ end
186
+ info
187
+ end
188
+
189
+ def boot
190
+ loop do
191
+ ret=outbytes nil,[0x40, 0, 0, 0, 0,0x95]
192
+ if ret[0]==0x01
193
+ break
194
+ end
195
+ end
196
+ loop do
197
+ ret=cmd :send_op_cond
198
+ if ret[0]==0x00
199
+ break
200
+ end
201
+ end
202
+ end
203
+
204
+ def init
205
+ tries=0
206
+ ret=false
207
+ loop do
208
+ ret=cmd :read_ocr
209
+ if ret==[0,0,0,0,0]
210
+ if tries>10
211
+ puts "Error: Cannot Init SD Card"
212
+ ret=false
213
+ break
214
+ end
215
+ boot
216
+ sleep 0.01
217
+ else
218
+ break
219
+ end
220
+ tries+=1
221
+ end
222
+ if ret
223
+ cmd :set_blocklen,@blklen
224
+ end
225
+ ret
226
+ end
227
+
228
+ def erase from=0,till=0
229
+ return if till<=from
230
+ cmd :erase_start,from*@blklen
231
+ cmd :erase_end,till*@blklen
232
+ cmd :erase
233
+ end
234
+ def write addr=0,data=[]
235
+ return if not data or data==[]
236
+ buf=[0xfe]
237
+ buf+=data
238
+ buf << 0 #crc 2 bytes
239
+ buf << 0
240
+ buf << 0 #this will shift data response
241
+
242
+ cmd :write_block,addr
243
+ outbytes({data: :busy},buf)
244
+ end
245
+ end
246
+
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sd
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ari Siitonen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-01-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Sd-card library for RPi in pure Ruby, supports SDHC via SPI, tested on
15
+ Raspberry Pi
16
+ email: jalopuuverstas@gmail.com
17
+ executables:
18
+ - sd-util.rb
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/sd.rb
23
+ - bin/sd-util.rb
24
+ homepage: https://github.com/arisi/sd
25
+ licenses:
26
+ - MIT
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 1.8.23
46
+ signing_key:
47
+ specification_version: 3
48
+ summary: sd-card library for RPi in pure Ruby
49
+ test_files: []