I am having great trouble initializing a sd card. Information is confusing and sometimes contradictory. I seem to remember, I think it was Peter Stone, someone had made a simple datalogger. I wonder if the code could be posted to give me something to go on.
I seem to be going good until the CMD55, ACMD41 sequence when I can never seem to get the correct response back from the card.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@David. A release of GCB compiler before May 2015 will not work correctly when read/writing. I can let you have the very latest Hot Build if you are interested. Send me a personal message - please provide your email address.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I really just want to dump data from a 16F1789 (which has plenty of RAM).
I have been looking at the sd.h in the include files I am confused as the SD_CS pin seems to be off when other documents (on the web) seem to suggest it should be on (that is right at the beginning of the initialization).
I will post my code it probably contains a lot of stuff that is not necessary as I am trying desperately to get it to work.
The CS pin is on portc.6.
The porta.0 is to flash a LED to indicate progress through the program.
~~~~~~~~~
chip 16F1789,4
config OSC=INTosc, MCLRE=off, WDT=Off, boren=off
wait 1 sec
dir portc.6 out
set portc.6 off 'cs pin
dir porta.0 out
set porta.0 off
dir porta.1 out
set porta.1 off
dir portc.3 out '[set
dir portc.4 in '[spi
dir portc.5 out '[pins
'set cke off
'set ckp on
spimode master 'low speed
set porta.0 on
wait 500 ms
set porta.0 off
set portc.6 on
for i=1 to 10
spitransfer b'11111111',r1
next i
set portc.6 off
for i=1 to 2
spitransfer b'11111111',r1
next i
wait 500 ms
set porta.0 on
wait 500 ms
set porta.0 off
cmd0
'check if idle?
wait 500 ms
set porta.0 on
wait 500 ms
set porta.0 off
'set portc.6 on
do
wait 10 ms
cmd55
acmd41
'cmd1
if r1.7 = 0 then exit do
loop
'spimode masterfast
wait 100 ms
set portc.6 off
set porta.0 on
wait 100 ms
set porta.0 off
cmd24
spitransfer b'11111110',r1 'block start token
for i=0 to 255
spitransfer b'01000000',r1
spitransfer b'00100000',r1
next i
set porta.0 on
sleep
sub cmd0
spitransfer 0x40,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD0
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0x95,r1
repeat 50
spitransfer 0xff,r1
if r1<>255 then exit repeat
end repeat
set portc.6 on
spitransfer 0xff,r1
set portc.6 off
end sub
sub cmd55
spitransfer 0x77,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD55
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1 'dummy crc
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
sub acmd41
spitransfer 0x69,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is ACMD41
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1 'dummy crc
spitransfer 0xff,r1
spitransfer 0xff,r1
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
sub cmd24
spitransfer 0x58,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD24
spitransfer 0x03,r1 'address 512
spitransfer 0x00,r1
spitransfer 0xff,r1
'spitransfer 0xff,r1
end sub
sub cmd1
spitransfer 0x41,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD1
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1
spitransfer 0xff,r1
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
~~~~~~~~
Last edit: David Stephenson 2015-05-25
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've completely re-written my routine and guess what - it still doesn't work.
It gets stuck at the CMD55,ACMD41 as the correct response is never received from the card.
I've seen one document that says CMD8 is mandatory so I've put it in.
I must be making some obvious mistake can anybody figure it out?
~~~~~~~~~~~~~~~~~
chip 16F1789,4
config OSC=INTosc, MCLRE=off, WDT=Off, boren=off
wait 100 ms
dir portc.6 out
set portc.6 off 'cs pin
dir porta.0 out
set porta.0 off
dir porta.1 out
set porta.1 off
dir porta.5 out
set porta.5 off
dir portc.3 out '[set
dir portc.4 in '[spi
dir portc.5 out '[pins
'set cke off
'set ckp on
spimode master 'low speed
set portc.6 off 'cs on
start:
for i=1 to 10
spitransfer 0xff,r1
next i
set portc.6 on
spitransfer 0xff,r1
spitransfer 0xff,r1
wait 10 us
sdsend (0,0,0,0,0,149) 'send cmd0
wait 10 us
sdsend (8,0,0,1,170,15) 'send cmd8
repeat 4
spitransfer 255,r1
end repeat
wait 10 us
repeat 5
sdsend (55,0,0,0,0,255) 'send cmd55
sdsend (41,0,0,0,0,255) 'send acmd41
'sdsend (41,64,0,0,0,255) 'hcs bit set
'sdsend (1,0,0,0,0,255) 'send cmd1
if r1=0 then exit repeat
wait 1 ms
end repeat
spimode masterfast 'speed up transfer
repeat 250
sdsend (24,0,0,3,0,255) 'send cmd24
if r1=0 then exit repeat
wait 1 ms
end repeat
spitransfer 254,r1 'write start token
for i=0 to 255
spitransfer 16,r1 'writing easy to find bytes
spitransfer 32,r1
next i
spitransfer 255,r1
spitransfer 255,r1
set porta.0 on 'turn led on finished
wait 100 ms
set portc.6 on 'comm off
sleep
sub sdsend (a1,d3,d2,d1,d0,crc)
set portc.6 off
a2=a1+64
'if a1=41 then a2=a1+192
repeat 250
spitransfer 255,r1
if r1<>255 then exit repeat
wait 1 ms
end repeat
spitransfer a2,r1
spitransfer d3,r1
spitransfer d2,r1
spitransfer d1,r1
spitransfer d0,r1
spitransfer crc,r1
wait 10 us
repeat 100
spitransfer 255,r1
if r1.7=0 then exit repeat
end repeat
set portc.6 on
spitransfer 255,r2
set portc.6 off
end sub
~~~~~~~~~~~~~~~~~~~~~~~
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am online but uber busy at the moment. I will gather up the sd card soon but the development I have it very robust but we do need to add SD Card write operations.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Puzzled. I have sent you working code that supports all three types of SD Card, supports directories, files, card config etc. I included an updated compiler required to support this functionality.
Is the code not working? Or, have you not received?
Send me an email, to my personal email address, as I do want not post to the forum as this package is intended for inclusion in the next release oF GCB.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just saw this post.
I have attached my early SD card data logger in the hope that it might help.
This logger does not use a file system as such.
I did find some issues with some SD cards. It appears that not all SD cards behave as expected . Try a few different types/brands. You need one that implements the SDI functions of the SD card spec.
Yes thanks Peter that was useful. I have managed to write to one card.
Two other cards refuse to cooperate. One looks like it is working even sends the data accepted byte, but nothing goes in memory. The third does not respond to the ACMD(41) it stays in idle mode returning 0x01.
I can view the contents of the card using the (free) HxD hex editor.
Last edit: David Stephenson 2015-05-29
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The methodology behind my design was to make the logger component as simple and cheap as possible. It was originally designed around a 16F88, hence the focus on low memory use.
It basically writes blocks on the fly and stores nothing in the actual micro (other than buffering a small amount of data).
It is fairly wasteful of SD card memory, but I figured I had plenty for basic logging. I needed to pad the data out to get the full 512byte block size for a write. Many of the PIC micros just do not have enough RAM to buffer a full block of 512bytes.
There is no file system. The data is just written directly to the card in blocks.
There is crude time stamping of each block.
The intention was to read on another computer (with much more capability) where the actual data reformatting would be done. In the short term I just used Linux to do a raw read of the SD card and manipulate the data as I needed. Easy enough to do.
You essentially initialise the little logger with a TTL serial connection (via a few of the logging pins) to a PC. You then unplug the cable and let it log for as long as you need.
I was using a 2GB SD card. It isn't designed for SDHC cards so probably will not work with these.
I believe some SD cards make not like the ACMD(41) command, so you might have to try the alternate commands originally intended for MMC cards. You will also find that some SD cards will not work with an SPI connection and will need the 4 bit parallel interface. Not something I wanted to explore for my purposes.
I have attached a schematic for those interested in experimenting with the design.
I would welcome feedback on any improvements.
Yes you're correct Peter. For cards with larger memory the HCS bit needs to be set in ACMD41.
I've got three cards to go successfully through the initialization (a 64 MB, 1GB and 4GB) on writing 512 bytes all three give the 0xE5 successful write byte. Problem is only the 64MB has the actual data the others no write has taken place.
Any Ideas?
Last edit: David Stephenson 2015-05-30
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi David,
Its been 18 months since I worked on my logger code, so my recollection of the details is getting a bit hazy.
I recall that it did take a bit to get going. The timing was very important.
Read my code carefully. I have made notes where I discovered little timing issues that needed addressing.
You will note that in one section I actually have to toggle the SD card CS pin for correct operation.
Have a good look at the supply voltage to the card also. A voltage outside of its allowable range will also give problems.
I do not recall the E5 success code????? Is this right? I have not looked at the SD card spec for a while.
Peter.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
0xE5 indicates data accepted after a write (bits 1,2 and 3 need to be 010).
So I'm still at the stage that all commands give a correct response on all the cards I've tried, but only the 64 MB actually has any data written to it.
I have attached my program.
I've finally managed to write to the larger capacity cards. There is still something strange happening though.
The 64 MB card putting in CMD24 with the address 0,2,0,0 puts the data in block 256 as expected. (block = 2*65536/512)
The 1GB card with CMD24 and address 0,2,0,0 puts the data in block 7 and 0,3,0,0 puts the data in block 135.
Any ideas?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
MMC, SD and HighDensitySD card all have different structures. One of the structures (a specific block) tell you where the ROOT block is. This root block is different between the two SDs cards. So, I would expect this behaviour.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am having great trouble initializing a sd card. Information is confusing and sometimes contradictory. I seem to remember, I think it was Peter Stone, someone had made a simple datalogger. I wonder if the code could be posted to give me something to go on.
I seem to be going good until the CMD55, ACMD41 sequence when I can never seem to get the correct response back from the card.
@David. A release of GCB compiler before May 2015 will not work correctly when read/writing. I can let you have the very latest Hot Build if you are interested. Send me a personal message - please provide your email address.
I have been waiting for someone to ask to motivate me to complete the project.
I have made a lot of progress on the SD Card. It is was really slow going.
Have a look at the video. The ADD (append instruction). Starts at about 2mins in.
So, add to a file. ASCII only and then two carriage returns shuts the file.
http://gcbasic.sourceforge.net/temp/Videos/gcbdos002.mp4
If Peter Stone has some working code this would be wonderful to complete this project.
I really just want to dump data from a 16F1789 (which has plenty of RAM).
I have been looking at the sd.h in the include files I am confused as the SD_CS pin seems to be off when other documents (on the web) seem to suggest it should be on (that is right at the beginning of the initialization).
I will post my code it probably contains a lot of stuff that is not necessary as I am trying desperately to get it to work.
The CS pin is on portc.6.
The porta.0 is to flash a LED to indicate progress through the program.
~~~~~~~~~
chip 16F1789,4
config OSC=INTosc, MCLRE=off, WDT=Off, boren=off
wait 1 sec
dir portc.6 out
set portc.6 off 'cs pin
dir porta.0 out
set porta.0 off
dir porta.1 out
set porta.1 off
dir portc.3 out '[set
dir portc.4 in '[spi
dir portc.5 out '[pins
'set cke off
'set ckp on
spimode master 'low speed
set porta.0 on
wait 500 ms
set porta.0 off
set portc.6 on
for i=1 to 10
spitransfer b'11111111',r1
next i
set portc.6 off
for i=1 to 2
spitransfer b'11111111',r1
next i
wait 500 ms
set porta.0 on
wait 500 ms
set porta.0 off
cmd0
'check if idle?
wait 500 ms
set porta.0 on
wait 500 ms
set porta.0 off
'set portc.6 on
do
wait 10 ms
cmd55
acmd41
'cmd1
if r1.7 = 0 then exit do
loop
'spimode masterfast
wait 100 ms
set portc.6 off
set porta.0 on
wait 100 ms
set porta.0 off
cmd24
spitransfer b'11111110',r1 'block start token
for i=0 to 255
spitransfer b'01000000',r1
spitransfer b'00100000',r1
next i
set porta.0 on
sleep
sub cmd0
spitransfer 0x40,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD0
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0x95,r1
repeat 50
spitransfer 0xff,r1
if r1<>255 then exit repeat
end repeat
set portc.6 on
spitransfer 0xff,r1
set portc.6 off
end sub
sub cmd55
spitransfer 0x77,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD55
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1 'dummy crc
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
sub acmd41
spitransfer 0x69,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is ACMD41
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1 'dummy crc
spitransfer 0xff,r1
spitransfer 0xff,r1
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
sub cmd24
spitransfer 0x58,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD24
spitransfer 0x03,r1 'address 512
spitransfer 0x00,r1
spitransfer 0xff,r1
'spitransfer 0xff,r1
end sub
sub cmd1
spitransfer 0x41,r1
spitransfer 0x00,r1
spitransfer 0x00,r1 'this is CMD1
spitransfer 0x00,r1
spitransfer 0x00,r1
spitransfer 0xff,r1
spitransfer 0xff,r1
set portc.6 on
spitransfer 0xff,r2
set portc.6 off
end sub
~~~~~~~~
Last edit: David Stephenson 2015-05-25
I've completely re-written my routine and guess what - it still doesn't work.
It gets stuck at the CMD55,ACMD41 as the correct response is never received from the card.
I've seen one document that says CMD8 is mandatory so I've put it in.
I must be making some obvious mistake can anybody figure it out?
~~~~~~~~~~~~~~~~~
chip 16F1789,4
config OSC=INTosc, MCLRE=off, WDT=Off, boren=off
wait 100 ms
dir portc.6 out
set portc.6 off 'cs pin
dir porta.0 out
set porta.0 off
dir porta.1 out
set porta.1 off
dir porta.5 out
set porta.5 off
dir portc.3 out '[set
dir portc.4 in '[spi
dir portc.5 out '[pins
'set cke off
'set ckp on
spimode master 'low speed
set portc.6 off 'cs on
start:
for i=1 to 10
spitransfer 0xff,r1
next i
set portc.6 on
spitransfer 0xff,r1
spitransfer 0xff,r1
wait 10 us
sdsend (0,0,0,0,0,149) 'send cmd0
wait 10 us
sdsend (8,0,0,1,170,15) 'send cmd8
repeat 4
spitransfer 255,r1
end repeat
wait 10 us
repeat 5
sdsend (55,0,0,0,0,255) 'send cmd55
sdsend (41,0,0,0,0,255) 'send acmd41
'sdsend (41,64,0,0,0,255) 'hcs bit set
'sdsend (1,0,0,0,0,255) 'send cmd1
if r1=0 then exit repeat
wait 1 ms
end repeat
spimode masterfast 'speed up transfer
repeat 250
sdsend (24,0,0,3,0,255) 'send cmd24
if r1=0 then exit repeat
wait 1 ms
end repeat
spitransfer 254,r1 'write start token
for i=0 to 255
spitransfer 16,r1 'writing easy to find bytes
spitransfer 32,r1
next i
spitransfer 255,r1
spitransfer 255,r1
set porta.0 on 'turn led on finished
wait 100 ms
set portc.6 on 'comm off
sleep
sub sdsend (a1,d3,d2,d1,d0,crc)
set portc.6 off
a2=a1+64
'if a1=41 then a2=a1+192
repeat 250
spitransfer 255,r1
if r1<>255 then exit repeat
wait 1 ms
end repeat
spitransfer a2,r1
spitransfer d3,r1
spitransfer d2,r1
spitransfer d1,r1
spitransfer d0,r1
spitransfer crc,r1
wait 10 us
repeat 100
spitransfer 255,r1
if r1.7=0 then exit repeat
end repeat
set portc.6 on
spitransfer 255,r2
set portc.6 off
end sub
~~~~~~~~~~~~~~~~~~~~~~~
I am online but uber busy at the moment. I will gather up the sd card soon but the development I have it very robust but we do need to add SD Card write operations.
Some developments. I have put a screen in the circuit and so I can now see the responses.
After CMD0 I get 0x81 so it has gone into idle but bit 7 is also set.
After CMD8 I get 4 bytes 0x81 0x80 0x00 0x01 don't know what that means.
After the CMD55/ACMD41 sequence (it takes about 5 tries) I get 0x80 so the idle bit had gone off, but again bit 7 is set.
I am using a microSD 1GByte (Samsung) (other sizes do not seem to even work this well)
Puzzled. I have sent you working code that supports all three types of SD Card, supports directories, files, card config etc. I included an updated compiler required to support this functionality.
Is the code not working? Or, have you not received?
Send me an email, to my personal email address, as I do want not post to the forum as this package is intended for inclusion in the next release oF GCB.
Hi Guys.
Just saw this post.
I have attached my early SD card data logger in the hope that it might help.
This logger does not use a file system as such.
I did find some issues with some SD cards. It appears that not all SD cards behave as expected . Try a few different types/brands. You need one that implements the SDI functions of the SD card spec.
Cheers
Peter.
A really, very interesting approach. Thank you - I like the methodology.
If this writing blocks or to a file handle?
What is method to access from a computer?
Yes thanks Peter that was useful. I have managed to write to one card.
Two other cards refuse to cooperate. One looks like it is working even sends the data accepted byte, but nothing goes in memory. The third does not respond to the ACMD(41) it stays in idle mode returning 0x01.
I can view the contents of the card using the (free) HxD hex editor.
Last edit: David Stephenson 2015-05-29
Anobium, I did not receive the code. The e-mail filters must have stripped off the attachments.
The methodology behind my design was to make the logger component as simple and cheap as possible. It was originally designed around a 16F88, hence the focus on low memory use.
It basically writes blocks on the fly and stores nothing in the actual micro (other than buffering a small amount of data).
It is fairly wasteful of SD card memory, but I figured I had plenty for basic logging. I needed to pad the data out to get the full 512byte block size for a write. Many of the PIC micros just do not have enough RAM to buffer a full block of 512bytes.
There is no file system. The data is just written directly to the card in blocks.
There is crude time stamping of each block.
The intention was to read on another computer (with much more capability) where the actual data reformatting would be done. In the short term I just used Linux to do a raw read of the SD card and manipulate the data as I needed. Easy enough to do.
You essentially initialise the little logger with a TTL serial connection (via a few of the logging pins) to a PC. You then unplug the cable and let it log for as long as you need.
I was using a 2GB SD card. It isn't designed for SDHC cards so probably will not work with these.
I believe some SD cards make not like the ACMD(41) command, so you might have to try the alternate commands originally intended for MMC cards. You will also find that some SD cards will not work with an SPI connection and will need the 4 bit parallel interface. Not something I wanted to explore for my purposes.
I have attached a schematic for those interested in experimenting with the design.
I would welcome feedback on any improvements.
Cheers
Peter
Here is a document that might also help.
And another.
Peter.
Yes you're correct Peter. For cards with larger memory the HCS bit needs to be set in ACMD41.
I've got three cards to go successfully through the initialization (a 64 MB, 1GB and 4GB) on writing 512 bytes all three give the 0xE5 successful write byte. Problem is only the 64MB has the actual data the others no write has taken place.
Any Ideas?
Last edit: David Stephenson 2015-05-30
Hi David,
Its been 18 months since I worked on my logger code, so my recollection of the details is getting a bit hazy.
I recall that it did take a bit to get going. The timing was very important.
Read my code carefully. I have made notes where I discovered little timing issues that needed addressing.
You will note that in one section I actually have to toggle the SD card CS pin for correct operation.
Have a good look at the supply voltage to the card also. A voltage outside of its allowable range will also give problems.
I do not recall the E5 success code????? Is this right? I have not looked at the SD card spec for a while.
Peter.
0xE5 indicates data accepted after a write (bits 1,2 and 3 need to be 010).
So I'm still at the stage that all commands give a correct response on all the cards I've tried, but only the 64 MB actually has any data written to it.
I have attached my program.
I've finally managed to write to the larger capacity cards. There is still something strange happening though.
The 64 MB card putting in CMD24 with the address 0,2,0,0 puts the data in block 256 as expected. (block = 2*65536/512)
The 1GB card with CMD24 and address 0,2,0,0 puts the data in block 7 and 0,3,0,0 puts the data in block 135.
Any ideas?
MMC, SD and HighDensitySD card all have different structures. One of the structures (a specific block) tell you where the ROOT block is. This root block is different between the two SDs cards. So, I would expect this behaviour.