Menu

Writing to a micro sd card

Help
2015-05-25
2015-06-24
  • David Stephenson

    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.

     
    • Anobium

      Anobium - 2015-05-25

      @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.

       
  • Anobium

    Anobium - 2015-05-25

    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.

     
  • David Stephenson

    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
  • David Stephenson

    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
    ~~~~~~~~~~~~~~~~~~~~~~~

     
  • Anobium

    Anobium - 2015-05-27

    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.

     
  • David Stephenson

    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)

     
  • Anobium

    Anobium - 2015-05-28

    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.

     
  • Peter Stone

    Peter Stone - 2015-05-29

    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.

     
  • Anobium

    Anobium - 2015-05-29

    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?

     
  • David Stephenson

    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
  • David Stephenson

    Anobium, I did not receive the code. The e-mail filters must have stripped off the attachments.

     
  • Peter Stone

    Peter Stone - 2015-05-29

    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

     
  • Peter Stone

    Peter Stone - 2015-05-30

    Here is a document that might also help.

     
  • Peter Stone

    Peter Stone - 2015-05-30

    And another.

    Peter.

     
  • David Stephenson

    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
  • Peter Stone

    Peter Stone - 2015-05-31

    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.

     
  • David Stephenson

    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.

     
  • David Stephenson

    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?

     
  • Anobium

    Anobium - 2015-06-24

    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.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.