MSP430 SD card SPI read and write operations with MSP430F5438A
[Copy link]
This section provides sample code for reading and writing SD cards using the MSP430F5438A SPI. It uses the official library msp430_driverlib_2_60_00_02 and is compiled using IAR for msp430 6.3.
The code in this section does not distinguish between SD cards, so it only operates on SDHC cards. The program has been verified to run normally on Kingston 8GB SDHC microSD cards.
sdhc.h
#ifndef _SDHC_H_
#define _SDHC_H_
#define SDHC_INIT_CLK 125000
#define SDHC_HIGH_CLK 3125000
#define SDHC_CS_PORT GPIO_PORT_P9
#define SDHC_CS_PIN GPIO_PIN0
#define CMD0 0 /* GO_IDLE_STATE */
#define CMD55 55 /* APP_ CMD */
#define ACMD41 41 /* SEND_OP_COND (ACMD) */
#define CMD1 1 /* SEND_OP_COND */
#define CMD17 17 /* READ_SINGLE_BLOCK */
#define CMD8 8 /* SEND_IF_COND */
#define CMD18 18 /* READ_MULTIPLE_BLOCK */
#define CMD12 12 /* STOP_TRANSMISSION */
#define CMD24 24 /* WRITE_BLOCK */
#define CMD25 25 /* WRITE_MULTIPLE_BLOCK * /
#define CMD13 13 /* SEND_STATUS */
#define CMD9 9 /* SEND_CSD */
#define CMD10 10 / * SEND_CID */
void SDHC_csInit(void);
void SDHC_csEnable(void); void SDHC_csDisable
(void);
void SDHC_spiInit(void);
void SDHC_spiEnable(void);
void SDHC_spiDisable(void);
uint8_t SDHC_writeByte(uint8_t data);
uint8_t SDHC_sendCmd( const uint8_t cmd,uint32_t arg,const uint8_t crc);
bool SDHC_reset(void);
bool SDHC_init(void);
bool SDHC_checkBusy(void);
bool SDHC_readBlock(uint32_t addr,uint8_t *buffer);
bool SDHC_writeBlock(uint32_t addr,uint8_t *buffer);
bool SDHC_readMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer);
bool SDHC_writeMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer);
#endif
sdhc.c
#include "driverlib.h"
#include "sdhc.h"
void SDHC_csInit(void)
{
GPIO_setAsOutputPin(SDHC_CS_PORT,SDHC_CS_PIN);
}
void SDHC_csEnable(void)
{
GPIO_setOutputLowOnPin(SDHC_CS_PORT,SDHC_CS_PIN);
}
void SDHC_csDisable(void)
{
GPIO_setOutputHighOnPin(SDHC_CS_PORT,SDHC_CS_PIN);
SDHC_writeByte(0xFF);
}
void SDHC_spiInit(void)
{
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P9,
GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3
);
//Initialize Master
USCI_B_SPI_initMasterParam param = {0};
param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;
param.clockSourceFrequency = UCS_getSMCLK();
param.desiredSpiClock = SDHC_INIT_CLK;
param.msbFirst = USCI_B_SPI_MSB_FIRST;
param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAP TURED_ON_NEXT;
param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
USCI_B_SPI_initMaster(USCI_B2_BASE, m);
}
void SDHC_spiEnable(void)
{
USCI_B_SPI_enable(USCI_B2_BASE);
}
void SDHC_spiDisable(void)
{
USCI_B_SPI_disable(USCI_B2_BASE);
}
uint8_t SDHC_writeByte(uint8_t data)
{
USCI_B_SPI_transmitData(USCI_B2_BASE,data);
while(USCI_B_SPI_isBusy(USCI_B2_BASE));
data = USCI_B_SPI_receiveData(USCI_B2_BASE);
return data;
}
u int8_t SDHC_getResponse(void)
{
uint8_t retrytime = 0;
uint8_t response;
while(retrytime <= 240)
{
response = SDHC_writeByte(0xFF);
if(response == 0x00) break;
if(response == 0x01) break;
if(response == 0xFE) break;
retrytime++;
}
return response ;
}
uint8_t SDHC_sendCmd(const uint8_t cmd,uint32_t arg,const uint8_t crc)
{
uint8_t rec;
SDHC_writeByte((cmd & 0x3F) | 0x40);
SDHC_writeByte(arg >> 24);
SDHC_writeByte(arg >> 16);
SDHC_writeByte(arg >> 8);
SDHC_writeByte (arg);
SDHC_writeByte(crc);
rec = SDHC_getResponse();
return rec;
}
bool SDHC_reset(void)
{
uint8_t i,rec;
SDHC_csDisable(); //PULL HIGH CS
for(i = 0;i < 16;i++ )
{
SDHC_writeByte(0xFF);
} //send 128 clocks for normal voltage and sync
SDHC_csEnable(); //PULL LOW CS
rec = SDHC_sendCmd(CMD0,0,0x95);
SDHC_csDisable();
if(rec != 0x01)
{
return false;
}
return true;
}
bool SDHC_init(void)
{
uint8_t rec;
uint16_t retrytime = 0;
SDHC_csEnable();
rec = SDHC_sendCmd(CMD8,0x1AA,0x87);
if(rec != 0x01)
{
//SD card not support ver2.0 or later
SDHC_csDisable ();
return false;
}
rec = SDHC_writeByte(0xFF);
rec = SDHC_writeByte(0xFF);
rec = SDHC_writeByte(0xFF);
rec = SDHC_writeByte(0xFF);
if(rec != 0xAA)
{
SDHC_csDisable();
return false;
}
do
{
do
{
rec = SDHC_sendCmd(CMD55,0,0xff);
retrytime++;
}while(rec != 0x01 && retrytime < 200) ;
if(retrytime >= 200)
{
SDHC_csDisable();
return false;
}
rec = SDHC_sendCmd(ACMD41,0x40000000,0xFF);
retrytime++;
}while(rec != 0x00 && retrytime < 200);
if(retrytime >= 200)
{
SDHC_csDisable();
return false;
}
SDHC_csDisable();
//SPI HIGH SPEED
USCI_B_SPI_changeMasterClockParam clockparam = {0};
clockparam.clockSourceFrequency = UCS_getSMCLK();
clockparam.desiredSpiClock = SDHC_HIGH_CLK;
USCI_B_SPI_changeMasterClock(USCI_B2_BASE, &clockparam);
return true;
}
bool SDHC_checkBusy(void)
{
uint16_t i = 0,response;
bool rvalue = false;
while (i <= 240)
{
response = SDHC_writeByte(0xFF);
response = response & 0x1F;
if(response == 0x05) {rvalue = true; break;}
i++;
}
i = 0;
do
{
response = SDHC_writeByte(0xFF) ;
i++;
if(i >= 65000)
{
rvalue = false;
break;
}
}while(response == 0x00);
return rvalue;
}
bool SDHC_readBlock(uint32_t addr,uint8_t *buffer)
{
uint8_t rec;
uint16_t i;
SDHC_csEnable();
rec = SDHC_sendCmd(CMD17,addr,0x55);
if(rec != 0x00)
{
SDHC_csDisable();
return false;
}
rec = SDHC_getResponse();
if(rec != 0xFE)
{
SDHC_csDisable();
return false;
}
for(i = 0; i < 512;i++)
{
*buffer ++ = SDHC_writeByte(0xFF);
}
SDHC_writeByte(0xFF);
SDHC_writeByte(0xFF);
SDHC_csDisable();
return true;
}
bool SDHC_writeBlock(uint32_t addr,uint8_t *buffer)
{
uint8_t rec;
uint16_t i;
bool rvalue = true;
SDHC_csEnable();
rec = SDHC_sendCmd(CMD24,addr,0xFF);
if(rec != 0x00)
{
SDHC_csDisable();
return false;
}
SDHC_writeByte(0xFE);
for(i = 0; i < 512;i++)
{
SDHC_writeByte(*buffer ++);
}
SDHC_writeByte(0xFF);
SDHC_writeByte(0xFF);
rvalue = SDHC_checkBusy() ;
SDHC_csDisable();
return rvalue;
}
bool SDHC_readMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer)
{
uint8_t rec;
uint16_t i;
SDHC_csEnable();
rec = SDHC_sendCmd(CMD18,addr,0xFF);
if(rec != 0x00 )
{
SDHC_csDisable();
return false;
}
do
{
rec = SDHC_getResponse();
if(rec != 0xFE)
{
SDHC_csDisable();
return false;
}
for(i = 0; i < 512;i++)
{
*buffer ++ = SDHC_writeByte(0xFF);
}
SDHC_writeByte(0xFF);
SDHC_writeByte(0xFF);
}while(-- block_num);
rec = SDHC_sendCmd(CMD12,0,0xFF);
SDHC_csDisable();
return true;
}
bool SDHC_writeMultiBlock(uint32_t addr,uint8_t block_num,uint8_t *buffer)
{
uint8_t rec;
uint16_t i;
bool rvalue = true;
SDHC_csEnable() ;
rec = SDHC_sendCmd(CMD25,addr,0xFF);
if(rec != 0x00)
{
SDHC_csDisable();
return false;
}
do
{
SDHC_writeByte(0xFC);
for(i = 0; i < 512;i++)
{
SDHC_writeByte(*buffer ++);
}
SDHC_writeByte(0xFF);
SDHC_writeByte(0xFF);
rvalue = SDHC_checkBusy();
if(!rvalue) break;
}while(-- block_num);
rec = SDHC_sendCmd(0xFD,0,0xFF);
i = 0;
do
{
rec = SDHC_writeByte(0xFF);
i++;
if(i >= 65000)
{
rvalue = false;
break;
}
}while(rec == 0x00);
SDHC_csDisable();
return rvalue;
}
|