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.

CCS/TMS570LS0432: SD Card Interfacing

Part Number: TMS570LS0432
Other Parts Discussed in Thread: LAUNCHXL-TMS57004, , HALCOGEN

Tool/software: Code Composer Studio

Hello.

We are interfacing an SD card (SanDisk  8GB MicroSDHC card) to TMS570LS0432 MCU (LaunchXL-TMS57004). SPI2 pins are being used. The code is attached below. We are facing the following issues:-

1) The minimum baud rate that we are able to generate in HALCoGen is 350kHz. We are trying to generate 250kHz, as its suggested to start the SD card initialization at a lower baud rate. However, we are not able to reduce the baud rate below 350KHZ.

2) After sending CMD0 command for SPI communication, the response is constantly 0. It is supposed to show 1 upon sending the CMD0 command.

3) Can you suggest a sample SPI code for SD card interfacing that we can build on. We have gone through several threads on the e2e forum, but we are not able to get them to work.

Regards,

Kartik

/** @file sys_main.c 
*   @brief Application main file
*   @date 07-July-2017
*   @version 04.07.00
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* 
* Copyright (C) 2009-2016 Texas Instruments Incorporated - www.ti.com 
* 
* 
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


/* USER CODE BEGIN (0) */

#include "sys_common.h"
#include "sci.h"
#include "spi.h"
#include "gio.h"
#include "stdio.h"
#define CMD0        0x00            /* GO_IDLE_STATE */
#define CMD1        0x01             /* SEND_OP_COND (MMC) */
#define CMD8        0x08
#define CMD17       0x11             /* READ_SINGLE */
#define WRITE_SINGLE_BLOCK      0x18
#define DATA_START    0xFE
#define FO_FIRST_SECT 0x1C6           // first sector of first partition offset
#define DATA_ACCEPT   0x05

#define BR_BYTES 0x0B                 // (word) bytes par sector
#define BR_SXC 0x0D                   // (byte) number of sectors per cluster
#define BR_RES 0x0E                   // (word) number of reserved sectors for the boot record
#define BR_FAT_SIZE 0x24              // (word) FAT size in number of sectors
#define BR_FAT_CPY 0x10               // (byte) number of FAT copies
#define BR_MAX_ROOT 0x11              // (odd word) max number of entries in root dir


#define bytes_per_sectors        0x0B   // Size 2 bytes
#define sector_per_cluster       0x0D   // Size 1 bytes
#define number_reserved_sector   0x0E   // Size 2 bytes
#define number_par_fat           0x10   // Size 1 bytes
#define number_of_sector_par_fat 0x24 // Size 4 bytes
#define roots_director_par_cluster 0x2C // Size 4 bytes



#define First_Cluster_High   0x14
#define First_Cluster_Low    0x1A
#define file_capacity            0x1C

#define filetype 0x1C2    // To read file formart is FAt16 or Fat32


uint16 Tx_Data_command=0xFF;
uint16 Rx_Data_command;
unsigned int i;
unsigned int i=0,status;
unsigned char buffer[512];
unsigned long volumeID;
unsigned long FAT1_address;
unsigned long FAT2_address;
unsigned long root_directory_address;
unsigned long data_directory_address;
unsigned long data_directory__sector_address;
unsigned int  bytes_per_sector;
unsigned int  sectors_par_cluster;
unsigned int  reserved_sectors;
unsigned int  fat_copies;
unsigned int  root_enteries;
//unsigned int  sectors_par_fat;
unsigned long address_data_write;
unsigned int cluster_number;
unsigned long total_sector;
unsigned long fat_sectors;
unsigned long root_sectors;
unsigned long data_sectors;
unsigned long file_size;
unsigned long sectors_par_fat;
unsigned rootdir_firstcluster;
unsigned long fat_begin_lba;
unsigned long cluster_begin_lba;
unsigned long lba_address;
unsigned char filename_check[]="BMBM";
unsigned char datalogged[520];
unsigned char CR=0x0D;// ASCII value for /r
unsigned char NL=0x0A; // ASCII code for new line
unsigned int testing[86];
uint16 TX_Data_Master[1] = { 0xFF };
/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */


unsigned char SPI_Write(unsigned char cData);
void sd_card_initalize();
unsigned int crc7(unsigned char* chr,unsigned int cnt,unsigned char crc);
void sdcard_read(unsigned char sdcard_command,unsigned int long LBA);
void fat_initialize();
void check(unsigned long value);
void file_parameter_finder(unsigned long address,unsigned char *filename);
void root_directory_read(unsigned long cluster);
//void file_write(unsigned sdcard_command,unsigned long cluster);
unsigned char SDCARD_Write(unsigned long address,unsigned int size);
void file_write(unsigned char *data,unsigned long address);
void data_arrange();

/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */


void SPI_hiSpeed (int on) {

  spiREG2->FMT0 &= 0xFFFF00FF;   // mask out baudrate prescaler
  if (on == 1) {
                                 // Max. 5 MBit used for Data Transfer.
    spiREG2->FMT0 |= 0 << 8;     // baudrate prescale 10MHz / (1+1) = 5MBit
  } else {
                                 // Max. 400 kBit used in Card Initialization.
    spiREG2->FMT0 |= 24 << 8;   // baudrate prescale 10MHz / (24+1) = 400kBit
    spiREG2->FMT1 |= 24 << 8;   // baudrate prescale 10MHz / (24+1) = 400kBit
  }
}


unsigned char SPI_send (unsigned char outb) {

  while ((spiREG2->FLG & 0x0200) == 0); // Wait until TXINTFLG is set for previous transmission
  spiREG2->DAT1 = outb | 0x100D0000;    // transmit register address
  //spiREG2->DAT1 = outb | 0x17010000;    // transmit register address
  while ((spiREG2->FLG & 0x0100) == 0); // Wait until RXINTFLG is set when new value is received
  return((unsigned char)spiREG2->BUF);  // Return received value
}

void _delay_ms(uint32 ms)
{
    uint32 i = 0;
    for( i=0; i<ms*5000; i++)
    {

    }
}

unsigned int SD_CARD_CMD(unsigned char a,unsigned long int LBA)
{
    spiDAT1_t dataconfig1_t;
    unsigned char send[6];
    uint16 Tx_Data[7]={0x40,0x00,0x00,0x00,0x00,0x95,0xFF};
    unsigned int j ;
    send[0]=(a|0x40);
    send[1]=LBA>>24;
    send[2]=LBA>>16;
    send[3]=LBA>>8;
    send[4]=LBA;
    send[5]=(crc7(send, 5, 0) << 1) | 1;
    //(unsigned int)c
    for(i=0;i<6;i++)
    {
        //Tx_Data[i]=(unsigned int)send[i];

    }
    for(i=0;i<6;i++)
    {
       // SPI_send(send[i]);
        //spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
        printf("i= %d" , i);
                printf("Tx_Data_command= %d\n" , Tx_Data[i]);
        spiSendData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i]);
    }
/*
    for(i=0;i<8;i++)
        {
           // SPI_send(send[i]);
            //spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
            spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
        }
     */
    i = 100;
   do {
       // j= SPI_send (0xFF); // check if ready
       j=spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
        // sciSendByte(scilinREG, (j+'0'));
        //sciSendByte(scilinREG, (Rx_Data_command+'0'));
        printf("Rx_Data_command= %d\n" , Rx_Data_command);
        //printf("j = %d\n " , j);
      if ( Rx_Data_command != 0xFF) break;
      } while ( --i > 0);
    return (Rx_Data_command);
}


unsigned int SD_CARD_CMD1(unsigned char a,unsigned long int LBA)
{
    spiDAT1_t dataconfig1_t;
    unsigned char send[6];
    uint16 Tx_Data[7];
    unsigned int j ;
    send[0]=(a|0x40);
    send[1]=LBA>>24;
    send[2]=LBA>>16;
    send[3]=LBA>>8;
    send[4]=LBA;
    send[5]=(crc7(send, 5, 0) << 1) | 1;
    //(unsigned int)c
    for(i=0;i<6;i++)
    {
        Tx_Data[i]=(unsigned int)send[i];

    }
    for(i=0;i<7;i++)
    {
       // SPI_send(send[i]);
        //spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
        printf("i= %d" , i);
                printf("Tx_Data_command= %d\n" , Tx_Data[i]);
        spiSendData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i]);
    }
/*
    for(i=0;i<8;i++)
        {
           // SPI_send(send[i]);
            //spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
            spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
        }
     */
    i = 100;
   do {
       // j= SPI_send (0xFF); // check if ready
       j=spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
        // sciSendByte(scilinREG, (j+'0'));
        //sciSendByte(scilinREG, (Rx_Data_command+'0'));
        printf("Rx_Data_command= %d\n" , Rx_Data_command);
        //printf("j = %d\n " , j);
      if ( Rx_Data_command != 0xFF) break;
      } while ( --i > 0);
    return (j);
}
unsigned int crc7(unsigned char* chr,unsigned int cnt,unsigned char crc)
{
     unsigned int i, a;
     unsigned char Data;

     for(a = 0; a < cnt; a++){
          Data = chr[a];
          for(i = 0; i < 8; i++){
               crc <<= 1;
               if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}
               Data <<= 1;
          }
     }
     return crc & 0x7F;
}

void sd_card_initalize()
 {
    spiDAT1_t dataconfig1_t;
    uint16  command_ack;
   unsigned int counter=40;
   retry1: _delay_ms(50);
   gioSetBit(gioPORTA, 1U, 0);
   _delay_ms(1);
   command_ack=SD_CARD_CMD(CMD0,0);
   _delay_ms(1);
   gioSetBit(gioPORTA, 1U, 1);
   if(command_ack==0)
     {
       retry3:spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
       printf("Tx_Data_command= %d\n" , Tx_Data_command);
       printf("Rx_Data_command= %d\n" , Rx_Data_command);
       if(Rx_Data_command==0xFF)
       {
           printf("Rx_Data_command= %d\n" , Rx_Data_command);
                      gioSetBit(gioPORTA, 1U, 0);
                     _delay_ms(1);
                     command_ack=SD_CARD_CMD(CMD0,0);
                     _delay_ms(1);
                     gioSetBit(gioPORTA, 1U, 1);
       }
       else
       {
           goto retry3;
       }

     }

     else
     {
         if(counter==0)
         {
             counter=40;
             _delay_ms(1000);
             sciSendByte(scilinREG, 'B');
             gioSetBit(gioPORTA, 1U, 1);
                                  for ( i=0;i<10;i++)
                                         {
                                      spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
                                         }
         }
         else
         {
             counter--;

             sciSendByte(scilinREG, 'N');
         }

         //_delay_ms(4000);
      goto retry1;
     }
   retry2: _delay_ms(400);
   gioSetBit(gioPORTA, 1U, 0);
   _delay_ms(1);
   command_ack=SD_CARD_CMD(CMD1,0);
   _delay_ms(5);
   gioSetBit(gioPORTA, 1U, 1);
   if(command_ack==1)
     {
      //_delay_ms(1);
       sciSendByte(scilinREG, 'Y');
     }

     else
     {
         _delay_ms(100);
         sciSendByte(scilinREG, 'N');
      goto retry2;
     }
 }
void sdcard_read(unsigned char sdcard_command,unsigned int long LBA)
 {

    unsigned char send[6];
    unsigned int  command_ack;
    send[0]=(sdcard_command|0x40);
    send[1]=LBA>>24;
    send[2]=LBA>>16;
    send[3]=LBA>>8;
    send[4]=LBA;
    send[5]=(crc7(send, 5, 0) << 1) | 1;
    for(i=0;i<6;i++)
    {
        SPI_send(send[i]);
    }
    for(i=0;i<1000;i++)
      {
       command_ack=SPI_send(0xFF);
       if(command_ack==DATA_START)
        {
           sciSendByte(scilinREG, 'A');
          break;
        }
      }
     for(i=0;i<512;i++)
        {
          buffer[i]=SPI_send(0xFF);
        }
     SPI_send(0xFF);
     SPI_send(0xFF);
 }

 void fat_initialize()
  {
    unsigned long fat_offset=0;
    gioSetBit(gioPORTA, 1U, 0);
    sdcard_read(CMD17,0);
    gioSetBit(gioPORTA, 1U, 1);
    for(i=0;i<512;i++)
            {
              //buffer[i]=SPI_send(0xFF);
              sciSendByte(scilinREG, buffer[i]);
            }
    check(volumeID);
      // File format is FAT32
        //fat_offset|=((unsigned long)(buffer[FO_FIRST_SECT+0x03]<<16));
        fat_offset=(((unsigned long)(buffer[FO_FIRST_SECT+0x03]))<<24)|(((unsigned long)(buffer[FO_FIRST_SECT+0x02]))<<16)|(((unsigned long)(buffer[FO_FIRST_SECT+0x01]))<<8)|(((unsigned long)(buffer[FO_FIRST_SECT])));
        volumeID=512*fat_offset;
        check(volumeID);
        gioSetBit(gioPORTA, 1U, 0);
        sdcard_read(CMD17,volumeID);
        gioSetBit(gioPORTA, 1U, 1);
        bytes_per_sector=(((unsigned int)(buffer[ bytes_per_sectors+0x01])<<8))|(((unsigned int)(buffer[bytes_per_sectors])));
        sectors_par_cluster=(((unsigned int)(buffer[sector_per_cluster])));
        reserved_sectors=(((unsigned int)(buffer[number_reserved_sector+0x01])<<8))|(((unsigned int)(buffer[number_reserved_sector])));
        fat_copies=(((unsigned int)(buffer[number_par_fat])));
        sectors_par_fat=(((unsigned long)(buffer[number_of_sector_par_fat+0x03]))<<24)|(((unsigned long)(buffer[number_of_sector_par_fat+0x02]))<<16)|(((unsigned long)(buffer[number_of_sector_par_fat+0x01]))<<8)|(((unsigned long)(buffer[number_of_sector_par_fat])));
        rootdir_firstcluster=(((unsigned long)(buffer[roots_director_par_cluster+0x03]))<<24)|(((unsigned long)(buffer[roots_director_par_cluster+0x02]))<<16)|(((unsigned long)(buffer[roots_director_par_cluster+0x01]))<<8)|(((unsigned long)(buffer[roots_director_par_cluster])));
        fat_begin_lba=fat_offset+reserved_sectors;
        cluster_begin_lba=fat_begin_lba+(((unsigned long)(fat_copies))*((unsigned  long)(sectors_par_fat)));
        check(reserved_sectors);
        check(fat_begin_lba);
        check(cluster_begin_lba);
        check(sectors_par_cluster);


  }


/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */
        uint16 Tx_Data[7]={0x40,0x00,0x00,0x00,0x00,0x95,0xFF};

        gioInit();
        spiInit();

        //SPI_hiSpeed (0);
        sciInit();
        spiDAT1_t dataconfig1_t;
        gioSetBit(gioPORTA, 1U, 1);
        //sciSendByte(scilinREG, 'A');
        //spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
        //printf("Tx_Data_command= %d\n" , Tx_Data_command);
        //printf("Rx_Data_command= %d\n" , Rx_Data_command);
        /*
        _delay_ms(10000);
        printf("Sending Commands= %d\n" );
           //_delay_ms(1);
         for ( i=0;i<10;i++)
             {
              spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
              printf("Tx_Data_command= %d\n" , Tx_Data_command);
              printf("Rx_Data_command= %d\n" , Rx_Data_command);
              //spiSendData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command);
             }
         try: _delay_ms(5000);
         //_delay_ms(100);
         gioSetBit(gioPORTA, 1U, 0);
         for(i=0;i<6;i++)
            {
               // SPI_send(send[i]);
                //spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
                printf("i= %d" , i);
                        printf("Tx_Data_command= %d\n" , Tx_Data[i]);
                        spiTransmitData(spiREG2, &dataconfig1_t, 1, &Tx_Data[i] );
            }
        i = 1000;
           do {
               // j= SPI_send (0xFF); // check if ready
               spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
                // sciSendByte(scilinREG, (j+'0'));
                //sciSendByte(scilinREG, (Rx_Data_command+'0'));
                printf("Rx_Data_command= %d\n" , Rx_Data_command);
                //printf("j = %d\n " , j);
              if ( Rx_Data_command != 0xFF) break;
              } while ( --i > 0);
           gioSetBit(gioPORTA, 1U, 1);
           if(Rx_Data_command!=1)
           {
               goto try;
           }
           */
while(1)
{
    for ( i=0;i<10;i++)
                 {
                  spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command, &Rx_Data_command);
                  printf("Tx_Data_command= %d\n" , Tx_Data_command);
                  printf("Rx_Data_command= %d\n" , Rx_Data_command);
                  //spiSendData(spiREG2, &dataconfig1_t, 1, &Tx_Data_command);
                 }
}


/* USER CODE END */


}


/* USER CODE BEGIN (4) */

void check(unsigned long value)
{
    unsigned long data;
    data=value;
    data=data/1000000;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%1000000;
    data=data/100000;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%100000;
    data=data/10000;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%100000;
    data=data%10000;
    data=data/1000;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%100000;
    data=data%10000;
    data=data%1000;
    data=data/100;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%100000;
    data=data%10000;
    data=data%1000;
    data=data%100;
    data=data/10;
    sciSendByte(scilinREG,(data+'0'));
    data=value;
    data=data%100000;
    data=data%10000;
    data=data%1000;
    data=data%100;
    data=data%10;
    sciSendByte(scilinREG,(data+'0'));
    sciSendByte(scilinREG, 0x0D);
    sciSendByte(scilinREG, 0x0A);
}




/* USER CODE END */