AnsweredAssumed Answered

Problems writing to SD card in SPI mode

Question asked by 1200rata on Aug 11, 2011
I'm trying to comunicate with SD card with  STM32F100RB controller via SPI.
I am able to erase blocks on card, and to read them. The problem is about writing blocks to card. I am able to write something to card, and i can read it, but i cant get correct response after writing bytes to card. Maybe anyone can tell me what i am doing wrong?
My code:

void SPI_SD_Init(void) 
{
     GPIO_InitTypeDef gpio;

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

     gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
     gpio.GPIO_Speed = GPIO_Speed_50MHz;
     gpio.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOA, &gpio);

     gpio.GPIO_Pin = GPIO_Pin_4;
     gpio.GPIO_Speed = GPIO_Speed_50MHz;
     gpio.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_Init(GPIOA, &gpio);

     SPI_SetSpeed(SD_SPEED_400KHZ);

void SPI_SetSpeed(SD_Speed_TypeDef speed)
{
     SPI_InitTypeDef spi;
       int prescaler = SPI_BaudRatePrescaler_64;
  
       if(speed == SD_SPEED_400KHZ){
          prescaler = SPI_BaudRatePrescaler_64;
     }
     else if (speed == SD_SPEED_25MHZ){
          prescaler = SPI_BaudRatePrescaler_2;
     }
     // 6 mhz / 187khz  ; 100<x<400khz, and <25mhz
     
     SPI_Cmd(SPI_SD, DISABLE);

     spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
     spi.SPI_Mode = SPI_Mode_Master;
     spi.SPI_DataSize = SPI_DataSize_8b;
     spi.SPI_CPOL = SPI_CPOL_Low;
     spi.SPI_CPHA = SPI_CPHA_1Edge;

     spi.SPI_NSS = SPI_NSS_Soft;
     spi.SPI_BaudRatePrescaler = prescaler;
     spi.SPI_FirstBit = SPI_FirstBit_MSB;
     spi.SPI_CRCPolynomial = 7;
     SPI_Init(SPI_SD, &spi);

     SPI_Cmd(SPI_SD, ENABLE);
}

unsigned char SPI_WriteByte(unsigned char data)   
{   
    u8 Data = 0;   
   
    /* Wait until the transmit buffer is empty */   
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);   
    /* Send the byte */   
    SPI_I2S_SendData(SPI1, data);   
       
    /* Wait until a data is received */   
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);   
    /* Get the received data */   
    Data = SPI_I2S_ReceiveData(SPI1);   
       
    /* Return the shifted data */   
    return Data;   
}   

u8 SD_Init(void)
{

     u8 retry;
     u8 response=0;
     u8 i;

     retry = 0x00;

     SD_CS_LOW();

     do   
    {
          for(i = 0; i < 10; i++)
          {
               SPI_WriteByte(0xff);
          }   
        response = SD_sendCommand(GO_IDLE_STATE, 0);   //send idle command 
          
          printf("Idle cmd - ");
          printfResponse(response);
            
        retry++;   
        if(retry > 100)
          {
               printf("SD init fail...\n\r");
               return 1;       //time out
          }   
    } while(response != 0x01);
     
     SD_CS_HIGH();
     
     SPI_WriteByte(0xff);
     SPI_WriteByte(0xff);

     retry = 0;

     do
     {
          response = SD_sendCommand(SEND_OP_COND, 0);     //activate card's initialization process
          response = SD_sendCommand(SEND_OP_COND, 0); //same command sent again for compatibility with some cards
          retry++;
          if(retry > 100)
          {
               printf("SD init fail..\n\r");
               return 1;       //time out
          }   
               
     }
     while(response);
     
     response = SD_sendCommand(CRC_ON_OFF, OFF);      //disable CRC; deafault - CRC disabled in SPI mode
     response = SD_sendCommand(SET_BLOCK_LEN, 512);      //
 

     SPI_SetSpeed(SD_SPEED_25MHZ);
    return 0;    //normal return       
}

u8 SD_writeSingleBlock(u32 startBlock, u8* buffer)
{
     u8 response = 0x04;
     u8 retry = 0;
     int i;

     SD_CS_LOW();     

     response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock<<9); //write a Block command
     if(response != 0x00) //check for SD status: 0x00 - OK (No flags set)
     return response;


     response = SPI_WriteByte(0xfe);      //Send start block token 0xfe (0x11111110)

     for(i=0; i<512; i++)    //send 512 bytes data
       {     
          SPI_WriteByte(buffer[i]);
     }

     printf("512 Bytes transfered!!\r\n");     

     SPI_WriteByte(0xFF);     //transmit dummy CRC (16-bit), CRC is ignored here
     SPI_WriteByte(0xFF);


     response = SPI_WriteByte(0xFF);
     printf("%#04x \r\n",response);
     
     
     if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted
     {                              //AAA='101'-data rejected due to CRC error
            SD_CS_HIGH();              //AAA='110'-data rejected due to write error

          printf("BAD RESPONSE!!\r\n");
            return response;
     }
     
     printf("GOOD!!\r\n");


     while(!SPI_WriteByte(0xff))                //wait for SD card to complete writing and get idle
     {
          if(retry++ > 0xfffe)
          {
               SD_CS_HIGH(); 
               return 1;
          }
     }
     SD_CS_HIGH(); 
     SPI_WriteByte(0xff);
     SD_CS_LOW(); 


     while(!SPI_WriteByte(0xff)) //wait for SD card to complete writing and get idle
        
          if(retry++ > 0xfffe)
          {
               SD_CS_HIGH(); 
               return 1;
          }
     SD_CS_HIGH();

      
     return 0;          
}

int main(void)
{

     u8 buf[512];
          
       // HW configuration 
       RCC_Configuration();
       GPIO_Configuration();
     NVIC_Configuration();

     // Peripherials configuration
     USART_Configuration();

     BLUE_LED_ON();


     SPI_SD_Init();
     SD_Init();

     buf[0] = 0x99;
     buf[1] = 0x99;
     
     SD_writeSingleBlock(0, buf);

  
     while(1);
}   


Outcomes