diff --git a/src/drv/sdcard/include/sdcard.h b/src/drv/sdcard/include/sdcard.h index 39d086dbb..362cbab93 100644 --- a/src/drv/sdcard/include/sdcard.h +++ b/src/drv/sdcard/include/sdcard.h @@ -1,19 +1,88 @@ - - #ifndef _SDCARD_H #define _SDCARD_H -#include "stdint.h" - #ifdef __cplusplus extern "C" { #endif -int sdcard_init(void); +/** + * @brief Card Specific Data: CSD Register + */ +typedef struct { + uint8_t CSDStruct; /*!< CSD structure */ + uint8_t SysSpecVersion; /*!< System specification version */ + uint8_t Reserved1; /*!< Reserved */ + uint8_t TAAC; /*!< Data read access-time 1 */ + uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */ + uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */ + uint16_t CardComdClasses; /*!< Card command classes */ + uint8_t RdBlockLen; /*!< Max. read data block length */ + uint8_t PartBlockRead; /*!< Partial blocks for read allowed */ + uint8_t WrBlockMisalign; /*!< Write block misalignment */ + uint8_t RdBlockMisalign; /*!< Read block misalignment */ + uint8_t DSRImpl; /*!< DSR implemented */ + uint8_t Reserved2; /*!< Reserved */ + uint32_t DeviceSize; /*!< Device Size */ + uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */ + uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */ + uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */ + uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */ + uint8_t DeviceSizeMul; /*!< Device size multiplier */ + uint8_t EraseGrSize; /*!< Erase group size */ + uint8_t EraseGrMul; /*!< Erase group size multiplier */ + uint8_t WrProtectGrSize; /*!< Write protect group size */ + uint8_t WrProtectGrEnable; /*!< Write protect group enable */ + uint8_t ManDeflECC; /*!< Manufacturer default ECC */ + uint8_t WrSpeedFact; /*!< Write speed factor */ + uint8_t MaxWrBlockLen; /*!< Max. write data block length */ + uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */ + uint8_t Reserved3; /*!< Reserded */ + uint8_t ContentProtectAppli; /*!< Content protection application */ + uint8_t FileFormatGrouop; /*!< File format group */ + uint8_t CopyFlag; /*!< Copy flag (OTP) */ + uint8_t PermWrProtect; /*!< Permanent write protection */ + uint8_t TempWrProtect; /*!< Temporary write protection */ + uint8_t FileFormat; /*!< File Format */ + uint8_t ECC; /*!< ECC code */ + uint8_t CSD_CRC; /*!< CSD CRC */ + uint8_t Reserved4; /*!< always 1*/ +} SD_CSD; + +/** + * @brief Card Identification Data: CID Register + */ +typedef struct { + uint8_t ManufacturerID; /*!< ManufacturerID */ + uint16_t OEM_AppliID; /*!< OEM/Application ID */ + uint32_t ProdName1; /*!< Product Name part1 */ + uint8_t ProdName2; /*!< Product Name part2*/ + uint8_t ProdRev; /*!< Product Revision */ + uint32_t ProdSN; /*!< Product Serial Number */ + uint8_t Reserved1; /*!< Reserved1 */ + uint16_t ManufactDate; /*!< Manufacturing Date */ + uint8_t CID_CRC; /*!< CID CRC */ + uint8_t Reserved2; /*!< always 1 */ +} SD_CID; + +/** + * @brief SD Card information + */ +typedef struct { + SD_CSD SD_csd; + SD_CID SD_cid; + uint64_t CardCapacity; /*!< Card Capacity */ + uint32_t CardBlockSize; /*!< Card Block Size */ +} SD_CardInfo; -void sdcard_read_sector(uint8_t *buf, int sectorno); +extern SD_CardInfo cardinfo; -void sdcard_write_sector(uint8_t *buf, int sectorno); +uint8_t sd_init(void); +void sdcard_init(void); +uint8_t sd_read_sector(uint8_t *data_buff, uint32_t sector, uint32_t count); +uint8_t sd_write_sector(uint8_t *data_buff, uint32_t sector, uint32_t count); +uint8_t sd_read_sector_dma(uint8_t *data_buff, uint32_t sector, uint32_t count); +uint8_t sd_write_sector_dma(uint8_t *data_buff, uint32_t sector, + uint32_t count); #ifdef __cplusplus } diff --git a/src/drv/sdcard/sdcard.cpp b/src/drv/sdcard/sdcard.cpp index 4ec593699..44e9ccd72 100644 --- a/src/drv/sdcard/sdcard.cpp +++ b/src/drv/sdcard/sdcard.cpp @@ -1,13 +1,53 @@ -#include "stdio.h" -#include "string.h" -#include "gpiohs.h" #include "stdint.h" -#include "dmac.h" -#include "spi_sd.h" +#include "stdio.h" #include "sdcard.h" -#include "stdlib.h" +#include "spi_sd.h" +#include "gpiohs.h" +/* + * @brief Start Data tokens: + * Tokens (necessary because at nop/idle (and CS active) only 0xff is + * on the data/command line) + */ +#define SD_START_DATA_SINGLE_BLOCK_READ \ + 0xFE /*!< Data token start byte, Start Single Block Read */ +#define SD_START_DATA_MULTIPLE_BLOCK_READ \ + 0xFE /*!< Data token start byte, Start Multiple Block Read */ +#define SD_START_DATA_SINGLE_BLOCK_WRITE \ + 0xFE /*!< Data token start byte, Start Single Block Write */ +#define SD_START_DATA_MULTIPLE_BLOCK_WRITE \ + 0xFC /*!< Data token start byte, Start Multiple Block Write */ +/* + * @brief Commands: CMDxx = CMD-number | 0x40 + */ +#define SD_CMD0 0 /*!< CMD0 = 0x40 */ +#define SD_CMD8 8 /*!< CMD8 = 0x48 */ +#define SD_CMD9 9 /*!< CMD9 = 0x49 */ +#define SD_CMD10 10 /*!< CMD10 = 0x4A */ +#define SD_CMD12 12 /*!< CMD12 = 0x4C */ +#define SD_CMD16 16 /*!< CMD16 = 0x50 */ +#define SD_CMD17 17 /*!< CMD17 = 0x51 */ +#define SD_CMD18 18 /*!< CMD18 = 0x52 */ +#define SD_ACMD23 23 /*!< CMD23 = 0x57 */ +#define SD_CMD24 24 /*!< CMD24 = 0x58 */ +#define SD_CMD25 25 /*!< CMD25 = 0x59 */ +#define SD_ACMD41 41 /*!< ACMD41 = 0x41 */ +#define SD_CMD55 55 /*!< CMD55 = 0x55 */ +#define SD_CMD58 58 /*!< CMD58 = 0x58 */ +#define SD_CMD59 59 /*!< CMD59 = 0x59 */ + +SD_CardInfo cardinfo; + +void sdcard_init() { + uint8_t cardinfo = sd_init(); + if (cardinfo) { + printf("sd card init error\n"); + } + else { + printf("sdcard init: %d\n", cardinfo); + } +} void SD_CS_HIGH(void) { gpiohs_set_pin(7, GPIO_PV_HIGH); } @@ -25,32 +65,19 @@ static void sd_lowlevel_init(uint8_t spi_index) { // spi_set_clk_rate(SPI_DEVICE_0, 200000); /*set clk rate*/ } -// #define SPI_CHIP_SELECT_0 -static void sd_write_data(uint8_t const *data_buff, uint32_t length) { +static void sd_write_data(uint8_t *data_buff, uint32_t length) { spi_init(SPI_DEVICE_0, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0); spi_send_data_standard(SPI_DEVICE_0, SPI_CHIP_SELECT_3, 0, 0, data_buff, length); } static void sd_read_data(uint8_t *data_buff, uint32_t length) { + spi_init(SPI_DEVICE_0, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0); spi_receive_data_standard(SPI_DEVICE_0, SPI_CHIP_SELECT_3, 0, 0, data_buff, length); } -static void sd_write_data_dma(uint8_t const *data_buff, uint32_t length) { - spi_init(SPI_DEVICE_0, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0); - spi_send_data_standard_dma(DMAC_CHANNEL0, SPI_DEVICE_0, SPI_CHIP_SELECT_3, - 0, 0, data_buff, length); -} - -static void sd_read_data_dma(uint8_t *data_buff, uint32_t length) { - spi_init(SPI_DEVICE_0, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0); - spi_receive_data_standard_dma((dmac_channel_number_t)-1, DMAC_CHANNEL0, - SPI_DEVICE_0, SPI_CHIP_SELECT_3, 0, 0, - data_buff, length); -} - /* * @brief Send 5 bytes command to the SD card. * @param Cmd: The user expected command to send to SD card. @@ -60,16 +87,31 @@ static void sd_read_data_dma(uint8_t *data_buff, uint32_t length) { */ static void sd_send_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t frame[6]; + /*!< Construct byte 1 */ frame[0] = (cmd | 0x40); + /*!< Construct byte 2 */ frame[1] = (uint8_t)(arg >> 24); + /*!< Construct byte 3 */ frame[2] = (uint8_t)(arg >> 16); + /*!< Construct byte 4 */ frame[3] = (uint8_t)(arg >> 8); + /*!< Construct byte 5 */ frame[4] = (uint8_t)(arg); + /*!< Construct CRC: byte 6 */ frame[5] = (crc); + /*!< SD chip select low */ SD_CS_LOW(); + /*!< Send the Cmd bytes */ sd_write_data(frame, 6); } +/* + * @brief Send 5 bytes command to the SD card. + * @param Cmd: The user expected command to send to SD card. + * @param Arg: The command argument. + * @param Crc: The CRC. + * @retval None + */ static void sd_end_cmd(void) { uint8_t frame[1] = {0xFF}; /*!< SD chip select high */ @@ -79,206 +121,218 @@ static void sd_end_cmd(void) { } /* - * Be noticed: all commands & responses below - * are in SPI mode format. May differ from - * what they are in SD mode. - */ - -#define SD_CMD0 0 -#define SD_CMD8 8 -#define SD_CMD58 58 // READ_OCR -#define SD_CMD55 55 // APP_CMD -#define SD_ACMD41 41 // SD_SEND_OP_COND -#define SD_CMD16 16 // SET_BLOCK_SIZE -#define SD_CMD17 17 // READ_SINGLE_BLOCK -#define SD_CMD24 24 // WRITE_SINGLE_BLOCK -#define SD_CMD13 13 // SEND_STATUS - -/* - * Read sdcard response in R1 type. + * @brief Returns the SD response. + * @param None + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed */ -static uint8_t sd_get_response_R1(void) { +static uint8_t sd_get_response(void) { uint8_t result; - uint16_t timeout = 0xff; - + uint16_t timeout = 0x0FFF; + /*!< Check if response is got or a timeout is happen */ while (timeout--) { sd_read_data(&result, 1); - if (result != 0xff) + // sd_read_data_dma(&result); + /*!< Right response got */ + if (result != 0xFF) return result; } - - // timeout! - return 0xff; + /*!< After time out */ + return 0xFF; } /* - * Read the rest of R3 response - * Be noticed: frame should be at least 4-byte long + * @brief Get SD card data response. + * @param None + * @retval The SD status: Read data response xxx01 + * - status 010: Data accecpted + * - status 101: Data rejected due to a crc error + * - status 110: Data rejected due to a Write error. + * - status 111: Data rejected due to other error. */ -static void sd_get_response_R3_rest(uint8_t *frame) { - sd_read_data(frame, 4); +static uint8_t sd_get_dataresponse(void) { + uint8_t response; + /*!< Read resonse */ + sd_read_data(&response, 1); + /*!< Mask unused bits */ + response &= 0x1F; + if (response != 0x05) + return 0xFF; + /*!< Wait null data */ + sd_read_data(&response, 1); + while (response == 0) + sd_read_data(&response, 1); + /*!< Return response */ + return 0; } /* - * Read the rest of R7 response - * Be noticed: frame should be at least 4-byte long + * @brief Read the CSD card register + * Reading the contents of the CSD register in SPI mode is a simple + * read-block transaction. + * @param SD_csd: pointer on an SCD register structure + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed */ -static void sd_get_response_R7_rest(uint8_t *frame) { - sd_read_data(frame, 4); -} - -static int switch_to_SPI_mode(void) { - int timeout = 0xff; - - while (--timeout) { - sd_send_cmd(SD_CMD0, 0, 0x95); - uint64_t result = sd_get_response_R1(); +static uint8_t sd_get_csdregister(SD_CSD *SD_csd) { + uint8_t csd_tab[18]; + /*!< Send CMD9 (CSD register) or CMD10(CSD register) */ + sd_send_cmd(SD_CMD9, 0, 0); + /*!< Wait for response in the R1 format (0x00 is no errors) */ + if (sd_get_response() != 0x00) { sd_end_cmd(); - - if (0x01 == result) - break; + return 0xFF; } - if (0 == timeout) { - printf("SD_CMD0 failed\n"); - return 0xff; + if (sd_get_response() != SD_START_DATA_SINGLE_BLOCK_READ) { + sd_end_cmd(); + return 0xFF; } - - return 0; -} - -// verify supply voltage range -static int verify_operation_condition(void) { - uint64_t result; - - // Stores the response reversely. - // That means - // frame[2] - VCA - // frame[3] - Check Pattern - uint8_t frame[4]; - - sd_send_cmd(SD_CMD8, 0x01aa, 0x87); - result = sd_get_response_R1(); - sd_get_response_R7_rest(frame); + /*!< Store CSD register value on csd_tab */ + /*!< Get CRC bytes (not really needed by us, but required by SD) */ + sd_read_data(csd_tab, 18); sd_end_cmd(); - - if (0x09 == result) { - printf("invalid CRC for CMD8\n"); - return 0xff; - } - else if (0x01 == result && 0x01 == (frame[2] & 0x0f) && 0xaa == frame[3]) { - return 0x00; - } - - printf("verify_operation_condition() fail!\n"); - return 0xff; + /*!< Byte 0 */ + SD_csd->CSDStruct = (csd_tab[0] & 0xC0) >> 6; + SD_csd->SysSpecVersion = (csd_tab[0] & 0x3C) >> 2; + SD_csd->Reserved1 = csd_tab[0] & 0x03; + /*!< Byte 1 */ + SD_csd->TAAC = csd_tab[1]; + /*!< Byte 2 */ + SD_csd->NSAC = csd_tab[2]; + /*!< Byte 3 */ + SD_csd->MaxBusClkFrec = csd_tab[3]; + /*!< Byte 4 */ + SD_csd->CardComdClasses = csd_tab[4] << 4; + /*!< Byte 5 */ + SD_csd->CardComdClasses |= (csd_tab[5] & 0xF0) >> 4; + SD_csd->RdBlockLen = csd_tab[5] & 0x0F; + /*!< Byte 6 */ + SD_csd->PartBlockRead = (csd_tab[6] & 0x80) >> 7; + SD_csd->WrBlockMisalign = (csd_tab[6] & 0x40) >> 6; + SD_csd->RdBlockMisalign = (csd_tab[6] & 0x20) >> 5; + SD_csd->DSRImpl = (csd_tab[6] & 0x10) >> 4; + SD_csd->Reserved2 = 0; /*!< Reserved */ + SD_csd->DeviceSize = (csd_tab[6] & 0x03) << 10; + /*!< Byte 7 */ + SD_csd->DeviceSize = (csd_tab[7] & 0x3F) << 16; + /*!< Byte 8 */ + SD_csd->DeviceSize |= csd_tab[8] << 8; + /*!< Byte 9 */ + SD_csd->DeviceSize |= csd_tab[9]; + /*!< Byte 10 */ + SD_csd->EraseGrSize = (csd_tab[10] & 0x40) >> 6; + SD_csd->EraseGrMul = (csd_tab[10] & 0x3F) << 1; + /*!< Byte 11 */ + SD_csd->EraseGrMul |= (csd_tab[11] & 0x80) >> 7; + SD_csd->WrProtectGrSize = (csd_tab[11] & 0x7F); + /*!< Byte 12 */ + SD_csd->WrProtectGrEnable = (csd_tab[12] & 0x80) >> 7; + SD_csd->ManDeflECC = (csd_tab[12] & 0x60) >> 5; + SD_csd->WrSpeedFact = (csd_tab[12] & 0x1C) >> 2; + SD_csd->MaxWrBlockLen = (csd_tab[12] & 0x03) << 2; + /*!< Byte 13 */ + SD_csd->MaxWrBlockLen |= (csd_tab[13] & 0xC0) >> 6; + SD_csd->WriteBlockPaPartial = (csd_tab[13] & 0x20) >> 5; + SD_csd->Reserved3 = 0; + SD_csd->ContentProtectAppli = (csd_tab[13] & 0x01); + /*!< Byte 14 */ + SD_csd->FileFormatGrouop = (csd_tab[14] & 0x80) >> 7; + SD_csd->CopyFlag = (csd_tab[14] & 0x40) >> 6; + SD_csd->PermWrProtect = (csd_tab[14] & 0x20) >> 5; + SD_csd->TempWrProtect = (csd_tab[14] & 0x10) >> 4; + SD_csd->FileFormat = (csd_tab[14] & 0x0C) >> 2; + SD_csd->ECC = (csd_tab[14] & 0x03); + /*!< Byte 15 */ + SD_csd->CSD_CRC = (csd_tab[15] & 0xFE) >> 1; + SD_csd->Reserved4 = 1; + /*!< Return the reponse */ + return 0; } -// read OCR register to check if the voltage range is valid -// this step is not mandotary, but I advise to use it -static int read_OCR(void) { - uint64_t result = 0; - uint8_t ocr[4]; - - int timeout; - - timeout = 0xff; - while (--timeout) { - sd_send_cmd(SD_CMD58, 0, 0); - result = sd_get_response_R1(); - sd_get_response_R3_rest(ocr); +/* + * @brief Read the CID card register. + * Reading the contents of the CID register in SPI mode is a simple + * read-block transaction. + * @param SD_cid: pointer on an CID register structure + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed + */ +static uint8_t sd_get_cidregister(SD_CID *SD_cid) { + uint8_t cid_tab[18]; + /*!< Send CMD10 (CID register) */ + sd_send_cmd(SD_CMD10, 0, 0); + /*!< Wait for response in the R1 format (0x00 is no errors) */ + if (sd_get_response() != 0x00) { sd_end_cmd(); - - if (0x01 == result && // R1 response in idle status - (ocr[1] & 0x1f) && (ocr[2] & 0x80) // voltage range valid - ) { - return 0; - } + return 0xFF; } - - // timeout! - printf("read_OCR() timeout!\n"); - printf("result = %d\n", result); - return 0xff; -} - -// send ACMD41 to tell sdcard to finish initializing -static int set_SDXC_capacity(void) { - uint8_t result = 0xff; - - int timeout = 0xfff; - while (--timeout) { - sd_send_cmd(SD_CMD55, 0, 0); - result = sd_get_response_R1(); - sd_end_cmd(); - if (0x01 != result) { - printf("SD_CMD55 fail! result = %d\n", result); - return 0xff; - } - - sd_send_cmd(SD_ACMD41, 0x40000000, 0); - result = sd_get_response_R1(); + if (sd_get_response() != SD_START_DATA_SINGLE_BLOCK_READ) { sd_end_cmd(); - if (0 == result) { - return 0; - } + return 0xFF; } - - // timeout! - printf("set_SDXC_capacity() timeout!\n"); - printf("result = %d\n", result); - return 0xff; + /*!< Store CID register value on cid_tab */ + /*!< Get CRC bytes (not really needed by us, but required by SD) */ + sd_read_data(cid_tab, 18); + sd_end_cmd(); + /*!< Byte 0 */ + SD_cid->ManufacturerID = cid_tab[0]; + /*!< Byte 1 */ + SD_cid->OEM_AppliID = cid_tab[1] << 8; + /*!< Byte 2 */ + SD_cid->OEM_AppliID |= cid_tab[2]; + /*!< Byte 3 */ + SD_cid->ProdName1 = cid_tab[3] << 24; + /*!< Byte 4 */ + SD_cid->ProdName1 |= cid_tab[4] << 16; + /*!< Byte 5 */ + SD_cid->ProdName1 |= cid_tab[5] << 8; + /*!< Byte 6 */ + SD_cid->ProdName1 |= cid_tab[6]; + /*!< Byte 7 */ + SD_cid->ProdName2 = cid_tab[7]; + /*!< Byte 8 */ + SD_cid->ProdRev = cid_tab[8]; + /*!< Byte 9 */ + SD_cid->ProdSN = cid_tab[9] << 24; + /*!< Byte 10 */ + SD_cid->ProdSN |= cid_tab[10] << 16; + /*!< Byte 11 */ + SD_cid->ProdSN |= cid_tab[11] << 8; + /*!< Byte 12 */ + SD_cid->ProdSN |= cid_tab[12]; + /*!< Byte 13 */ + SD_cid->Reserved1 |= (cid_tab[13] & 0xF0) >> 4; + SD_cid->ManufactDate = (cid_tab[13] & 0x0F) << 8; + /*!< Byte 14 */ + SD_cid->ManufactDate |= cid_tab[14]; + /*!< Byte 15 */ + SD_cid->CID_CRC = (cid_tab[15] & 0xFE) >> 1; + SD_cid->Reserved2 = 1; + /*!< Return the reponse */ + return 0; } -// Used to differ whether sdcard is SDSC type. -static int is_standard_sd = 0; - -// check OCR register to see the type of sdcard, -// thus determine whether block size is suitable to buffer size -static int check_block_size(void) { - uint8_t result = 0xff; - uint8_t ocr[4]; - - int timeout = 0xff; - while (timeout--) { - sd_send_cmd(SD_CMD58, 0, 0); - result = sd_get_response_R1(); - sd_get_response_R3_rest(ocr); - sd_end_cmd(); - - if (0 == result) { - if (ocr[0] & 0x40) { - printf("SDHC/SDXC detected\n"); - is_standard_sd = 0; - } - else { - printf("SDSC detected, setting block size\n"); - // setting SD card block size to 512 - int timeout = 0xff; - int result = 0xff; - while (--timeout) { - sd_send_cmd(SD_CMD16, 512, 0); - result = sd_get_response_R1(); - sd_end_cmd(); - - if (0 == result) - break; - } - if (0 == timeout) { - printf("check_OCR(): fail to set block size"); - return 0xff; - } - - is_standard_sd = 1; - } - - return 0; - } - } - - // timeout! - printf("check_OCR() timeout!\n"); - printf("result = %d\n", result); - return 0xff; +/* + * @brief Returns information about specific card. + * @param cardinfo: pointer to a SD_CardInfo structure that contains all SD + * card information. + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed + */ +static uint8_t sd_get_cardinfo(SD_CardInfo *cardinfo) { + if (sd_get_csdregister(&(cardinfo->SD_csd))) + return 0xFF; + if (sd_get_cidregister(&(cardinfo->SD_cid))) + return 0xFF; + cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) * 1024; + cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen); + cardinfo->CardCapacity *= cardinfo->CardBlockSize; + /*!< Returns the reponse */ + return 0; } /* @@ -288,180 +342,173 @@ static int check_block_size(void) { * - 0xFF: Sequence failed * - 0: Sequence succeed */ -static int sd_init(void) { - uint8_t frame[10]; - +uint8_t sd_init(void) { + uint8_t frame[10], index, result; + /*!< Initialize SD_SPI */ sd_lowlevel_init(0); - // SD_CS_HIGH(); - SD_CS_LOW(); - - // send dummy bytes for 80 clock cycles - for (int i = 0; i < 10; i++) - frame[i] = 0xff; + /*!< SD chip select high */ + SD_CS_HIGH(); + /*!< Send dummy byte 0xFF, 10 times with CS high */ + /*!< Rise CS and MOSI for 80 clocks cycles */ + /*!< Send dummy byte 0xFF */ + for (index = 0; index < 10; index++) + frame[index] = 0xFF; sd_write_data(frame, 10); + /*------------Put SD in SPI mode--------------*/ + /*!< SD initialized and set to SPI mode properly */ - if (0 != switch_to_SPI_mode()) { - printf("1\n"); - return 0xff; + index = 0xFF; + while (index--) { + sd_send_cmd(SD_CMD0, 0, 0x95); + // printf("get_response: %d\n", index); + result = sd_get_response(); + sd_end_cmd(); + if (result == 0x01) + break; } - if (0 != verify_operation_condition()) { - printf("2\n"); - return 0xff; + if (index == 0) { + printf("SD_CMD0 is %x\n", result); + return 0xFF; } - if (0 != read_OCR()) { - printf("3\n"); - return 0xff; + + sd_send_cmd(SD_CMD8, 0x01AA, 0x87); + /*!< 0x01 or 0x05 */ + result = sd_get_response(); + sd_read_data(frame, 4); + sd_end_cmd(); + if (result != 0x01) { + printf("SD_CMD8 is %x\n", result); + return 0xFF; } - if (0 != set_SDXC_capacity()) { - printf("4\n"); - return 0xff; + index = 0xFF; + while (index--) { + sd_send_cmd(SD_CMD55, 0, 0); + result = sd_get_response(); + sd_end_cmd(); + if (result != 0x01) + return 0xFF; + sd_send_cmd(SD_ACMD41, 0x40000000, 0); + result = sd_get_response(); + sd_end_cmd(); + if (result == 0x00) + break; } - if (0 != check_block_size()) { - printf("5\n"); - return 0xff; + if (index == 0) { + printf("SD_CMD55 is %x\n", result); + return 0xFF; } - - return 0; -} - -// static struct sleeplock sdcard_lock; -// SleepLock sdcard_lock; - -int sdcard_init(void) { - int result = sd_init(); - // initsleeplock(&sdcard_lock, "sdcard"); - // sdcard_lock.init("sdcard"); - - if (result != 0) { - printf("sdcard_init failed\n"); + index = 255; + while (index--) { + sd_send_cmd(SD_CMD58, 0, 1); + result = sd_get_response(); + sd_read_data(frame, 4); + sd_end_cmd(); + if (result == 0) { + break; + } } - else { - printf("sdcard_init\n"); + if (index == 0) { + printf("SD_CMD58 is %x\n", result); + return 0xFF; } - return 0; + if ((frame[0] & 0x40) == 0) + return 0xFF; + SD_HIGH_SPEED_ENABLE(); + return sd_get_cardinfo(&cardinfo); } -void sdcard_read_sector(uint8_t *buf, int sectorno) { - uint8_t result; - uint32_t address; - uint8_t dummy_crc[2]; - memset(buf, 0, 512); -#ifdef DEBUG - printf("sdcard_read_sector()\n"); -#endif - - if (is_standard_sd) { - address = sectorno << 9; +/* + * @brief Reads a block of data from the SD. + * @param data_buff: pointer to the buffer that receives the data read from the + * SD. + * @param sector: SD's internal address to read from. + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed + */ +uint8_t sd_read_sector(uint8_t *data_buff, uint32_t sector, uint32_t count) { + uint8_t frame[2], flag; + /*!< Send CMD17 (SD_CMD17) to read one block */ + if (count == 1) { + flag = 0; + sd_send_cmd(SD_CMD17, sector, 0); } else { - address = sectorno; + flag = 1; + sd_send_cmd(SD_CMD18, sector, 0); } - - // enter critical section! - // acquiresleep(&sdcard_lock); - // sdcard_lock.lock(); - - sd_send_cmd(SD_CMD17, address, 0); - result = sd_get_response_R1(); - - if (0 != result) { - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - printf("sdcard: fail to read"); + /*!< Check if the SD acknowledged the read block command: R1 response (0x00: + * no errors) */ + if (sd_get_response() != 0x00) { + sd_end_cmd(); + return 0xFF; } - - int timeout = 0xffffff; - while (--timeout) { - sd_read_data(&result, 1); - if (0xfe == result) + while (count) { + if (sd_get_response() != SD_START_DATA_SINGLE_BLOCK_READ) break; + /*!< Read the SD block data : read NumByteToRead data */ + sd_read_data(data_buff, 512); + /*!< Get CRC bytes (not really needed by us, but required by SD) */ + sd_read_data(frame, 2); + data_buff += 512; + count--; } - if (0 == timeout) { - printf("sdcard: timeout waiting for reading"); - } - sd_read_data_dma(buf, 512); - sd_read_data(dummy_crc, 2); - sd_end_cmd(); - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - // leave critical section! + if (flag) { + sd_send_cmd(SD_CMD12, 0, 0); + sd_get_response(); + sd_end_cmd(); + sd_end_cmd(); + } + /*!< Returns the reponse */ + return count > 0 ? 0xFF : 0; } -void sdcard_write_sector(uint8_t *buf, int sectorno) { - uint32_t address; - static uint8_t const START_BLOCK_TOKEN = 0xfe; - uint8_t dummy_crc[2] = {0xff, 0xff}; -#ifdef DEBUG - printf("sdcard_write_sector()\n"); -#endif +/* + * @brief Writes a block on the SD + * @param data_buff: pointer to the buffer containing the data to be written on + * the SD. + * @param sector: address to write on. + * @retval The SD Response: + * - 0xFF: Sequence failed + * - 0: Sequence succeed + */ +uint8_t sd_write_sector(uint8_t *data_buff, uint32_t sector, uint32_t count) { + uint8_t frame[2] = {0xFF}; - if (is_standard_sd) { - address = sectorno << 9; + if (count == 1) { + frame[1] = SD_START_DATA_SINGLE_BLOCK_WRITE; + sd_send_cmd(SD_CMD24, sector, 0); } else { - address = sectorno; + frame[1] = SD_START_DATA_MULTIPLE_BLOCK_WRITE; + sd_send_cmd(SD_ACMD23, count, 0); + sd_get_response(); + sd_end_cmd(); + sd_send_cmd(SD_CMD25, sector, 0); } - - // enter critical section! - // acquiresleep(&sdcard_lock); - // sdcard_lock.lock(); - - sd_send_cmd(SD_CMD24, address, 0); - if (0 != sd_get_response_R1()) { - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - printf("sdcard: fail to write"); + /*!< Check if the SD acknowledged the write block command: R1 response + * (0x00: no errors) */ + if (sd_get_response() != 0x00) { + sd_end_cmd(); + return 0xFF; } - - // sending data to be written - sd_write_data(&START_BLOCK_TOKEN, 1); - sd_write_data_dma(buf, 512); - sd_write_data(dummy_crc, 2); - - // waiting for sdcard to finish programming - uint8_t result; - int timeout = 0xfff; - while (--timeout) { - sd_read_data(&result, 1); - if (0x05 == (result & 0x1f)) { - break; + while (count--) { + /*!< Send the data token to signify the start of the data */ + sd_write_data(frame, 2); + /*!< Write the block data to SD : write count data by block */ + sd_write_data(data_buff, 512); + /*!< Put CRC bytes (not really needed by us, but required by SD) */ + sd_write_data(frame, 2); + data_buff += 512; + /*!< Read data response */ + if (sd_get_dataresponse() != 0x00) { + sd_end_cmd(); + return 0xFF; } } - if (0 == timeout) { - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - printf("sdcard: invalid response token"); - } - - timeout = 0xffffff; - while (--timeout) { - sd_read_data(&result, 1); - if (0 != result) - break; - } - if (0 == timeout) { - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - printf("sdcard: timeout waiting for response"); - } sd_end_cmd(); - - // send SD_CMD13 to check if writing is correctly done - uint8_t error_code = 0xff; - sd_send_cmd(SD_CMD13, 0, 0); - result = sd_get_response_R1(); - sd_read_data(&error_code, 1); sd_end_cmd(); - if (0 != result || 0 != error_code) { - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - printf("result: %x\n", result); - printf("error_code: %x\n", error_code); - printf("sdcard: an error occurs when writing"); - } - - // releasesleep(&sdcard_lock); - // sdcard_lock.unlock(); - // leave critical section! + /*!< Returns the reponse */ + return 0; } diff --git a/src/kernel/kernel_main.cpp b/src/kernel/kernel_main.cpp index b9886558b..63dd9dbda 100644 --- a/src/kernel/kernel_main.cpp +++ b/src/kernel/kernel_main.cpp @@ -47,7 +47,7 @@ void kernel_main(uint32_t, void *) { fpioa_init(); // gpio_init(); // spi_init(); - dmac_init(); + // dmac_init(); sdcard_init(); test_sdcard(); #endif @@ -214,27 +214,40 @@ int test_vfs(void) { } int test_sdcard(void) { - uint8_t buf[512]; - for (int sec = 0; sec < 5; sec++) { - for (int i = 0; i < 512; i++) { - buf[i] = 0xaa; // data to be written - } - // sdcard_write_sector(buf, sec); - - for (int i = 0; i < 512; i++) { - buf[i] = 0xff; // fill in junk - } - - sdcard_read_sector(buf, sec); - for (int i = 0; i < 512; i++) { - if (0 == i % 16) { - printf("\n"); - } - - printf("%x ", buf[i]); - } - printf("\n"); + uint8_t *buffer = (uint8_t *)malloc(0x1000); + uint8_t *pre_buffer = (uint8_t *)malloc(0x1000); + memset(buffer, 0, sizeof(buffer)); + if (sd_read_sector(pre_buffer, 0, sizeof(pre_buffer))) { + printf("[test_sdcard]SD card read sector err\n"); + } + else { + printf("[test_sdcard]SD card read sector succeed\n"); + } + printf("[test_sdcard]Buffer: %s\n", buffer); + memmove(buffer, "Hello,sdcard", sizeof("Hello,sdcard")); + printf("[test_sdcard]Buffer: %s\n", buffer); + if (sd_write_sector(buffer, 0, sizeof(buffer))) { + printf("[test_sdcard]SD card write sector err\n"); + } + else { + printf("[test_sdcard]SD card write sector succeed\n"); + } + memset(buffer, 0, sizeof(buffer)); + if (sd_read_sector(buffer, 0, sizeof(buffer))) { + printf("[test_sdcard]SD card read sector err\n"); + } + else { + printf("[test_sdcard]SD card read sector succeed\n"); + } + printf("[test_sdcard]Buffer: %s\n", buffer); + if (sd_write_sector(pre_buffer, 0, sizeof(pre_buffer))) { + printf("[test_sdcard]SD card recover err\n"); + } + else { + printf("[test_sdcard]SD card recover succeed\n"); } + free(buffer); + free(pre_buffer); printf("sd card test done\n"); return 0;