/****************************************************************************** * SDCARD SPI Bus Access Driver * * Portions from CHIPCON CC1010 SPI Bus Access EXAMPLE PROGRAM * * and SANDISK SD-Card Product Manual v1.9 * * /*Author(s)/* Abhishek Mitra and Anirban Banerjee*/ * ******************************************************************************/ #include #include #include #include //SD ADDRESS GENERATOR int SD_ADD_GEN(void); //GLOBAL ADDRESS BYTE VARIABLES char AD0=0; //LSB char AD1=0; char AD2=0; char AD3=0; //MSB //SDCARD access function prototypes. int SD_SPI_Init(); int SD_RD_OCR(); int SD_Init(); void SD_Block_Len(int SD_BL_3, SD_BL_4); int SD_RD_BLK(); int SD_WR_BLK(int card_data); int SD_Transaction(int B0, B1, B2, B3, B4, B5); int SD_WR_SECTOR(unsigned int address); int SD_RD_SECTOR(unsigned int address); int SD_ERASE_128MEG(long int start_address); int SD_WR_1MEG(); int sleep_baby(); int main() { int i=0,j=0,shift=0,k=0; int dat; // Turn off watchdog timer WDT_ENABLE(FALSE); // Set optimum settings for speed and low power consumption MEM_NO_WAIT_STATES(); FLASH_SET_POWER_MODE(FLASH_STANDBY_BETWEEN_READS); // All I/Os are inputs after reset. Make I/Os connected to LEDs outputs RLED_OE(TRUE); YLED_OE(TRUE); GLED_OE(TRUE); BLED_OE(TRUE); RLED=YLED=GLED=BLED=LED_OFF; // Set up P0.3 as output to CS_N //Port 0 is clock //port 1 is data out //port 2 is data in //port 3 is CS PORTDIRBIT(0,3,POUT);//Enable CS on P0.3 /*Enable SPI*/ SPI_CONTROL(SPI_SPM_DISABLED | SPI_ENABLE | SPI_MSB_FIRST | SPI_POSEDGE_IDLE1 | SPI_CLK_DIV_8); MOSI_OE(TRUE);/*Master Out, Slave In, Output Enable */ //UART0_SETUP(57600, CC1010EB_CLKFREQ, UART_NO_PARITY | UART_RX_TX | UART_POLLED); PORTBIT(0,3) = 1; // Raise CS RLED=LED_ON; // Error Diagnostic LED remains on thruout initialization. init: if (dat = SD_SPI_Init()==0x01) ; else goto init; while (dat==0x01) { //BLED = LED_ON; PORTBIT(0,3) = 1;//RaiseSS(); SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); PORTBIT(0,3) = 0;//LowerSS(); dat=SD_Init(); shift++; } RLED=LED_OFF;//SD Card Initialized Properly, turn off RED LED PORTBIT(0,3) = 1;//RaiseCS = Disable SD-CARD SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); /*END Initialization*/ //SD_WR_SECTOR(0x200); //SD_RD_SECTOR(0x200); //SD_RD_BLK(); //RLED=LED_ON; //SD_ERASE_SECTOR(); //RLED=LED_OFF; /* AD0=0x00; AD1=0x06; AD2=0x00; AD3=0x00; // SD_WR_BLK(0x43); SD_RD_BLK(); */ SD_ERASE_128MEG(0); // SD_WR_1MEG(); BLED=LED_ON; SPI_CONTROL(SPI_DISABLE); while(1); // sleep_baby(); } //SD ADDRESS GENERATOR FUNCTION BODY int SD_ADD_GEN() { AD1 =AD1; AD2 =AD2; } int SD_SPI_Init(){ #define SD_SPI_MODE0 0x00 //CMD0 #define SD_SPI_MODE1 0x00 #define SD_SPI_MODE2 0x00 #define SD_SPI_MODE3 0x00 #define SD_SPI_MODE4 0x00 #define SD_SPI_MODE5 0x95 { int i; int dat; PORTBIT(0,3) = 0; // Raise CS=Enable SD for(i=0; i < 10; i++) { SPI_DATA = 0xFF;// send 10*8=80 clock pulses while (SPI_IS_ACTIVE); } //*-+-+-+-+Change mode of SD card to SPI-+-+-+-+*/ dat = SD_Transaction (SD_SPI_MODE0, SD_SPI_MODE1, \ SD_SPI_MODE2, SD_SPI_MODE3, SD_SPI_MODE4, SD_SPI_MODE5); return dat; /* Send in SD_INIT Command*/ } }//End SD_SPI_Init int SD_Init() { #define SD_INIT_0 0x01 //CMD 1 #define SD_INIT_1 0x00 #define SD_INIT_2 0x00 #define SD_INIT_3 0x00 #define SD_INIT_4 0x00 #define SD_INIT_5 0xFF int dat; dat = SD_Transaction (SD_INIT_0, SD_INIT_1, SD_INIT_2,\ SD_INIT_3, SD_INIT_4, SD_INIT_5); return dat; }// End SDInit void SD_Block_Len(char SD_BL_3, SD_BL_4) {//Defunct donot use #define SD_BL_0 0x10 //01010000 CMD 16 #define SD_BL_1 0x00 #define SD_BL_2 0x00 // #define SD_BL_3 0x02 //512 bytes // #define SD_BL_4 0x00 #define SD_BL_5 0xFF char ret; PORTBIT(0,3) = 0; ret = SD_Transaction(SD_BL_0, SD_BL_1, SD_BL_2,\ SD_BL_3, SD_BL_4, SD_BL_5); PORTBIT(0,3) = 1; } int SD_RD_BLK() //Read 512 bytes from the designated address { #define SD_RD_0 0x11 //CMD17 #define SD_RD_1 AD3 #define SD_RD_2 AD2 #define SD_RD_3 AD1 #define SD_RD_4 AD0 #define SD_RD_5 0xFF int ret; unsigned int count; int dat; PORTBIT(0,3) = 0; //Lower CS=Enable SD ret = SD_Transaction(SD_RD_0, SD_RD_1, SD_RD_2,\ SD_RD_3, SD_RD_4, SD_RD_5); while(1) { SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); if (SPI_DATA != 0xFE) break; } for(count=0; count < 522; count++) //522 is good { SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); dat = SPI_DATA; //if (count > 10)UART0_WAIT_AND_SEND(dat); //Diagnostics: Send byte to UART } SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); PORTBIT(0,3) = 1; //Raise CS = Disable SD return dat; } int SD_RD_BLK2() { //Multi Block Read: Experimental #define SD_RDM_0 0x12 //CMD18 #define SD_RDM_1 AD3 #define SD_RDM_2 AD2 #define SD_RDM_3 AD1 #define SD_RDM_4 AD0 #define SD_RDM_5 0xFF int ret; unsigned int count, count1; int dat; PORTBIT(0,3) = 0; //Lower CS ret = SD_Transaction(SD_RDM_0, SD_RDM_1, SD_RDM_2,\ SD_RDM_3, SD_RDM_4, SD_RDM_5); while(1) { SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); if (SPI_DATA != 0xFE) break; } // for(count1=0; count1 < 158; count1++) { for(count=0; count < 65000; count++) { SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); dat = SPI_DATA; //UART0_WAIT_AND_SEND(dat); // UART0_SEND(0xFF); } // } RLED = LED_ON; #define SD_STOP0 0xC //CMD12 #define SD_STOP1 0x00 #define SD_STOP2 0x00 #define SD_STOP3 0x00 #define SD_STOP4 0x00 #define SD_STOP5 0xFF ret = SD_Transaction(SD_STOP0, SD_STOP1, SD_STOP2,\ SD_STOP3, SD_STOP4, SD_STOP5); /* SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; while (SPI_IS_ACTIVE);*/ do{ SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); }while (SPI_DATA==0); PORTBIT(0,3) = 1; //Raise SS return dat; } int SD_WR_BLK(int card_data) { #define SD_WR_0 0x18 //CMD24 #define SD_WR_1 AD3 #define SD_WR_2 AD2 #define SD_WR_3 AD1 #define SD_WR_4 AD0 #define SD_WR_5 0xFF char ret; char busy; int count; PORTBIT(0,3) = 0; //Lower CS = Enable SD ret = SD_Transaction(SD_WR_0, SD_WR_1, SD_WR_2,\ SD_WR_3, SD_WR_4, SD_WR_5); if (ret==0x00) { SPI_DATA = 0xFE; while (SPI_IS_ACTIVE); for(count=0;count<514;count++){//514 is good SPI_DATA = card_data; while (SPI_IS_ACTIVE); // UART0_WAIT_AND_SEND(count); // Diagnostic:UART o/p } SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); busy=SPI_DATA; while(busy==0){ SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); busy=SPI_DATA; } ret=ret&0x0f; PORTBIT(0,3) = 1; //Raise CS = Disable CS //SPI_DATA = 0xFF; // while (SPI_IS_ACTIVE); return ret; }//EndIF } int SD_Transaction(int B0, B1, B2, B3, B4, B5) { //Master Function for a SD-Card transaction //Calling Function is responsible for enabling the SD Card //I Will not Enable SD Card //PORTBIT(0,3) = 0; //Lower CS, Enable SDCard SPI_DATA = 0xFF; //Start SPI transaction while (SPI_IS_ACTIVE); SPI_DATA = B0|0x40; while (SPI_IS_ACTIVE); SPI_DATA = B1; while (SPI_IS_ACTIVE); SPI_DATA = B2; while (SPI_IS_ACTIVE); SPI_DATA = B3; while (SPI_IS_ACTIVE); SPI_DATA = B4; while (SPI_IS_ACTIVE); SPI_DATA = B5; while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); /*Command sent*/ /* Read a byte */ SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); return SPI_DATA; //Calling Function is responsible for disabling the SD Card // I Will not Disable SD Card // PORTBIT(0,3) = 1; //Raise CS, Disable SDCard } int SD_RD_OCR() {//Defunct /*#define SD_INIT_0 0x3A //CMD 58 #define SD_INIT_1 0x00 #define SD_INIT_2 0x00 #define SD_INIT_3 0x00 #define SD_INIT_4 0x00 #define SD_INIT_5 0xFF int dat; dat = SD_Transaction (SD_INIT_0, SD_INIT_1, SD_INIT_2,\ SD_INIT_3, SD_INIT_4, SD_INIT_5); SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); return dat; // if (k==0x01)BLED=LED_ON; */ } int SD_WR_SECTOR(unsigned int address) { int count; unsigned int add0; add0=address; for (count=0;count<32; count++){ AD0=add0; AD1=add0 >> 8; AD2=0x00; AD3=0x00; SD_WR_BLK(count+0x41); add0 = add0 +0x200; } } int SD_RD_SECTOR(unsigned int address) { int count; unsigned int add0; add0=address; for (count=0;count<32; count++){ AD0=add0; AD1=add0 >> 8; AD2=0x00; AD3=0x00; SD_RD_BLK(); add0 = add0 +0x200; } } /* /*int SD_ERASE_SECTOR(/*int start_address, unsigned int end_address)*/ /*{ int ret=0; PORTBIT(0,3) = 0; //Lower CS #define SD_ERS_0 0x20 //CMD32 = Start Address #define SD_ERS_1 0x00 #define SD_ERS_2 0x00 #define SD_ERS_3 0x00 #define SD_ERS_4 0x00 #define SD_ERS_5 0xFF ret = SD_Transaction(SD_ERS_0, SD_ERS_1, SD_ERS_2,\ SD_ERS_3, SD_ERS_4, SD_ERS_5); #define SD_ERT_0 0x21 //CMD33 = End Address #define SD_ERT_1 0x00 #define SD_ERT_2 0x00 #define SD_ERT_3 0x40 #define SD_ERT_4 0x00 #define SD_ERT_5 0xFF ret = SD_Transaction(SD_ERT_0, SD_ERT_1, SD_ERT_2,\ SD_ERT_3, SD_ERT_4, SD_ERT_5); #define SD_ER_0 0x26 //CMD38 = ERASE #define SD_ER_1 0x00 #define SD_ER_2 0x00 #define SD_ER_3 0x00 #define SD_ER_4 0x00 #define SD_ER_5 0xFF ret = SD_Transaction(SD_ER_0, SD_ER_1, SD_ER_2,\ SD_ER_3, SD_ER_4, SD_ER_5); do{ SPI_DATA = 0xFF; //Wait 8 cycles while (SPI_IS_ACTIVE); }while (SPI_DATA==0); PORTBIT(0,3) = 1; //Lower CS } */ int SD_ERASE_128MEG(long int start_address) { int ret=0; unsigned long int end_address = start_address + 51200000; char ST0, ST1, ST2, ST3; // start address segments char END0, END1, END2, END3; // end address segments AD0 = start_address; AD1 = start_address>>8; AD2 = start_address>>16; AD3 = start_address>>24; #define SD_ERS_0 0x20 //CMD32 = Start Address #define SD_ERS_1 AD3 // chunk 1 #define SD_ERS_2 AD2 // chunk 2 #define SD_ERS_3 AD1 // chunk 3 #define SD_ERS_4 AD0 // chunk 4 #define SD_ERS_5 0xFF PORTBIT(0,3) = 0; //Lower CS = Enable SD SD_Transaction(SD_ERS_0, SD_ERS_1, SD_ERS_2,\ SD_ERS_3, SD_ERS_4, SD_ERS_5); AD0 = end_address; AD1 = end_address>>8; AD2 = end_address>>16; AD3 = end_address>>24; #define SD_ERT_0 0x21 //CMD33 = End Address #define SD_ERT_1 AD3 // chunk 1 #define SD_ERT_2 AD2 // chunk 2 #define SD_ERT_3 AD1 // chunk 3 #define SD_ERT_4 AD0 // chunk 4 #define SD_ERT_5 0xFF SD_Transaction(SD_ERT_0, SD_ERT_1, SD_ERT_2,\ SD_ERT_3, SD_ERT_4, SD_ERT_5); #define SD_ER_0 0x26 //CMD38 = ERASE #define SD_ER_1 0x00 #define SD_ER_2 0x00 #define SD_ER_3 0x00 #define SD_ER_4 0x00 #define SD_ER_5 0xFF SD_Transaction(SD_ER_0, SD_ER_1, SD_ER_2,\ SD_ER_3, SD_ER_4, SD_ER_5); do{ SPI_DATA = 0xFF; while (SPI_IS_ACTIVE); }while (SPI_DATA==0); PORTBIT(0,3) = 1; //Raise CS = Disable SD } int SD_WR_1MEG() { long int address=0; //Address = 512*n unsigned char WAD0, WAD1, WAD2, WAD3; int count; int eo=0; int temp, temp1; // YLED = LED_ON; for (count=0; count < 2048; count++){ WAD0 = address;//0..7 WAD1 = address >> 8;//8..15 WAD2 = address >> 16;//16..23 WAD3 = address >> 24;//24..31 AD0=WAD0; AD1=WAD1; AD2=WAD2; AD3=WAD3; //UART0_WAIT_AND_SEND(count + 0x30);//iteration //UART0_WAIT_AND_SEND(0x2C);//comma /*if ((WAD1 >>8) < 10) UART0_WAIT_AND_SEND(WAD1+0x30); else if (WAD1 >9 && WAD1 < 100) { temp = WAD1/10; UART0_WAIT_AND_SEND(temp+0x30); UART0_WAIT_AND_SEND(WAD1-(temp*10)+0x30); } else if (WAD1 >99 && WAD1 < 256) {temp=WAD1/100; UART0_WAIT_AND_SEND(temp+0x30); temp = WAD1-(temp*100); UART0_WAIT_AND_SEND(temp/10+0x30); temp1 = temp - (temp/10)*10; UART0_WAIT_AND_SEND(temp1+0x30); } UART0_WAIT_AND_SEND(0x2C);//comma UART0_WAIT_AND_SEND(0x2E);//space */ if (eo==1) { // SD_WR_BLK(0x4F); eo=0;} else if (eo==0){ // SD_WR_BLK(0x45); eo=1;} // SD_WR_BLK(0x48); SD_RD_BLK(); address+=512; } PORTBIT(0,3) = 0; //Raise CS = Disable SD SD_Transaction (SD_SPI_MODE0, SD_SPI_MODE1, \ SD_SPI_MODE2, SD_SPI_MODE3, SD_SPI_MODE4, SD_SPI_MODE5); PORTBIT(0,3) = 1; //Raise CS = Disable SD YLED = LED_OFF; GLED = LED_ON; } int sleep_baby() { // 32 kHz crystal clock frequency in kHz #define X32_CLKFREQ 32 int i; // Infinite loop //while(1) { // Switch LEDS off YLED=GLED=LED_OFF; // Enable 32kHz oscillator, wait 0.5s to stabilize, // then switch clock source, then disable high-speed XOSC X32_INPUT_SOURCE(X32_USING_CRYSTAL); X32_ENABLE(TRUE); halWait(250, CC1010EB_CLKFREQ); halWait(250, CC1010EB_CLKFREQ); MAIN_CLOCK_SET_SOURCE(CLOCK_X32); XOSC_ENABLE(FALSE); // Switch the red LED 10 times to verify new clock frequency for (i=0; i<10; i++) { RLED = LED_ON; halWait(250, X32_CLKFREQ); halWait(250, X32_CLKFREQ); RLED = LED_OFF; halWait(250, X32_CLKFREQ); halWait(250, X32_CLKFREQ); } // Enable high speed XOSC, switch clock source, then disable 32kHz XOSC /* XOSC_ENABLE(TRUE); MAIN_CLOCK_SET_SOURCE(CLOCK_XOSC); X32_ENABLE(FALSE); // Switch the green LED 10 times to verify new clock frequency for (i=0; i<10; i++) { GLED = LED_ON; halWait(250, CC1010EB_CLKFREQ); halWait(250, CC1010EB_CLKFREQ); GLED = LED_OFF; halWait(250, CC1010EB_CLKFREQ); halWait(250, CC1010EB_CLKFREQ); }*/ } }