static void testReadWrite() { int32_t ret; { ret = sd_setBlockSize(sd, SD_BLOCK_SIZE_512B); CONFIG_ASSERT(ret == 0); #if 1 memset(data, 0x42, ARRAY_SIZE(data)); /* read 4K from card */ ret = sd_read(sd, CMD(18), 0, ARRAY_SIZE(data), (uint32_t *) data, 1000 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); /* stop transver */ ret = sd_sendCommand(sd, CMD(12), 0, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); #else memset(data, 0x00, ARRAY_SIZE(data)); #endif /* Write Back test */ ret = sd_write(sd, CMD(25), 0, ARRAY_SIZE(data), (uint32_t *) data, 1000 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); /* stop transver */ ret = sd_sendCommand(sd, CMD(12), 0, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); vTaskDelay(500 / portTICK_PERIOD_MS); /* read 4K from card */ ret = sd_read(sd, CMD(18), 0, ARRAY_SIZE(data2), (uint32_t *) data2, 1000 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); /* stop transver */ ret = sd_sendCommand(sd, CMD(12), 0, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); ret = memcmp(data, data2, ARRAY_SIZE(data)); CONFIG_ASSERT(ret == 0); } }
uint8_t sd_read( uint8_t card_type, uint32_t addr, uint8_t *buff, uint16_t size ){ uint32_t block_addr; uint16_t offset; uint8_t resp; uint8_t retry; uint16_t idx; if( card_type == SDCARD_TYPR_SDSC || card_type == SDCARD_TYPR_1 ){ block_addr = addr &(~0x1ff); offset = addr & 0x1ff; } else{ block_addr = addr>>5; offset = ( addr - (block_addr<<5) ) * 16; } PDEBUG( "read block addr %u\n", block_addr ); PDEBUG( "offset %u\n", offset ); resp = sd_sendCommand( READ_SINGLE_BLOCK, block_addr ); if( resp != 0x00 ){ PDEBUG( "CMD READ_SINGLE_BLOCK failure: %d\n", resp ); return SDCARD_FAILURE; } /* Wait for token 0xfe */ sd_pin_CS_setValue( 0 ); retry = RETRY_CMD_COUNT; do{ resp = sd_spi_rw( 0xff ); if( retry-- == 0 ){ sd_pin_CS_setValue( 1 ); PDEBUG( "wait for token: timeout\n" ); return SDCARD_FAILURE; } }while( resp != 0xfe ); sd_readBuffer( 0, offset ); sd_readBuffer( buff, size ); sd_readBuffer( 0, 514-size-offset ); sd_pin_CS_setValue( 1 ); sd_clockDelay( 10 ); /* retry = 0; for( idx=0; idx<512; ++idx ){ printf( "%x ", sd_spi_rw( 0xff ) ); ++retry; if( retry == 32 ){ retry = 0; printf( "\n" ); } } sd_spi_rw( 0xff ); sd_spi_rw( 0xff ); sd_spi_rw( 0xff ); sd_pin_CS_setValue( 1 ); */ //_delay_ms( 1000 ); PDEBUG( "Read OK\n" ); }
uint8_t __sd_init( void ){ uint16_t retry; uint8_t resp; sd_pin_setup(); sd_clockDelay( 10 ); // 80 clock //sd_pin_CS_setValue( 0 ); /* 发送CMD0, 进入SPI模式 */ retry = RETRY_CMD_COUNT; do{ resp = sd_sendCommand( CMD0, 0 ); if( --retry == 0 ) break; }while( resp != IN_IDLE_STATE ); sd_clockDelay( 2 ); PDEBUG( "CMD0 response 0x%x\n", resp ); if( resp != IN_IDLE_STATE ){ PDEBUG( "CMD0 failure\n" ); return SDCARD_FAILURE; } /* * 发送CMD8命令, 1.x的卡不支持CMD8命令, 对于2.0卡 * 该命令是必要的, 可用于判断卡的版本 */ retry = RETRY_CMD_COUNT; do{ resp = sd_sendCommand( CMD8, 0x1aa ); if( --retry == 0 ) break; }while( resp == 0xff ); sd_clockDelay( 2 ); PDEBUG( "CMD8 response: 0x%x\n", resp ); if( resp == 0xff ){ PDEBUG( "CMD8 failure\n" ); return SDCARD_FAILURE; } /* * 如果响应CMD8, 则为2.00卡 */ if( resp == IN_IDLE_STATE ){ PDEBUG( "This is V2.00 Card\n" ); //sd_readBuffer( resp_data, 4 ); PDEBUG( "resp data = 0x%x, 0x%x, 0x%x, 0x%x\n", resp_data[0], resp_data[1],resp_data[2],resp_data[3] ); if( resp_data[2] == 0x01 && resp_data[3] == 0xaa ){ //if( 1 ){ /* TODO */ /* * 发送ACMD41 */ retry = RETRY_CMD_COUNT; do{ resp = sd_sendCommand( CMD55, 0 ); sd_clockDelay( 2 ); resp = sd_sendCommand( ACMD41, 0x40000000 ); if( --retry == 0 ) break; }while( resp != 0x00 ); sd_clockDelay( 2 ); PDEBUG( "ACMD41 response : 0x%x\n", resp ); if( resp != 0x00 ){ PDEBUG( "ACMD41 failure\n" ); return SDCARD_FAILURE; } PDEBUG( "ACMD41 OK\n" ); /* * 发送CMD58, read ocr */ retry = RETRY_CMD_COUNT; do{ resp = sd_sendCommand( CMD58, 0 ); // 返回R3 if( --retry == 0 ) break; }while( resp != 0x00 ); PDEBUG( "CMD58 response : 0x%x\n", resp ); PDEBUG( "resp data = 0x%x\n", resp_data[0] ); if( resp_data[0]&OCR_CCS_BYTE ){ PDEBUG( "SDHC or SDXC\n" ); return SDCARD_TYPR_SDHC; } else{ PDEBUG( "SDSC\n" ); return SDCARD_TYPR_SDSC; } }else{ PDEBUG( "CMD8 response error\n" ); return SDCARD_FAILURE; } } /* * 如果不能正确响应CMD8, 则为1.x卡 */ //else if( resp == (IN_IDLE_STATE|ILLEGAL_COMMAND) ){ // V 1.x else{ PDEBUG( "This is V1.x Card\n" ); /* * 发送ACMD41 */ retry = RETRY_CMD_COUNT; do{ resp = sd_sendCommand( CMD55, 0 ); resp = sd_sendCommand( ACMD41, 0 ); if( --retry == 0 ) break; }while( resp != 0x00 ); PDEBUG( "ACMD41 response : 0x%x\n", resp ); if( resp != 0x00 ){ PDEBUG( "ACMD41 failure\n" ); return SDCARD_FAILURE; } PDEBUG( "ACMD41 OK\n" ); return SDCARD_TYPR_1; } PDEBUG( "init OK\n" ); return SDCARD_SUCCESS; }
void sdtest_task(void *d) { struct sd_response res; int32_t ret; uint32_t arg; uint32_t rca; (void) data; ret = sd_sendCommand(sd, CMD(0), 0, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); { arg = 0; arg |= (0x1 << 8); /* Select 2.7 - 3.3 V */ arg |= (0x42 << 0); /* 8 Bit Check Pattern */ ret = sd_sendCommand(sd, CMD(8), arg, &res, 100 / portTICK_PERIOD_MS); /* Only Version >= 2.0 is suppored in this test */ CONFIG_ASSERT(ret == 0); /* Voltage shall acceped and check pattern is 0x42 */ CONFIG_ASSERT((res.data[3] & 0xFFF) == ((1 << 8) | (0x42 << 0))); } { arg = 0; arg |= BIT(19) | BIT(20) | BIT(31); /* aprox 3.3 is used */; arg |= BIT(28); /* Switch from Power Save to max perf */ arg |= BIT(30); /* Acrivate SDHC or SDXC Support */ do { /* Send ACMD41 -> CMD55 + ACMD41 */ ret = sd_sendCommand(sd, CMD(55), 0, &res, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); ret = sd_sendCommand(sd, ACMD(41), arg, &res, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); } while (((res.data[3] >> 31) & 0x1) != 0x1); } { /* Ask for CID */ ret = sd_sendCommand(sd, CMD(2), 0, &res, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); /* Set Card to ready mode and get RCA*/ ret = sd_sendCommand(sd, CMD(3), 0, &res, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); rca = res.data[3] & 0xFFFF0000; /* Set Card is transver mode */ ret = sd_sendCommand(sd, CMD(7), rca, 0, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); } testReadWrite(); { arg = 0; arg |= 2; ret = sd_sendCommand(sd, CMD(55), rca, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); ret = sd_sendCommand(sd, ACMD(6), arg, NULL, 100 / portTICK_PERIOD_MS); CONFIG_ASSERT(ret == 0); ret = sd_setBusWide(sd, SD_BusWide_4b); CONFIG_ASSERT(ret == 0); } testReadWrite(); { ret = sd_setClock(sd, 48000000); CONFIG_ASSERT(ret == 0); } testReadWrite(); vTaskSuspend(NULL); }