This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SD card FR_NOT_READY

Other Parts Discussed in Thread: CSD, EK-LM3S3748

hi,

     i am making use sd card with my controller(TM4C123).

    when i am trying with it, i am getting a f_opendir (&g_sDirObject, g_cCwdBuf) ; return status as FR_NOT _READY.

     i checked by checking  sd cards even though same thing came.i came to know that due to in correct  initialization this problem arrises.

    but i am not getting where i went wrong, here is my sd init funtion.

 

void SDCardInit()
{
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

GPIOPinConfigure(GPIO_PD0_SSI3CLK);
GPIOPinConfigure(GPIO_PD1_SSI3FSS);
GPIOPinConfigure(GPIO_PD2_SSI3RX);
GPIOPinConfigure(GPIO_PD3_SSI3TX);

ROM_GPIOPinTypeSSI(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

ROM_GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU);

}

can any one tell me where i missed..........

  • Hi,

    You should add the file Tiva/third_party/fatfs/port/mmc-dk-tm4c123g.c to your project. If you already done it, please note two problems:

    a) the initialization of SSI is already done in this file;

    b) This file initialize SSI0 rather than SSI3, so it is quite obvious you will get some wrong results.

    Read that file - and if you still need to use SSI3, you should modify it for your SSI3 pins.

    Petrei

  • hi Petrei,

    i already changed pins in Tiva/third_party/fatfs/port/mmc-dk-LM4F120H5QR.c to ssi3 even though i got the same problem.

    i am using Tiva/third_party/fatfs/port/mmc-dk-LM4F120H5QR.c becaz i dont have it for dk-tm4c123g.any way i think this wont be the problem.

    one more thing is that On D0,D1,D2,D3 both ssi1 and ssi3 are there i tried two with no success.

    here the way i changed pins in Tiva/third_party/fatfs/port/mmc-dk-LM4F120H5QR.c


    // SSI port
    #define SDC_SSI_BASE SSI3_BASE
    #define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI3

    // GPIO for SSI pins
    #define SDC_GPIO_PORT_BASE GPIO_PORTD_BASE
    #define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOD
    #define SDC_SSI_CLK GPIO_PIN_0
    #define SDC_SSI_TX GPIO_PIN_3
    #define SDC_SSI_RX GPIO_PIN_2
    #define SDC_SSI_FSS GPIO_PIN_1
    #define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | \
    SDC_SSI_FSS)

    in init i called like this

    void SDCardInit()
    {
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    }

    is there any thing to change...


  • Hi,

    Some problems:

    a) While in the first post you said you have a tm4c, now you change it to lm4f - take care the pins may not have the same location or configuration. Check again.

    b) You should first learn from the sd_card example in boards/ek-lm4f232/sd-card/sd-card.c - there the initialization of sd-card is simply

    //
    // Mount the file system, using logical disk 0.
    //
    iFResult = f_mount(0, &g_sFatFs);
    if(iFResult != FR_OK)….. so start with f_mount file, read it, see what functions are called inside, see how it works.

    Note also the SSIFSS is GPIO pin for sd-card - so take care...

    c) Related to SSI3, in Tiva 2.0 there is the file mmc-dk-tm4c129x.c in ports folder and uses SSI3 - look how SSI3 is initialized.

    Petrei

  • hi petrei,

    thanks a lot for your support, my problem got solved.

    shyam

  • shyam reddy said:
    ROM_GPIOPinTypeSSI(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    ROM_GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3,
    GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU);

    For the record (you and/or interested others) that first call to, "ROM_GPIOPinTypeSSI()" should automate/embed a call to, "ROM_GPIOPadConfigSet()."   And - review of GPIOPinTypeSSI() - w/in StellarisWare\driverlib: gpio.c - reveals, "GPIO_STRENGTH_2MA, & GPIO_PIN_TYPE_STD" - both differing from your selection.

    May not matter - but always best to comply with that which is well-known and extensively tested...

    And - while you report success, "my problem got solved!" - that in itself does not provide, "useful guidance" to "follow-on readers" - who may well benefit from the more specific & detailed advice you can now uniquely provide...

  • hi,

    there was some initialization problem.

    i just done pin muxing for clk,ss,ssiTx,ssiRx  by making use of GPIO_PINCONFIG(); in power_on(). function of k-lm4f232.c file.

    here is my code 

    void SDCardInit()
    {
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    }


    LM4F232.c

    /*-----------------------------------------------------------------------*/
    /* MMC/SDC (in SPI mode) control module (C)ChaN, 2007 */
    /*-----------------------------------------------------------------------*/
    /* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros */
    /* are platform dependent. */
    /*-----------------------------------------------------------------------*/

    /*
    * This file was modified from a sample available from the FatFs
    * web site. It was modified to work with a Stellaris EK-LM4F232H5QD
    * evaluation board.
    */

    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "third_party/fatfs/src/diskio.h"

    /* Definitions for MMC/SDC command */
    #define CMD0 (0x40+0) /* GO_IDLE_STATE */
    #define CMD1 (0x40+1) /* SEND_OP_COND */
    #define CMD8 (0x40+8) /* SEND_IF_COND */
    #define CMD9 (0x40+9) /* SEND_CSD */
    #define CMD10 (0x40+10) /* SEND_CID */
    #define CMD12 (0x40+12) /* STOP_TRANSMISSION */
    #define CMD16 (0x40+16) /* SET_BLOCKLEN */
    #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
    #define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
    #define CMD23 (0x40+23) /* SET_BLOCK_COUNT */
    #define CMD24 (0x40+24) /* WRITE_BLOCK */
    #define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
    #define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */
    #define CMD55 (0x40+55) /* APP_CMD */
    #define CMD58 (0x40+58) /* READ_OCR */

    /* Peripheral definitions for EK-LM3S3748 board */
    // SSI port
    #define SDC_SSI_BASE SSI3_BASE
    #define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI3

    // GPIO for SSI pins
    #define SDC_GPIO_PORT_BASE GPIO_PORTD_BASE
    #define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOD
    #define SDC_SSI_CLK GPIO_PIN_0
    #define SDC_SSI_TX GPIO_PIN_3
    #define SDC_SSI_RX GPIO_PIN_2
    #define SDC_SSI_FSS GPIO_PIN_1
    #define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | \
    SDC_SSI_FSS)

    // asserts the CS pin to the card
    static
    void SELECT (void)
    {
    ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_FSS, 0);
    }

    // de-asserts the CS pin to the card
    static
    void DESELECT (void)
    {
    ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_FSS, SDC_SSI_FSS);
    }

    /*--------------------------------------------------------------------------

    Module Private Functions

    ---------------------------------------------------------------------------*/

    static volatile
    DSTATUS Stat = STA_NOINIT; /* Disk status */

    static volatile
    BYTE Timer1, Timer2; /* 100Hz decrement timer */

    static
    BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */

    static
    BYTE PowerFlag = 0; /* indicates if "power" is on */

    /*-----------------------------------------------------------------------*/
    /* Transmit a byte to MMC via SPI (Platform dependent) */
    /*-----------------------------------------------------------------------*/

    static
    void xmit_spi(BYTE dat)
    {
    DWORD rcvdat;

    ROM_SSIDataPut(SDC_SSI_BASE, dat); /* Write the data to the tx fifo */

    ROM_SSIDataGet(SDC_SSI_BASE, &rcvdat); /* flush data read during the write */
    }


    /*-----------------------------------------------------------------------*/
    /* Receive a byte from MMC via SPI (Platform dependent) */
    /*-----------------------------------------------------------------------*/

    static
    BYTE rcvr_spi (void)
    {
    DWORD rcvdat;

    ROM_SSIDataPut(SDC_SSI_BASE, 0xFF); /* write dummy data */

    ROM_SSIDataGet(SDC_SSI_BASE, &rcvdat); /* read data frm rx fifo */

    return (BYTE)rcvdat;
    }


    static
    void rcvr_spi_m (BYTE *dst)
    {
    *dst = rcvr_spi();
    }

    /*-----------------------------------------------------------------------*/
    /* Wait for card ready */
    /*-----------------------------------------------------------------------*/

    static
    BYTE wait_ready (void)
    {
    BYTE res;


    Timer2 = 50; /* Wait for ready in timeout of 500ms */
    rcvr_spi();
    do
    res = rcvr_spi();
    while ((res != 0xFF) && Timer2);

    return res;
    }

    /*-----------------------------------------------------------------------*/
    /* Send 80 or so clock transitions with CS and DI held high. This is */
    /* required after card power up to get it into SPI mode */
    /*-----------------------------------------------------------------------*/
    static
    void send_initial_clock_train(void)
    {
    unsigned int i;
    DWORD dat;

    /* Ensure CS is held high. */
    DESELECT();

    /* Switch the SSI TX line to a GPIO and drive it high too. */
    ROM_GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
    ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_TX, SDC_SSI_TX);

    /* Send 10 bytes over the SSI. This causes the clock to wiggle the */
    /* required number of times. */
    for(i = 0 ; i < 10 ; i++)
    {
    /* Write DUMMY data. SSIDataPut() waits until there is room in the */
    /* FIFO. */
    ROM_SSIDataPut(SDC_SSI_BASE, 0xFF);

    /* Flush data read during data write. */
    ROM_SSIDataGet(SDC_SSI_BASE, &dat);
    }

    /* Revert to hardware control of the SSI TX line. */
    ROM_GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
    }

    /*-----------------------------------------------------------------------*/
    /* Power Control (Platform dependent) */
    /*-----------------------------------------------------------------------*/
    /* When the target system does not support socket power control, there */
    /* is nothing to do in these functions and chk_power always returns 1. */

    static
    void power_on (void)
    {
    /*
    * This doesn't really turn the power on, but initializes the
    * SSI port and pins needed to talk to the card.
    */

    /* Enable the peripherals used to drive the SDC on SSI */
    ROM_SysCtlPeripheralEnable(SDC_SSI_SYSCTL_PERIPH);
    ROM_SysCtlPeripheralEnable(SDC_GPIO_SYSCTL_PERIPH);

    /*
    * Configure the appropriate pins to be SSI instead of GPIO. The FSS (CS)
    * signal is directly driven to ensure that we can hold it low through a
    * complete transaction with the SD card.
    */
    ROM_GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK);
    ROM_GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_FSS);


    ROM_GPIOPinConfigure(GPIO_PD0_SSI3CLK);
    ROM_GPIOPinConfigure(GPIO_PD1_SSI3FSS);
    ROM_GPIOPinConfigure(GPIO_PD2_SSI3RX);
    ROM_GPIOPinConfigure(GPIO_PD3_SSI3TX);
    /*
    * Set the SSI output pins to 4MA drive strength and engage the
    * pull-up on the receive line.
    */
    ROM_GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_RX, GPIO_STRENGTH_4MA,
    GPIO_PIN_TYPE_STD_WPU);
    ROM_GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_CLK | SDC_SSI_TX | SDC_SSI_FSS,
    GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

    /* Configure the SSI0 port */
    ROM_SSIConfigSetExpClk(SDC_SSI_BASE, ROM_SysCtlClockGet(),
    SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 400000, 8);
    ROM_SSIEnable(SDC_SSI_BASE);

    /* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
    /* to be able to accept a native command. */
    send_initial_clock_train();

    PowerFlag = 1;
    }

    // set the SSI speed to the max setting
    static
    void set_max_speed(void)
    {
    unsigned long i;

    /* Disable the SSI */
    ROM_SSIDisable(SDC_SSI_BASE);

    /* Set the maximum speed as half the system clock, with a max of 12.5 MHz. */
    i = ROM_SysCtlClockGet() / 2;
    if(i > 12500000)
    {
    i = 12500000;
    }

    /* Configure the SSI0 port to run at 12.5MHz */
    ROM_SSIConfigSetExpClk(SDC_SSI_BASE, ROM_SysCtlClockGet(),
    SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, i, 8);

    /* Enable the SSI */
    ROM_SSIEnable(SDC_SSI_BASE);
    }

    static
    void power_off (void)
    {
    PowerFlag = 0;
    }

    static
    int chk_power(void) /* Socket power state: 0=off, 1=on */
    {
    return PowerFlag;
    }

    /*-----------------------------------------------------------------------*/
    /* Receive a data packet from MMC */
    /*-----------------------------------------------------------------------*/

    static
    BOOL rcvr_datablock (
    BYTE *buff, /* Data buffer to store received data */
    UINT btr /* Byte count (must be even number) */
    )
    {
    BYTE token;


    Timer1 = 100;
    do { /* Wait for data packet in timeout of 100ms */
    token = rcvr_spi();
    } while ((token == 0xFF) && Timer1);
    if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */

    do { /* Receive the data block into buffer */
    rcvr_spi_m(buff++);
    rcvr_spi_m(buff++);
    } while (btr -= 2);
    rcvr_spi(); /* Discard CRC */
    rcvr_spi();

    return TRUE; /* Return with success */
    }

    /*-----------------------------------------------------------------------*/
    /* Send a data packet to MMC */
    /*-----------------------------------------------------------------------*/

    #if _READONLY == 0
    static
    BOOL xmit_datablock (
    const BYTE *buff, /* 512 byte data block to be transmitted */
    BYTE token /* Data/Stop token */
    )
    {
    BYTE resp, wc;


    if (wait_ready() != 0xFF) return FALSE;

    xmit_spi(token); /* Xmit data token */
    if (token != 0xFD) { /* Is data token */
    wc = 0;
    do { /* Xmit the 512 byte data block to MMC */
    xmit_spi(*buff++);
    xmit_spi(*buff++);
    } while (--wc);
    xmit_spi(0xFF); /* CRC (Dummy) */
    xmit_spi(0xFF);
    resp = rcvr_spi(); /* Reveive data response */
    if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
    return FALSE;
    }

    return TRUE;
    }
    #endif /* _READONLY */

    /*-----------------------------------------------------------------------*/
    /* Send a command packet to MMC */
    /*-----------------------------------------------------------------------*/

    static
    BYTE send_cmd (
    BYTE cmd, /* Command byte */
    DWORD arg /* Argument */
    )
    {
    BYTE n, res;


    if (wait_ready() != 0xFF) return 0xFF;

    /* Send command packet */
    xmit_spi(cmd); /* Command */
    xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
    xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
    xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
    xmit_spi((BYTE)arg); /* Argument[7..0] */
    n = 0xff;
    if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
    if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
    xmit_spi(n);

    /* Receive command response */
    if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
    n = 10; /* Wait for a valid response in timeout of 10 attempts */
    do
    res = rcvr_spi();
    while ((res & 0x80) && --n);

    return res; /* Return with the response value */
    }

    /*-----------------------------------------------------------------------*
    * Send the special command used to terminate a multi-sector read.
    *
    * This is the only command which can be sent while the SDCard is sending
    * data. The SDCard spec indicates that the data transfer will stop 2 bytes
    * after the 6 byte CMD12 command is sent and that the card will then send
    * 0xFF for between 2 and 6 more bytes before the R1 response byte. This
    * response will be followed by another 0xFF byte. In testing, however, it
    * seems that some cards don't send the 2 to 6 0xFF bytes between the end of
    * data transmission and the response code. This function, therefore, merely
    * reads 10 bytes and, if the last one read is 0xFF, returns the value of the
    * latest non-0xFF byte as the response code.
    *
    *-----------------------------------------------------------------------*/

    static
    BYTE send_cmd12 (void)
    {
    BYTE n, res, val;

    /* For CMD12, we don't wait for the card to be idle before we send
    * the new command.
    */

    /* Send command packet - the argument for CMD12 is ignored. */
    xmit_spi(CMD12);
    xmit_spi(0);
    xmit_spi(0);
    xmit_spi(0);
    xmit_spi(0);
    xmit_spi(0);

    /* Read up to 10 bytes from the card, remembering the value read if it's
    not 0xFF */
    for(n = 0; n < 10; n++)
    {
    val = rcvr_spi();
    if(val != 0xFF)
    {
    res = val;
    }
    }

    return res; /* Return with the response value */
    }

    /*--------------------------------------------------------------------------

    Public Functions

    ---------------------------------------------------------------------------*/


    /*-----------------------------------------------------------------------*/
    /* Initialize Disk Drive */
    /*-----------------------------------------------------------------------*/

    DSTATUS disk_initialize (
    BYTE drv /* Physical drive nmuber (0) */
    )
    {
    BYTE n, ty, ocr[4];


    if (drv) return STA_NOINIT; /* Supports only single drive */
    if (Stat & STA_NODISK) return Stat; /* No card in the socket */

    power_on(); /* Force socket power on */
    send_initial_clock_train(); /* Ensure the card is in SPI mode */

    SELECT(); /* CS = L */
    ty = 0;
    if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
    Timer1 = 100; /* Initialization timeout of 1000 msec */
    if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
    for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
    if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
    do {
    if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
    } while (Timer1);
    if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
    for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
    ty = (ocr[0] & 0x40) ? 6 : 2;
    }
    }
    } else { /* SDC Ver1 or MMC */
    ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
    do {
    if (ty == 2) {
    if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
    } else {
    if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
    }
    } while (Timer1);
    if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
    ty = 0;
    }
    }
    CardType = ty;
    DESELECT(); /* CS = H */
    rcvr_spi(); /* Idle (Release DO) */

    if (ty) { /* Initialization succeded */
    Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
    set_max_speed();
    } else { /* Initialization failed */
    power_off();
    }

    return Stat;
    }

    /*-----------------------------------------------------------------------*/
    /* Get Disk Status */
    /*-----------------------------------------------------------------------*/

    DSTATUS disk_status (
    BYTE drv /* Physical drive nmuber (0) */
    )
    {
    if (drv) return STA_NOINIT; /* Supports only single drive */
    return Stat;
    }

    /*-----------------------------------------------------------------------*/
    /* Read Sector(s) */
    /*-----------------------------------------------------------------------*/

    DRESULT disk_read (
    BYTE drv, /* Physical drive nmuber (0) */
    BYTE *buff, /* Pointer to the data buffer to store read data */
    DWORD sector, /* Start sector number (LBA) */
    BYTE count /* Sector count (1..255) */
    )
    {
    if (drv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;

    if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */

    SELECT(); /* CS = L */

    if (count == 1) { /* Single block read */
    if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
    && rcvr_datablock(buff, 512))
    count = 0;
    }
    else { /* Multiple block read */
    if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
    do {
    if (!rcvr_datablock(buff, 512)) break;
    buff += 512;
    } while (--count);
    send_cmd12(); /* STOP_TRANSMISSION */
    }
    }

    DESELECT(); /* CS = H */
    rcvr_spi(); /* Idle (Release DO) */

    return count ? RES_ERROR : RES_OK;
    }

    /*-----------------------------------------------------------------------*/
    /* Write Sector(s) */
    /*-----------------------------------------------------------------------*/

    #if _READONLY == 0
    DRESULT disk_write (
    BYTE drv, /* Physical drive nmuber (0) */
    const BYTE *buff, /* Pointer to the data to be written */
    DWORD sector, /* Start sector number (LBA) */
    BYTE count /* Sector count (1..255) */
    )
    {
    if (drv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;
    if (Stat & STA_PROTECT) return RES_WRPRT;

    if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */

    SELECT(); /* CS = L */

    if (count == 1) { /* Single block write */
    if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
    && xmit_datablock(buff, 0xFE))
    count = 0;
    }
    else { /* Multiple block write */
    if (CardType & 2) {
    send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
    }
    if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
    do {
    if (!xmit_datablock(buff, 0xFC)) break;
    buff += 512;
    } while (--count);
    if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
    count = 1;
    }
    }

    DESELECT(); /* CS = H */
    rcvr_spi(); /* Idle (Release DO) */

    return count ? RES_ERROR : RES_OK;
    }
    #endif /* _READONLY */

    /*-----------------------------------------------------------------------*/
    /* Miscellaneous Functions */
    /*-----------------------------------------------------------------------*/

    DRESULT disk_ioctl (
    BYTE drv, /* Physical drive nmuber (0) */
    BYTE ctrl, /* Control code */
    void *buff /* Buffer to send/receive control data */
    )
    {
    DRESULT res;
    BYTE n, csd[16], *ptr = buff;
    WORD csize;


    if (drv) return RES_PARERR;

    res = RES_ERROR;

    if (ctrl == CTRL_POWER) {
    switch (*ptr) {
    case 0: /* Sub control code == 0 (POWER_OFF) */
    if (chk_power())
    power_off(); /* Power off */
    res = RES_OK;
    break;
    case 1: /* Sub control code == 1 (POWER_ON) */
    power_on(); /* Power on */
    res = RES_OK;
    break;
    case 2: /* Sub control code == 2 (POWER_GET) */
    *(ptr+1) = (BYTE)chk_power();
    res = RES_OK;
    break;
    default :
    res = RES_PARERR;
    }
    }
    else {
    if (Stat & STA_NOINIT) return RES_NOTRDY;

    SELECT(); /* CS = L */

    switch (ctrl) {
    case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
    if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
    if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
    csize = csd[9] + ((WORD)csd[8] << 8) + 1;
    *(DWORD*)buff = (DWORD)csize << 10;
    } else { /* MMC or SDC ver 1.XX */
    n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
    csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
    *(DWORD*)buff = (DWORD)csize << (n - 9);
    }
    res = RES_OK;
    }
    break;

    case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
    *(WORD*)buff = 512;
    res = RES_OK;
    break;

    case CTRL_SYNC : /* Make sure that data has been written */
    if (wait_ready() == 0xFF)
    res = RES_OK;
    break;

    case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
    if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
    && rcvr_datablock(ptr, 16))
    res = RES_OK;
    break;

    case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
    if (send_cmd(CMD10, 0) == 0 /* READ_CID */
    && rcvr_datablock(ptr, 16))
    res = RES_OK;
    break;

    case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
    if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
    for (n = 0; n < 4; n++)
    *ptr++ = rcvr_spi();
    res = RES_OK;
    }

    // case MMC_GET_TYPE : /* Get card type flags (1 byte) */
    // *ptr = CardType;
    // res = RES_OK;
    // break;

    default:
    res = RES_PARERR;
    }

    DESELECT(); /* CS = H */
    rcvr_spi(); /* Idle (Release DO) */
    }

    return res;
    }

    /*-----------------------------------------------------------------------*/
    /* Device Timer Interrupt Procedure (Platform dependent) */
    /*-----------------------------------------------------------------------*/
    /* This function must be called in period of 10ms */

    void disk_timerproc (void)
    {
    // BYTE n, s;
    BYTE n;


    n = Timer1; /* 100Hz decrement timer */
    if (n) Timer1 = --n;
    n = Timer2;
    if (n) Timer2 = --n;

    }

    /*---------------------------------------------------------*/
    /* User Provided Timer Function for FatFs module */
    /*---------------------------------------------------------*/
    /* This is a real time clock service to be called from */
    /* FatFs module. Any valid time must be returned even if */
    /* the system does not support a real time clock. */

    DWORD get_fattime (void)
    {

    return ((2007UL-1980) << 25) // Year = 2007
    | (6UL << 21) // Month = June
    | (5UL << 16) // Day = 5
    | (11U << 11) // Hour = 11
    | (38U << 5) // Min = 38
    | (0U >> 1) // Sec = 0
    ;

    }

    shyam

  • Hi Shyam

    I'm facing the same problem... FR_NOT_READY!!

    I'm using DK-TM4C129x, microSD of 2GB. I dint make any changes in the example code.

    Appreciate your help.

    Regards

    Alston

  • hi alston,

    this error comes when the initialisation is not proper or not card when there is an sd card problem.

    better check with your initialization is proper r not if OK than check by changing the Sd card.

    this error comes when the system is not able to read the SD card.