0
\$\begingroup\$

I've implemented the low lever drivers of the fatfs. I tried to write some txt file to an SDHC card, but I can never initialize the card. MCU is STM32F103C8T6. I'm using CubeMX with HAL libraries and using SPI to communicate. I've debugged to find out that during wait_ready(), the card is supposed to return 0xFF to indicate it's ready, but in my case it returns 0x00, no matter how long I wait. If I omit the the wait_ready() and send the IDLE command(CMD0), I still get 0x00 as a response. I enabled the internal pull-up for the MISO pin, didn't help. The interesting part is that, when I probed the MISO pin right after its initialization, I noticed it was at 0.01 volts. It seems to me that it was not being pulled high. I also made sure that SPI clock speed was in between 100khz-400khz range.

I managed to write to the card by connecting it to my computer. Also managed to write with an arduino. Following are the relevant parts of my code. You can ignore the timeout implementations.

static BYTE wait_ready(void) {
Timer2 = 255;
rcvr_spi();
do
    res = rcvr_spi();
while ((res != 0xFF) && Timer2--);

return (res == 0xFF) ? 1 : 0;
}

void deselect()
{
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
    xmit_spi(0xFF);
}

uint8_t select()
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);

xmit_spi(0xFF);
if(wait_ready()) return 1;
deselect();

return 0;
}

DSTATUS USER_initialize (
BYTE pdrv           /* Physical drive nmuber to identify the drive */
)
{
  BYTE n, ty, ocr[4];

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

deselect();

//send_initial_clock_train();
for (int i = 0; i < 10; i++)
    xmit_spi(0xFF); 

HAL_Delay(10);

ty = 0;
uint32_t tick = HAL_GetTick();

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 */


return Stat;
}

static void xmit_spi(BYTE Data)
{
 while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
 HAL_SPI_Transmit(&hspi1, &Data, 1, 5000);
}

static BYTE rcvr_spi(void)
{
 unsigned char Dummy, Data;
 Dummy = 0xFF;
 Data = 0;
 while ((HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY));

 HAL_SPI_TransmitReceive(&hspi1, &Dummy, &Data, 1, 5000);

 return Data;
}

What am I doing wrong?

\$\endgroup\$
  • 2
    \$\begingroup\$ Try to identify an operation you can perform on the card that should return a more complex bit pattern - ie, read an ID or capacity register. You need to validate the low level communication before you worry about anything else. If you have a digital scope or USB-based logic analyzer they can be useful too. With a loop doing some safe operation even an analog scope could give some insight. \$\endgroup\$ – Chris Stratton Aug 9 '18 at 14:10
  • \$\begingroup\$ 0x00 in your case probably means that bus is all time low. Probably it is not an answer from device. Check your wiring first. Could you post code which initialize SPI and SPI's GPIO pins? \$\endgroup\$ – Misaz Sep 18 '18 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.