• AVR Freaks

Bit banging SPI to MMC/SD card problem

Page: 12 > Showing page 1 of 2
Author
el_litri
New Member
  • Total Posts : 22
  • Reward points : 0
  • Joined: 2010/02/20 18:57:37
  • Location: 0
  • Status: offline
2010/03/27 04:49:54 (permalink)
0

Bit banging SPI to MMC/SD card problem

I am building an MP3 player with MMC/SD card interface to a PIC18F4550 through SPI, but I cannot get any response from the card, here are the details, anyone can help me?

- When I read from the card, the MISO line is all the time high or "1". I expect to receive an R1 command or "0x01" but I see no movement on the line.
- I am implementing the SPI read and write routines as "bit banging", with data valid on the rising edge of the clock
- The card and the microcontroller are powered at 3.3V
- There are no other chips using SPI on the bus
- The command initialization sequence is correct (the first command I send is CMD0, including staffing zeroes and the corresponding precalculated CRC).
- The socket is for MMC cards (has 2 pins less at the edges) and the card is a microSD, but this shouldn't affect no?
- The card is a microSD in an adapter to SD, instead of a proper SD, this shouldn't be a problem either?
- Do I need to send the SPI commands at an specific frequency or bitrate? The PIC is running off a 20MHz oscillator and the SPI routine is bit-banged so it should be relatively slow but this should help.
- The card is not broken as I can read and write using on my laptop's MMC/SD card reader
- Any consideration regarding data polarity?

I have followed the directions given by http://elm-chan.org/docs/mmc/mmc_e.html and the SD card Association.

I have no idea what else I can try... Anyone who has worked in a similar project can assist? Thx
#1

20 Replies Related Threads

    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/03/27 06:00:18 (permalink)
    0
    There are several threads regarding MMC/SD cards, here's one:
    http://www.microchip.com/forums/tm.aspx?m=452739

    Note that initialisation has to be done between 100 and 400kHz, once initialised you can switch to up to 20MHz.

    I don't know of any problems when using microSD in MMC card adapters, but I haven't ever used microSD before.

    There is some debate however as to whether mode 0 or mode 3 is the correct one to use, there are many projects out there that use mode 3 (i.e. default clock polarity is high, not low. Still uses rising edge to latch data) which is contrary to the link you posted, example timing diagram:
    http://mfb.nopdesign.sk/datasheet/cat_d/MMC/spitiming.pdf

    Mark.


    #2
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/03/27 06:57:45 (permalink)
    0
    Thanks for your input, so far the only problem could be the 100KHz to 400KHz required during reset, perhaps I am going too fast xD (although I would be surprised but I will give it a go)

    I don't see the difference between polarity high and low. I see the difference between sampling data in rising edge of clock or in the falling edge, but how is polarity defined?
    #3
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/03/27 07:28:34 (permalink)
    0
    There are 4 modes of SPI. The default condition of the CLK can be either high or low (i.e. what state the clock is in when the device is not being accessed), and the edge on which data is latched (low or high). A microcontroller usually has a couple of control bits to set this up, but you are bit-banging.

    If you look at the spitimg.pdf link you'll see that the CLK line is high when not accessed. In your link you'll see that the CLK is low when not accessed. Rising edge is still used in both to latch or shift data.

    Mark.
    #4
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/03/27 21:02:00 (permalink)
    0
    I don´t see any response from the MMC. MISO line is all the time high.

    These are my functions for bit-banging SPI and MMC reset:


    ========SPI routines:

    void spi_write_sw_250KHz(int data)
    {
        int i;
       
           for(i=1;i<=8;++i)
        {
            output_low(SPI_CLK);
            delay_us(1);
            output_bit(SPI_SDO, shift_left(&data,1,0));
            delay_us(1);
            output_high(SPI_CLK);
            delay_us(2);
        }
        output_low(SPI_CLK); //Warning. This leaves SCK at 0 after each write. Thus polarity is low.
        output_high(SPI_SDO);
    }

    int spi_read_sw_8bit_word_250KHz()
    {
       BYTE i;
       int data;

       for(i=1;i<=8;++i) {
          output_low(SPI_CLK);
          delay_us(2);
          output_high(SPI_CLK);
          delay_us(2);
          shift_left(&data,1,input(SPI_SDI));
       }
       return data;
    }


    ========MMC routines:

    int mmc_init()
    {
    int i;

    mmc_disable();                    // set SS = 1 (off)

    for(i=0;i<10;i++)                       // initialise the MMC card into SPI mode by sending more than 74 clks on
    {
        spi_write_sw_250KHz(0xFF);
    }

    mmc_enable();                     // set SS = 0 (on) tells card to go to spi mode when it receives reset

    spi_write_sw_250KHz(0x40);                        // send reset command CMD0
    spi_write_sw_250KHz(0x00);                        // all the arguments are 0x00 for the reset command
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x95);                        // precalculated checksum as we are still in MMC mode

    printf("Sent go to SPI\n\r");

    if(mmc_response(0x01)==1) return 1;     // should get R1=00000001, which means "in idle state". Otherwise there was a timeout waiting for 0x01 from the mmc

    printf("Got response from MMC\n\r"); // It never reachs this point!
    return 0;

    }


    int mmc_response(int response)
    {
            unsigned long count = 0xFFFF;          
            int data_received;
            data_received=spi_read_sw_8bit_word_250KHz();
            while(data_received != response && --count > 0)
            {
                data_received=spi_read_sw_8bit_word_250KHz();
            }       

            if(count==0) return 1;                  // loop was exited due to timeout
            else return 0;                          // loop was exited before timeout
    }

    #5
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/03/28 08:21:08 (permalink)
    0
    A few observations:

    You do not need a separate SPI read routine. SPI accesses always transfer data in both directions, a read only is simply a write but with 0xFF as the data written. I'm guessing you  assume that SPI_SDO is always high when you do a read but that makes the function dependent on previous activity. You should have a single routine that shifts out the data you provide as a parameter, and returns the data read back (a combination of your write and read functions). The reason this might be important is that it is possible to send data and get data back with a single byte transfer.

    I notice you've used pre-increment for the counter in some for loops, I'm not sure you meant that - usually the counter is post incremented. E.g.:
    for(i=1;i<=8;++i)
    should be
    for(i=1;i<=8;i++)

    You've also used signed int variables for the data, better to use 8 bit unsigned char IMO. I'm assuming a signed int is 16 bits. SPI transfers should be MSB first (i.e. send bit 7, then 6, then 5 etc) so your shift_left() routine, which takes a signed int as a parameter, would need to be looking at bit 7 to determine whether to return a 1 or a 0 - this routine hasn't been shown.

    Your comment "it never reaches this point!" doesn't make sense, I assume it always reaches that point but shouldn't!

    Also be aware of when you need to send dummy clocks, the following thread has some more info on that:
    http://www.microchip.com/forums/tm.aspx?m=452739

    Mark.



    #6
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/13 14:23:19 (permalink)
    0
    Hi markp, sorry for my late response

    I have tried to debug the SPI interface using an oscilloscope and trying to make the signals match with the timing diagram you posted. You can have a look at the oscilloscope screenshots, the signals look right to me so I have no idea why the MISO line never moves.
    I am sure I am not going too fast, I have measured the frequency of the clock and it´s 135KHz.
    It´s true that I only need one routine to send and receive data throuth SPI, however the routines I am using just do the job, according to the waveforms.

    What can be missing there? The MMC is not broken because I can read it on my PC...

    Any idea? Thanks
    [8|]

    PD: how can I upload images?

    #7
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/13 14:37:34 (permalink)
    0
    By the way, I am using a microSD card on an MMC/SD card socket, do you know if there is a difference between SD and microSD? Could this be the cause of the problem?
    Otherwise, I am starting to think about problems like a bad contact in the socket and that kind of stuff, because I cannot think of anything else.

    If I can upload the screenshots that will be much clarifying
    #8
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/13 15:18:23 (permalink)
    0
    Could you post your current code, especially the shift_left() routine which seems to accept a signed int as a parameter. Also you might want to try adding a pull-up (say 47k) to MISO in case this is high impedance (you could try enabling the PIC's pull-up for that pin and see if it makes any diffeence). You could verify that the MISO signal is actually being driven high by the card or not by temporarily putting a 1k pull-down on MISO.

    Apparently SPI support for microSD is optional, so you may need to check that the microSD card you have really supports SPI.

    Mark.




    #9
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:26:24 (permalink)
    0
    Here is the code. The shift_left() routine is a built-in function from the compiler. On the oscilloscope the SPI waveforms look ok.

    void main() {
    int test1=1;
    int b=0;

    setup_adc_ports(NO_ANALOGS); // port A all digital inputs
    setup_wdt(WDT_OFF);
    SET_TRIS_A(TRIS_A);
    SET_TRIS_B(TRIS_B_I2CSEND);
    SET_TRIS_C(TRIS_C);
    SET_TRIS_D(TRIS_D);
    SET_TRIS_E(TRIS_E);
    port_b_pullups(TRUE);

    printf("MMC test program\n\r");

    while(1)
    {
    b=mmc_init();
    printf("Loop\n\r");
    puts("Testing MMC\n\r");
    test1=test1+1;
    }
    }


    void mmc_enable(void) {
    output_low(MMC_CS);
    }

    void mmc_disable(void) {
    output_high(MMC_CS);
    }


    int mmc_init()
    {
    int i;

    mmc_disable(); // set MMC_CS = 1 (off)

    for(i=0;i<10;i++) // initialise the MMC card into SPI mode by sending more than 74 clks on
    {
    spi_write_sw_250KHz(0xFF);
    }

    mmc_enable(); // set SS = 0 (on) tells card to go to spi mode when it receives reset

    spi_write_sw_250KHz(0x40); // send Reset command CMD0
    spi_write_sw_250KHz(0x00); // all the arguments are 0x00 for the reset command
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x00);
    spi_write_sw_250KHz(0x95); // precalculated checksum as we are still in MMC mode

    printf("Sent go to SPI\n\r");

    if(mmc_response(0x01)==1)
    {
    printf("No response from MMC\n\r"):
    mmc_disable();
    return 1; // should get R1=00000001, which means "in idle state". Otherwise there was a timeout waiting for 0x01 from the mmc. IT AL WAYS EXITS HERE AS I GET NO RESPONSE FROM THE MMC ON THE MOSI LINE (i.e. MOSI=1 ALL THE TIME)
    }

    printf("Got response from MMC\n\r");

    i = 0;

    while((i < 255) && (mmc_response(0x00)==1)) // must keep sending command if response
    {
    spi_write_sw(0x41); // send mmc command one to bring out of idle state
    spi_write_sw(0x00); // all the arguments are 0x00 for command one
    spi_write_sw(0x00);
    spi_write_sw(0x00);
    spi_write_sw(0x00);
    spi_write_sw(0xFF); // checksum is no longer required but we always send 0xFF
    i++;
    }
    if(i >= 254) return 1; // if >= 254 then there was a timeout waiting for 0x00 from the mmc

    printf("Got out of idle response from MMC\n\r");

    mmc_disable(); // set MMC_CS = 1 (off)

    spi_write_sw(0xFF); // extra clocks to allow mmc to finish off what it is doing

    mmc_enable(); // set MMC_CS = 0 (on)

    spi_write_sw(0x50); // CMD16, set block lenght
    spi_write_sw(0x00);
    spi_write_sw(0x00);
    spi_write_sw(0x02); // high block length bits - 512 bytes
    spi_write_sw(0x00); // low block length bits
    spi_write_sw(0xFF); // checksum is no longer required but we always send 0xFF

    if((mmc_response(0x00))==1) return 1;
    mmc_disable(); // set SS = 1 (off)
    printf("Got set block length response from MMC\n\r");
    return 0;
    }


    int mmc_response(int response)
    {
    unsigned long count = 0xFFFF; // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
    int data_received;
    data_received=spi_read_sw_8bit_word_250KHz();
    while(data_received != response && --count > 0)
    {
    data_received=spi_read_sw_8bit_word_250KHz();
    }

    if(count==0) return 1; // loop was exited due to timeout
    else return 0; // loop was exited before timeout
    }


    void spi_write_sw_250KHz(int data)
    {
    int i;

    for(i=1;i<=8;++i)
    {
    output_low(SPI_CLK);
    delay_us(1);
    output_bit(SPI_SDO, shift_left(&data,1,0));
    delay_us(1);
    output_high(SPI_CLK);
    delay_us(2);
    }
    output_low(SPI_CLK); //Warning. This leaves SCK at 0 after each write. Thus polarity is low.
    output_high(SPI_SDO);
    }

    int spi_read_sw_8bit_word_250KHz()
    {
    BYTE i;
    int data;

    for(i=1;i<=8;++i) {
    output_low(SPI_CLK);
    delay_us(2);
    output_high(SPI_CLK);
    delay_us(2);
    shift_left(&data,1,input(SPI_SDI));
    }
    return data;
    }
    #10
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:40:51 (permalink)
    0
    These are the screenshots of the SPI signals.
    Green=SCK, Red=MOSI, Yellow=MISO, Blue=MMC_CS

    First picture:
    First 74+ clocks, followed by the Reset command (data is 0x40, 0x00, 0x00, 0x00, 0x00, 0x95). Last clock pulses not shown (the ones where the MMC should respond, see next picture). SCK frequency is 135KHz.

    Second picture:
    First bytes of the Reset command (data 0x40, 0x00), with MMC_CS going from high to low. SCK frequency is 135KHz.

    Third picture:
    Last clock pulses, where the MMC should send a response pulling low the MISO line, but it doesn´t (all the pulses are not shown in the screenshot, I send a lot of pulses, see code above, and there is no response)


    Attached Image(s)

    #11
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:41:35 (permalink)
    0
    Second screenshot

    Attached Image(s)

    #12
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:42:02 (permalink)
    0
    Third screenshot

    Attached Image(s)

    #13
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:43:17 (permalink)
    0
    Detail of the reset command timing

    Data 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 (MMC_CS not shown)

    Attached Image(s)

    #14
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 04:46:15 (permalink)
    0
    OK, I'm still unclear about the shift_left() routine. It seems this takes a pointer to an unsigned int (16 bits, signed). Since SPI needs to send MSB first, your shift left really should be shift right, and if you give it a pointer to 16 bit integer it should return the stae of bit 7. 

    Can you detail exactly what shift_left() does? Do you have a code fragment or a definition of this function? I suspect you are not sending data correctly (or probably in reverse order) so the microSD is never seeing the correct command.

    Mark.

    Edit: Well it looks from your diagrams that you are sending the correct data.

    Have you checked the make of microSD card you have can use SPI?

    The only other thing I can suggest is that you retry the reset command. You would need to de-assert CS#, give it 8 dummy clocks with CS# de-asserted (always do that at the end of any command, basically send 0xFF with CS# de-asserted), re-assert CS# and do the command again, and put in a continual loop. Although a bit noisy your timing diagrams look OK to me.

    Mark.
    post edited by markp - 2010/04/14 05:08:06
    #15
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 05:26:39 (permalink)
    0
    Well, actually I think that in these first command I am not using SPI mode, but rather MMC mode, and that´s where the first precalculated CRC (0x95) comes from. In both modes the communication is done through the same SCK, MOSI, MISO lines, I think the only difference being the use of CRC and the frequency. So, if I´m not wrong, I am not still writing to the card in SPI mode.

    I will check the manufacturer´s datasheet of the microSD to see if I find anything that I am not taking into account.
    #16
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 05:30:55 (permalink)
    0
    The card is a SanDisk 1GB microSD (0925903520C4US I guess it´s the product or serial number) on a SanDisk microSD-to-SD adapter.
    #17
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2010/04/14 05:53:05 (permalink)
    0
    Yes, by default CRC is on (which is why you need to supply one during reset) and it is in MMC mode. It detects whether it is supposed to switch to SPI by looking at the state of CS# during the reset command. A low on CS# means go into SPI mode.
    #18
    sd_trial
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2011/12/13 21:30:31
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2011/12/14 07:34:29 (permalink)
    0
    hi, I am facing lot of problem in interfacing PIC18F4550 with a micoSD card. I could not put the device in to SPI bus mode after sending the required commands. ie... after sending more than 74 clock pulses on setting Chip select high and then sending 0x40 0x00 0x00 0x00 0x00 0x95. I found you had faced the same problem. Please help me if you have any solution. your comments are most welcome. Thank you.
    #19
    el_litri
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2010/02/20 18:57:37
    • Location: 0
    • Status: offline
    RE: Bit banging SPI to MMC/SD card problem 2012/01/15 13:07:37 (permalink)
    0
    Hi sd_trial please send me your email via Private Message and I will send you example code that I used for PIC to SD/MMC interface. I wish you the best luck with your project. Best regards el_litri
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5