/****************************************************************************** * Includes *****************************************************************************/ #include "fsstub.h" /****************************************************************************** * Public variables *****************************************************************************/ /****************************************************************************** * Typedefs and defines *****************************************************************************/ // The settings below should be modified // to match your hardware/software settings #define _CVAVR_ // #define _ICCAVR_ #define _SD_MMC_MEDIA_ #define SD_CS_OFF() IOSET = 0x00002000; #define SD_CS_ON() IOCLR = 0x00002000; #define CS_DDR_SET() IODIR |= 0x00002000; #define CLI() abcd_error #define SEI() efgh_error //#include //#include #include #include #include #ifdef _SD_MMC_MEDIA_ #include "sd_cmd.h" #endif enum { CMD0=0, CMD1, CMD9, CMD10, CMD12, CMD13, CMD16, CMD17, CMD18, CMD24, CMD25, CMD27, CMD28, CMD29, CMD30, CMD32, CMD33, CMD34, CMD35, CMD36, CMD37, CMD38, CMD42, CMD58, CMD59, ACMD41, CMD_TOT }; enum {RESP_1, RESP_1b, RESP_2, RESP_3}; enum {NO_ARG, BLOCK_LEN, DATA_ADDR, STUFF_BITS}; struct CMD { unsigned int index; unsigned int tx_data; unsigned int arg; unsigned int resp; }; struct CMD sd_cmd[CMD_TOT] = { {CMD0, 0x40, NO_ARG, RESP_1}, // GO_IDLE_STATE {CMD1, 0x41, NO_ARG, RESP_1}, // SEND_OP_COND (ACMD41 = 0x69) {CMD9, 0x49, NO_ARG, RESP_1}, // SEND_CSD {CMD10, 0x4A, NO_ARG, RESP_1}, // SEND_CID {CMD12, 0x4C, NO_ARG, RESP_1}, // STOP_TRANSMISSION {CMD13, 0x4D, NO_ARG, RESP_2}, // SEND_STATUS {CMD16, 0x50, BLOCK_LEN, RESP_1}, // SET_BLOCKLEN {CMD17, 0x51, DATA_ADDR, RESP_1}, // READ_SINGLE_BLOCK {CMD18, 0x52, DATA_ADDR, RESP_1}, // READ_MULTIPLE_BLOCK {CMD24, 0x58, DATA_ADDR, RESP_1}, // WRITE_BLOCK {CMD25, 0x59, DATA_ADDR, RESP_1}, // WRITE_MULTIPLE_BLOCK {CMD27, 0x5B, NO_ARG, RESP_1}, // PROGRAM_CSD {CMD28, 0x5C, DATA_ADDR, RESP_1b}, // SET_WRITE_PROT {CMD29, 0x5D, DATA_ADDR, RESP_1b}, // CLR_WRITE_PROT {CMD30, 0x5E, DATA_ADDR, RESP_1}, // SEND_WRITE_PROT {CMD32, 0x60, DATA_ADDR, RESP_1}, // TAG_SECTOR_START {CMD33, 0x61, DATA_ADDR, RESP_1}, // TAG_SECTOR_END {CMD34, 0x62, DATA_ADDR, RESP_1}, // UNTAG_SECTOR {CMD35, 0x63, DATA_ADDR, RESP_1}, // TAG_ERASE_GROUP_START {CMD36, 0x64, DATA_ADDR, RESP_1}, // TAG_ERASE_GROUP_END {CMD37, 0x65, DATA_ADDR, RESP_1}, // TAG_ERASE_GROUP {CMD38, 0x66, STUFF_BITS, RESP_1b}, // ERASE {CMD42, 0x6A, STUFF_BITS, RESP_1b}, // LOCK_UNLOCK {CMD58, 0x7A, NO_ARG, RESP_3}, // READ_OCR {CMD59, 0x7B, STUFF_BITS, RESP_1}, // CRC_ON_OFF {ACMD41, 0x69, NO_ARG, RESP_1} }; #include #define DIVIDER 1 #define MIN_SPI_SPEED (8*DIVIDER) /****************************************************************************** * Local variables *****************************************************************************/ /****************************************************************************** * Local functions *****************************************************************************/ static unsigned char _FF_spi(unsigned char mydata); static void clear_sd_buff(void); static unsigned char spi_speedset(void); static unsigned char reset_sd(void); static unsigned char init_sd(void); static unsigned int send_cmd(unsigned char command, unsigned long argument); /****************************************************************************** * Implementation of public functions *****************************************************************************/ /***************************************************************************** * * Description: * Initializes the SD card. * * Params: * N/A * * Returns: * TRUE if the initialization worked, FALSE if not. * ****************************************************************************/ tBool sdcmdInitMedia(void) { unsigned char data_temp; unsigned long n; // SPI BUS SETUP // SPI initialization // SPI Type: Master // SPI Clock Rate: ca 1.6MHz // SPI Clock Phase: Cycle Half // SPI Clock Polarity: Low // SPI Data Order: MSB First //init SPI SPI_SPCCR = MIN_SPI_SPEED; //set SPI clock rate SPI_SPCR = 0x30; //no irq, MSB first, CPOL=1, CPHA=0, Master PINSEL0 &= ~0x00003F00; PINSEL0 |= 0x00001500; // PINSEL0 |= 0x00005500; CS_DDR_SET(); // Set CS to Output printf("."); if (reset_sd()==0) return FALSE; printf("\nsdcmdInitMedia done!"); for (n=0; ((n<100)||(data_temp==0)) ; n++) { SD_CS_ON(); data_temp = _FF_spi(0xFF); SD_CS_OFF(); } // delay_ms(50); for (n=0; n<100; n++) { printf("\n!"); if (init_sd()) // Initialization Succeeded break; if (n==99) return FALSE; } return TRUE; } #ifdef FAT_DEBUG_C /***************************************************************************** * * Description: * Reads SECTORSIZE number of bytes from the SD card into pBuffer. * All ready bytes are printed before they are returned. * * Params: * [inOut] pBuffer - The buffer to store the read data into * [in] addr - The address to read from * * Returns: * TRUE if the data was read, FALSE if not. * ****************************************************************************/ tBool sdcmdReadDisp(unsigned char* pBuffer, unsigned long addr) { unsigned char resp; unsigned long n, remainder; if (addr % 0x200) { // Not a valid read address printf("sdcmdReadDisp(buff, %ld) READ_ERR: Not a valid read address\n", addr); return FALSE; } printf("\nDUMP OF %d BYTES FROM ADDR 0x%08lx (SECTOR %ld)\n",SECTORSIZE,addr,addr/SECTORSIZE); clear_sd_buff(); resp = send_cmd(CMD17, addr); // Send read request while (resp!=0xFE) { resp = _FF_spi(0xFF); } for (n=0; n start reading SD Card for (n=0; n> 24; _FF_spi(spi_data_out); spi_data_out = (argument & 0x00FF0000) >> 16; _FF_spi(spi_data_out); spi_data_out = (argument & 0x0000FF00) >> 8; _FF_spi(spi_data_out); spi_data_out = (argument & 0x000000FF); _FF_spi(spi_data_out); } if (command == CMD0) spi_data_out = 0x95; // CRC byte, don't care except for first signal=0x95 else spi_data_out = 0xFF; _FF_spi(spi_data_out); _FF_spi(0xff); c = sd_cmd[command].resp; switch (c) { case RESP_1: return(_FF_spi(0xFF)); break; case RESP_1b: response_1 = _FF_spi(0xFF); response_2 = 0; while (response_2 == 0) response_2 = _FF_spi(0xFF); return(response_1); break; case RESP_2: response_2 = _FF_spi(0xFF); response_2 = (response_2 << 8) | _FF_spi(0xFF); return(response_2); break; case RESP_3: response_1 = _FF_spi(0xFF); OCR_REG = 0; response_2 = _FF_spi(0xFF); OCR_REG = response_2 << 24; response_2 = _FF_spi(0xFF); OCR_REG |= (response_2 << 16); response_2 = _FF_spi(0xFF); OCR_REG |= (response_2 << 8); response_2 = _FF_spi(0xFF); OCR_REG |= (response_2); return(response_1); break; } return(0); }