/* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */
SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
/* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */
SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
- (1 << SPE) | /* SPI Enable */
- (0 << DORD) | /* Data Order: MSB first */
- (1 << MSTR) | /* Master mode */
- (0 << CPOL) | /* Clock Polarity: SCK low when idle */
- (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
- (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
- (1 << SPR0);
+ (1 << SPE) | /* SPI Enable */
+ (0 << DORD) | /* Data Order: MSB first */
+ (1 << MSTR) | /* Master mode */
+ (0 << CPOL) | /* Clock Polarity: SCK low when idle */
+ (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
+ (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
+ (1 << SPR0);
- response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);
- if(response == (1 << R1_IDLE_STATE))
- break;
-
- if(i == 0x1ff)
- {
- unselect_card();
- return 0;
- }
+ response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);
+ if(response == (1 << R1_IDLE_STATE))
+ break;
+
+ if(i == 0x1ff)
+ {
+ unselect_card();
+ return 0;
+ }
response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */);
if((response & (1 << R1_ILL_COMMAND)) == 0)
{
response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */);
if((response & (1 << R1_ILL_COMMAND)) == 0)
{
- sd_raw_rec_byte();
- sd_raw_rec_byte();
- if((sd_raw_rec_byte() & 0x01) == 0)
- return 0; /* card operation voltage range doesn't match */
- if(sd_raw_rec_byte() != 0xaa)
- return 0; /* wrong test pattern */
-
- /* card conforms to SD 2 card specification */
- sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
+ sd_raw_rec_byte();
+ sd_raw_rec_byte();
+ if((sd_raw_rec_byte() & 0x01) == 0)
+ return 0; /* card operation voltage range doesn't match */
+ if(sd_raw_rec_byte() != 0xaa)
+ return 0; /* wrong test pattern */
+
+ /* card conforms to SD 2 card specification */
+ sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
- /* determine SD/MMC card type */
- sd_raw_send_command(CMD_APP, 0);
- response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0);
- if((response & (1 << R1_ILL_COMMAND)) == 0)
- {
- /* card conforms to SD 1 card specification */
- sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
- }
- else
- {
- /* MMC card */
- }
+ /* determine SD/MMC card type */
+ sd_raw_send_command(CMD_APP, 0);
+ response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0);
+ if((response & (1 << R1_ILL_COMMAND)) == 0)
+ {
+ /* card conforms to SD 1 card specification */
+ sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
+ }
+ else
+ {
+ /* MMC card */
+ }
- sd_raw_send_command(CMD_APP, 0);
- response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
- }
- else
- {
- response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
- }
-
- if((response & (1 << R1_IDLE_STATE)) == 0)
- break;
-
- if(i == 0x7fff)
- {
- unselect_card();
- return 0;
- }
+ sd_raw_send_command(CMD_APP, 0);
+ response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
+ }
+ else
+ {
+ response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
+ }
+
+ if((response & (1 << R1_IDLE_STATE)) == 0)
+ break;
+
+ if(i == 0x7fff)
+ {
+ unselect_card();
+ return 0;
+ }
- if(sd_raw_send_command(CMD_READ_OCR, 0))
- {
- unselect_card();
- return 0;
- }
-
- if(sd_raw_rec_byte() & 0x40)
- sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);
-
- sd_raw_rec_byte();
- sd_raw_rec_byte();
- sd_raw_rec_byte();
+ if(sd_raw_send_command(CMD_READ_OCR, 0))
+ {
+ unselect_card();
+ return 0;
+ }
+
+ if(sd_raw_rec_byte() & 0x40)
+ sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);
+
+ sd_raw_rec_byte();
+ sd_raw_rec_byte();
+ sd_raw_rec_byte();
}
#endif
/* set block size to 512 bytes */
if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512))
{
}
#endif
/* set block size to 512 bytes */
if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512))
{
- case CMD_GO_IDLE_STATE:
- sd_raw_send_byte(0x95);
- break;
- case CMD_SEND_IF_COND:
- sd_raw_send_byte(0x87);
- break;
- default:
- sd_raw_send_byte(0xff);
- break;
+ case CMD_GO_IDLE_STATE:
+ sd_raw_send_byte(0x95);
+ break;
+ case CMD_SEND_IF_COND:
+ sd_raw_send_byte(0x87);
+ break;
+ default:
+ sd_raw_send_byte(0xff);
+ break;
- /* determine byte count to read at once */
- block_offset = offset & 0x01ff;
- block_address = offset - block_offset;
- read_length = 512 - block_offset; /* read up to block border */
- if(read_length > length)
- read_length = length;
-
+ /* determine byte count to read at once */
+ block_offset = offset & 0x01ff;
+ block_address = offset - block_offset;
+ read_length = 512 - block_offset; /* read up to block border */
+ if(read_length > length)
+ read_length = length;
+
- /* read byte block */
- uint16_t read_to = block_offset + read_length;
- for(uint16_t i = 0; i < 512; ++i)
- {
- uint8_t b = sd_raw_rec_byte();
- if(i >= block_offset && i < read_to)
- *buffer++ = b;
- }
+ /* read byte block */
+ uint16_t read_to = block_offset + read_length;
+ for(uint16_t i = 0; i < 512; ++i)
+ {
+ uint8_t b = sd_raw_rec_byte();
+ if(i >= block_offset && i < read_to)
+ *buffer++ = b;
+ }
- /* read byte block */
- uint8_t* cache = raw_block;
- for(uint16_t i = 0; i < 512; ++i)
- *cache++ = sd_raw_rec_byte();
- raw_block_address = block_address;
-
- memcpy(buffer, raw_block + block_offset, read_length);
- buffer += read_length;
+ /* read byte block */
+ uint8_t* cache = raw_block;
+ for(uint16_t i = 0; i < 512; ++i)
+ *cache++ = sd_raw_rec_byte();
+ raw_block_address = block_address;
+
+ memcpy(buffer, raw_block + block_offset, read_length);
+ buffer += read_length;
uint8_t sd_raw_read_interval(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p)
{
if(!buffer || interval == 0 || length < interval || !callback)
uint8_t sd_raw_read_interval(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p)
{
if(!buffer || interval == 0 || length < interval || !callback)
- /* as reading is now buffered, we directly
- * hand over the request to sd_raw_read()
- */
- if(!sd_raw_read(offset, buffer, interval))
- return 0;
- if(!callback(buffer, offset, p))
- break;
- offset += interval;
- length -= interval;
+ /* as reading is now buffered, we directly
+ * hand over the request to sd_raw_read()
+ */
+ if(!sd_raw_read(offset, buffer, interval))
+ return 0;
+ if(!callback(buffer, offset, p))
+ break;
+ offset += interval;
+ length -= interval;
- /* determine byte count to read at once */
- block_offset = offset & 0x01ff;
- read_length = 512 - block_offset;
-
- /* send single block request */
+ /* determine byte count to read at once */
+ block_offset = offset & 0x01ff;
+ read_length = 512 - block_offset;
+
+ /* send single block request */
- {
- unselect_card();
- return 0;
- }
-
- /* wait for data block (start byte 0xfe) */
- while(sd_raw_rec_byte() != 0xfe);
-
- /* read up to the data of interest */
- for(uint16_t i = 0; i < block_offset; ++i)
- sd_raw_rec_byte();
-
- /* read interval bytes of data and execute the callback */
- do
- {
- if(read_length < interval || length < interval)
- break;
-
- buffer_cur = buffer;
- for(uint16_t i = 0; i < interval; ++i)
- *buffer_cur++ = sd_raw_rec_byte();
-
- if(!callback(buffer, offset + (512 - read_length), p))
- {
- finished = 1;
- break;
- }
-
- read_length -= interval;
- length -= interval;
-
- } while(read_length > 0 && length > 0);
-
- /* read rest of data block */
- while(read_length-- > 0)
- sd_raw_rec_byte();
-
- /* read crc16 */
- sd_raw_rec_byte();
- sd_raw_rec_byte();
-
- if(length < interval)
- break;
-
- offset = offset - block_offset + 512;
+ {
+ unselect_card();
+ return 0;
+ }
+
+ /* wait for data block (start byte 0xfe) */
+ while(sd_raw_rec_byte() != 0xfe);
+
+ /* read up to the data of interest */
+ for(uint16_t i = 0; i < block_offset; ++i)
+ sd_raw_rec_byte();
+
+ /* read interval bytes of data and execute the callback */
+ do
+ {
+ if(read_length < interval || length < interval)
+ break;
+
+ buffer_cur = buffer;
+ for(uint16_t i = 0; i < interval; ++i)
+ *buffer_cur++ = sd_raw_rec_byte();
+
+ if(!callback(buffer, offset + (512 - read_length), p))
+ {
+ finished = 1;
+ break;
+ }
+
+ read_length -= interval;
+ length -= interval;
+
+ } while(read_length > 0 && length > 0);
+
+ /* read rest of data block */
+ while(read_length-- > 0)
+ sd_raw_rec_byte();
+
+ /* read crc16 */
+ sd_raw_rec_byte();
+ sd_raw_rec_byte();
+
+ if(length < interval)
+ break;
+
+ offset = offset - block_offset + 512;
- /* determine byte count to write at once */
- block_offset = offset & 0x01ff;
- block_address = offset - block_offset;
- write_length = 512 - block_offset; /* write up to block border */
- if(write_length > length)
- write_length = length;
-
- /* Merge the data to write with the content of the block.
- * Use the cached block if available.
- */
- if(block_address != raw_block_address)
- {
+ /* determine byte count to write at once */
+ block_offset = offset & 0x01ff;
+ block_address = offset - block_offset;
+ write_length = 512 - block_offset; /* write up to block border */
+ if(write_length > length)
+ write_length = length;
+
+ /* Merge the data to write with the content of the block.
+ * Use the cached block if available.
+ */
+ if(block_address != raw_block_address)
+ {
- if(block_offset || write_length < 512)
- {
- if(!sd_raw_read(block_address, raw_block, sizeof(raw_block)))
- return 0;
- }
- raw_block_address = block_address;
- }
+ if(block_offset || write_length < 512)
+ {
+ if(!sd_raw_read(block_address, raw_block, sizeof(raw_block)))
+ return 0;
+ }
+ raw_block_address = block_address;
+ }
- if(buffer != raw_block)
- {
- memcpy(raw_block + block_offset, buffer, write_length);
+ if(buffer != raw_block)
+ {
+ memcpy(raw_block + block_offset, buffer, write_length);
- /* write byte block */
- uint8_t* cache = raw_block;
- for(uint16_t i = 0; i < 512; ++i)
- sd_raw_send_byte(*cache++);
+ /* write byte block */
+ uint8_t* cache = raw_block;
+ for(uint16_t i = 0; i < 512; ++i)
+ sd_raw_send_byte(*cache++);
- /* write dummy crc16 */
- sd_raw_send_byte(0xff);
- sd_raw_send_byte(0xff);
+ /* write dummy crc16 */
+ sd_raw_send_byte(0xff);
+ sd_raw_send_byte(0xff);
- buffer += write_length;
- offset += write_length;
- length -= write_length;
+ buffer += write_length;
+ offset += write_length;
+ length -= write_length;
- uint16_t bytes_to_write = callback(buffer, offset, p);
- if(!bytes_to_write)
- break;
- if(!endless && bytes_to_write > length)
- return 0;
-
- /* as writing is always buffered, we directly
- * hand over the request to sd_raw_write()
- */
- if(!sd_raw_write(offset, buffer, bytes_to_write))
- return 0;
-
- offset += bytes_to_write;
- length -= bytes_to_write;
+ uint16_t bytes_to_write = callback(buffer, offset, p);
+ if(!bytes_to_write)
+ break;
+ if(!endless && bytes_to_write > length)
+ return 0;
+
+ /* as writing is always buffered, we directly
+ * hand over the request to sd_raw_write()
+ */
+ if(!sd_raw_write(offset, buffer, bytes_to_write))
+ return 0;
+
+ offset += bytes_to_write;
+ length -= bytes_to_write;
- uint8_t b = sd_raw_rec_byte();
-
- switch(i)
- {
- case 0:
- info->manufacturer = b;
- break;
- case 1:
- case 2:
- info->oem[i - 1] = b;
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- info->product[i - 3] = b;
- break;
- case 8:
- info->revision = b;
- break;
- case 9:
- case 10:
- case 11:
- case 12:
- info->serial |= (uint32_t) b << ((12 - i) * 8);
- break;
- case 13:
- info->manufacturing_year = b << 4;
- break;
- case 14:
- info->manufacturing_year |= b >> 4;
- info->manufacturing_month = b & 0x0f;
- break;
- }
+ uint8_t b = sd_raw_rec_byte();
+
+ switch(i)
+ {
+ case 0:
+ info->manufacturer = b;
+ break;
+ case 1:
+ case 2:
+ info->oem[i - 1] = b;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ info->product[i - 3] = b;
+ break;
+ case 8:
+ info->revision = b;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ info->serial |= (uint32_t) b << ((12 - i) * 8);
+ break;
+ case 13:
+ info->manufacturing_year = b << 4;
+ break;
+ case 14:
+ info->manufacturing_year |= b >> 4;
+ info->manufacturing_month = b & 0x0f;
+ break;
+ }
uint8_t csd_structure = 0;
if(sd_raw_send_command(CMD_SEND_CSD, 0))
{
uint8_t csd_structure = 0;
if(sd_raw_send_command(CMD_SEND_CSD, 0))
{
- uint8_t b = sd_raw_rec_byte();
-
- if(i == 0)
- {
- csd_structure = b >> 6;
- }
- else if(i == 14)
- {
- if(b & 0x40)
- info->flag_copy = 1;
- if(b & 0x20)
- info->flag_write_protect = 1;
- if(b & 0x10)
- info->flag_write_protect_temp = 1;
- info->format = (b & 0x0c) >> 2;
- }
- else
- {
+ uint8_t b = sd_raw_rec_byte();
+
+ if(i == 0)
+ {
+ csd_structure = b >> 6;
+ (void)csd_structure;
+ }
+ else if(i == 14)
+ {
+ if(b & 0x40)
+ info->flag_copy = 1;
+ if(b & 0x20)
+ info->flag_write_protect = 1;
+ if(b & 0x10)
+ info->flag_write_protect_temp = 1;
+ info->format = (b & 0x0c) >> 2;
+ }
+ else
+ {
- if(csd_structure == 0x01)
- {
- switch(i)
- {
- case 7:
- b &= 0x3f;
- case 8:
- case 9:
- csd_c_size <<= 8;
- csd_c_size |= b;
- break;
- }
- if(i == 9)
- {
- ++csd_c_size;
- info->capacity = (offset_t) csd_c_size * 512 * 1024;
- }
- }
- else if(csd_structure == 0x00)
+ if(csd_structure == 0x01)
+ {
+ switch(i)
+ {
+ case 7:
+ b &= 0x3f;
+ case 8:
+ case 9:
+ csd_c_size <<= 8;
+ csd_c_size |= b;
+ break;
+ }
+ if(i == 9)
+ {
+ ++csd_c_size;
+ info->capacity = (offset_t) csd_c_size * 512 * 1024;
+ }
+ }
+ else if(csd_structure == 0x00)
- {
- switch(i)
- {
- case 5:
- csd_read_bl_len = b & 0x0f;
- break;
- case 6:
- csd_c_size = b & 0x03;
- csd_c_size <<= 8;
- break;
- case 7:
- csd_c_size |= b;
- csd_c_size <<= 2;
- break;
- case 8:
- csd_c_size |= b >> 6;
- ++csd_c_size;
- break;
- case 9:
- csd_c_size_mult = b & 0x03;
- csd_c_size_mult <<= 1;
- break;
- case 10:
- csd_c_size_mult |= b >> 7;
-
- info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);
- break;
- }
- }
- }
+ {
+ switch(i)
+ {
+ case 5:
+ csd_read_bl_len = b & 0x0f;
+ break;
+ case 6:
+ csd_c_size = b & 0x03;
+ csd_c_size <<= 8;
+ break;
+ case 7:
+ csd_c_size |= b;
+ csd_c_size <<= 2;
+ break;
+ case 8:
+ csd_c_size |= b >> 6;
+ ++csd_c_size;
+ break;
+ case 9:
+ csd_c_size_mult = b & 0x03;
+ csd_c_size_mult <<= 1;
+ break;
+ case 10:
+ csd_c_size_mult |= b >> 7;
+
+ info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);
+ break;
+ }
+ }
+ }