sd 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 (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: []