Part Number: MSP430FR2633
I am trying to initialize an sd card so that I can write some data to it that can be read at a later date. I don't need any special file system as I am only writing unsigned chars to the card. I am attaching the relevant code below:
Header File Definitions:
#define CS (P3DIR |= BIT1)// Set CS to Output
#define CS_H (P3OUT |= BIT1 ) //Sets CS to Inactive (Active Low)
#define CS_L (P3OUT |= ~BIT1) //Sets CS to Active (Active Low)
#define TX UCA1TXBUF //Tx Buffer
#define RX UCA1RXBUF //Rx Buffer
#define TX_READY (UCA1IFG & 0x0002) //0 when Busy, 1 When Ready
#define RX_READY (UCA1IFG & 0x0001) //0 When Empty, 1 when Full
#define SPI_SEND(x) UCA1TXBUF = x
// macro defines
#define HIGH(a) ((a>>8)&0xFF) //High byte from Word
#define LOW(a) (a&0xFF) //Low Byte from word
#define DUMMY 0xFF
//Commands 48 bits: [47]: Start (0) ; [46]: Tx bit (1) ; [45:40] CMD index; [39:8] Argument; [7:1] CRC7; [0]: end (1)
#define GO_IDLE_STATE 0x40 //Resets SD Memory Card (CMD0)
#define SEND_OP_COND 0x41 //Sends Host Capacity Support Information and activates the card's Init Process (CMD1)
#define SWITCH_FUN 0x46 //Checks Switchable function (mode 0) and switches card function (mode 1) (CMD6)
#define SEND_IF_COND 0x48 //Sends SD Mem card interface condition that includes host supply voltage information and asks accessed card if it operate in that range (CMD8)
#define SEND_CSD 0x49 //Asks the selected card to send its card specific data (CSD) (CMD9)
#define SEND_CID 0x4A // Ask the selected card to send its card ID (CID) (CMD10)
#define STOP_TRANS 0x4C //Forces the card to stop transmission in multiple block read operation (CMD12)
#define SEND_STATUS 0x4D //Ask the selected card to send its status register (CMD13)
#define SET_BLOCKLEN 0x50 //Sets Length of LOCK_UNLOCK Command (Block Size Otherwise locked at 512 bytes) (CMD16)
#define READ_SINGLE_BLOCK 0x51 //Read a block of size 512 bytes (CMD17)
#define READ_MULT_BLOCKS 0x52 //Read Multiple Blocks Unil STOP_TRANS command issured (CMD18)
#define WRITE_BLOCK 0x58 //Write a block of size 512 bytes (CMD24)
#define WRITE_MULT_BLOCKS 0x59 //Write Multiple Blocks of DATA until STOP_TRANS command Issured (CMD25)
#define PROGRAM_CSD 0x5B //PRogram the programmable bits of the CSD (CMD27)
#define ERASE_W_SA 0x60 //Sets the Address of the first write block to be erased (CMD32)
#define ERASE_W_EA 0x61 //Sets the address of the last write block to be erased (CMD33)
#define ERASE 0x66 //Erase all previously selected write blocks (CMD38)
#define LOCK_UNLOCK 0x6A //Used to Set/Reset the password or lock/unlock the card. A transferred data block includes all the command details.
// The Size of Data block Locked/Unlocked is set by SET_BLOCKLEN (CMD42)
#define APP_CMD 0x77 //Defines to the card that the next command is an ACMD (CMD55)
#define GEN_CMD 0x78 //Used either to ransfer a Data Blcok to the card or to get a Data Blcok from the card for general purpose/application specfic commands (CMD56)
#define READ_OCR 0x7A //Reads the OCR register of a card, CCS bit is assigned to OCR[30]. (CMD58)
#define CRC_ON_OFF 0x7B //Turns the CRC option on or off. A '1' in the CRC option bit will turn the option on, a '0' will turn it off (CMD59)
//Application Specific Commands (ACMD), always proceeded by CMD55, same setup as CMD
#define APP_SD_STATUS 0x4D //Send the SD Status (ACMD13)
#define APP_NUM_W_BLKS 0x56 //Send the numbers of the well written (no errors) blocks. Respons with 32 bit + CRC data block (ACMD22)
#define APP_SET_W_BLK_ER_N 0x57 //Set the number of write blocks to be pre-erased before writing (to be used for faster Multiple block WR command) (ACMD23)
#define APP_START_INIT 0x69 //Sends host capacity support information and activates the card's initialization process. Reserved bits shall be set to '0' (ACMD41)
#define APP_SET_CLR_CARD_D 0x6A //Connect[1]/Disconnect[0] the 50 kOhm pull-up resistor on CS (pin 1) of the card. The pull-up may be used for card detection (ACMD42)
#define APP_SEND_SCR 0x73 //Reads the SD configuration register (SCR)
Relevant Functions
void SD_Send_Cmd(const char cmd, unsigned long data, const char crc)
{
unsigned char frame[6];
char temp;
int i;
frame[0] = (cmd|0x40);
for(i = 3; i >= 0; i--)
{
temp = (char)(data>>(8*i));
frame[4-i] = (temp);
}
frame[5] = crc;
SD_Send_SPI_Frame(frame,6);
}
unsigned char getResponse()
{
int i = 0;
unsigned char response;
while(i <= 25000)
{
response = SD_Send_SPI_Char(DUMMY);
if(response == 0x00) break;
if(response == 0x01) break;
i++;
}
return response;
}
void SD_Card_Init()
{
CSCTL5 |= 0x0003 | 0x0030; //MCLK and SMCLK Reduced For SD Card Functions
CS_H; //Set CS to Off During Power Up (At Least 74 Clock Cycles)
unsigned int i;
for(i = 0; i <= 9; i++)
{
SD_Send_SPI_Char(DUMMY); //8 bits * 10 = 80 Clock Cycles
}
goIdle();
CSCTL5 &= ~((0x0003) | (0x0030)); //Return Clock Back To Desired Speed
}
unsigned char goIdle()
{
unsigned char response = 0x01;
CS_L;
SD_Send_Cmd(GO_IDLE_STATE,0,0x95);
if(getResponse() != 0x01)
{
return(2);
}
while (response == 0x01)
{
CS_H;
SD_Send_SPI_Char(DUMMY);
CS_L;
SD_Send_Cmd(SEND_OP_COND,0x00,0xff);
response = getResponse();
}
CS_H;
SD_Send_SPI_Char(DUMMY);
return (1);
}
unsigned char SD_Send_SPI_Char(unsigned char x)
{
while (TX_READY == 0); // Waiting for TXBuffer to Become Free
SPI_SEND(x);
while (RX_READY == 0); //Waiting to Recieve Data
return (RX);
}
unsigned long SD_Send_SPI_Frame(unsigned char* pBuffer, unsigned int sz)
{
unsigned int i;
for(i = 0; i < sz; i++)
{
while(TX_READY == 0);
SPI_SEND(pBuffer[i]);
while(RX_READY == 0);
pBuffer[i] = RX;
}
return(0);
}
Main Function
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
// Configure one FRAM waitstate as required by the device datasheet for MCLK
// operation beyond 8MHz _before_ configuring the clock system.
FRCTL0 = FRCTLPW | NWAITS_1;
__bis_SR_register(SCG0); // disable FLL
CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source
CSCTL0 = 0; // clear DCO and MOD registers
CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits first
CSCTL1 |= DCORSEL_5; // Set DCO = 16MHz
CSCTL2 = FLLD_0 + 487; // DCOCLKDIV = 16MHz
__delay_cycles(3);
__bic_SR_register(SCG0); // enable FLL
while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // FLL locked
CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
// default DCOCLKDIV as MCLK and SMCLK source
CSCTL5 |= 0x0003 | 0x0030; //MCLK and SMCLK Reduced For SD Card Functions
P1DIR |= BIT7; // set MCLK as output
SDI;
SCLK;
LAT;//initial
//Begin SPI Setup
P2SEL0 |= BIT4 | BIT5 | BIT6; //Setting Up CLK,SOMI,MOSI (UCA1)
P3SEL0 |= BIT1; //Setting Up GPIO to Act as CS
UCA0CTLW0 |= UCSWRST;
UCA1CTLW0 |= UCMST|UCSYNC|UCCKPL|UCMSB|UCSTEM;
UCA1CTLW0 |= UCSSEL__SMCLK;
UCA1BR0 = 0x01;
UCA1BR1 = 0;
UCA1MCTLW = 0;
UCA1CTLW0 &= ~UCSWRST;
UCA1IE |= UCRXIE | UCTXIE;
PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
// to activate previously configured port settings
FC1_write(7,511,511,511);
P1SEL1 |= BIT7; // set MCLK pin as second function->GCLK=16MHz
unsigned int ij;
for(ij = 0; ij < 16; ij++)
{
data[ij] = 0x111111111111; //Brightness Set
}
while (1) // Test//14.88m
{
SD_Card_Init();
/*Rest of Code Cut due to lack of relevancy (Following code has been tested and works fine) */
I originally put the code in without adjusting the clock for the initialization period, and I kept getting 0xFF for the response. I added code that would bring SMCLK down to ~250KHz during SD Initialization. However, I keep getting 0xFF in the response Line. I have looked over the MMC/SD Card example code for the MSP430F169 and thought I implemented the necessary changes for the MSP430FR2633 but I keep running into problems.
Any help to why I am getting 0xFF only when I try to Start Up the SD Card would be super helpful!
Thanks in Advanced for any help!