int strategy( const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int myhd[HNUM]; int select = -1; int hdcopy[CNUM]; int udcopy[us]; int currentpoint = 0; int deck[CNUM] = { 0 }; int decknum = CNUM; int k; int lastchangehd = 0; // 最初から高い点なら手札を変えずに終了 arr_copy( hdcopy, hd, HNUM); currentpoint = poker_point(hdcopy); if ( currentpoint >= P6 ) { return -1; } arr_copy( udcopy, ud, us ); decknum = make_deck( hdcopy, udcopy, us, deck ); if ( tk == 4 && decknum <= 7 - cg ) { //LAST_RECURSION_LIMIT = decknum; select = select_card_last( hdcopy, cg, tk, udcopy, us, deck, decknum ); } else { select = select_card( hdcopy, cg, tk, udcopy, us, deck, decknum ); } return select; }
DRESULT disk_readp ( BYTE* dest, /* Pointer to the destination object */ DWORD sector, /* Sector number (LBA) */ WORD sofs, /* Offset in the sector */ WORD count /* Byte count (bit15:destination) */ ) { DRESULT res; USHORT timeout; USHORT bytes_to_read; select_card(); if(!(card_type & CT_BLOCK)) sector *= 512; res = RES_ERROR; if(send_cmd(CMD_17, sector, 0x00) != 0){ deselect_card(); return RES_ERROR; } timeout = 4000; while((rec_byte() != 0xFE) && timeout--){} if(timeout){ bytes_to_read = 514 - sofs - count; //Pass through offset if(sofs){ do{ rec_byte(); }while(--sofs); //Debug: check this } //get requested data bytes if(dest){ do { *dest++ = rec_byte(); } while (--count); }else{ do { rec_byte();//DEBUG: Not sure if i need this. Examples uses FORWARD(rec_byte()); for communication with a computer }while(--count); } //skip over trailing bytes do { rec_byte(); }while(--bytes_to_read); res = RES_OK; }//close if timeout deselect_card(); rec_byte(); return res; }
uint16_t sd_raw_read_start(uint32_t offset, uint8_t* buffer, uint16_t length) { uint32_t block_address; if (currentblockoffset != 0xFFFF) { putstring("YEEEK"); while (1); } if (length > 512) length = 512; /* determine byte count to read at once */ block_address = offset & 0xfffffe00; // putstring("\n\raddr "); uart_putdw_hex(block_address); /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, block_address)) { unselect_card(); return 0; } /* wait for data block (start byte 0xfe) */ while(sd_raw_rec_byte() != 0xfe); /* read byte block */ for(currentblockoffset = 0; currentblockoffset < length; ++currentblockoffset) { *buffer++ = sd_raw_rec_byte(); //uart_putc(b); } return length; }
static int spi_set_init_para(struct rtsx_chip *chip) { struct spi_info *spi = &(chip->spi); int retval; RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8)); RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div)); retval = switch_clock(chip, spi->spi_clock); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); retval = select_card(chip, SPI_CARD); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN); RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN); wait_timeout(10); retval = spi_init(chip); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); return STATUS_SUCCESS; }
struct sd_card * mmchs_card_initialize(struct sd_slot *slot) { // mmchs_init(1); struct sd_card *card; card = &slot->card; memset(card, 0, sizeof(struct sd_card)); card->slot = slot; if (card_goto_idle_state()) { mmc_log_warn(&log, "Failed to go idle state\n"); return NULL; } if (card_identification()) { mmc_log_warn(&log, "Failed to do card_identification\n"); return NULL; } if (card_query_voltage_and_type(&slot->card.regs)) { mmc_log_warn(&log, "Failed to do card_query_voltage_and_type\n"); return NULL; } if (card_identify(&slot->card.regs)) { mmc_log_warn(&log, "Failed to identify card\n"); return NULL; } /* We have now initialized the hardware identified the card */ if (card_csd(&slot->card.regs)) { mmc_log_warn(&log, "failed to read csd (card specific data)\n"); return NULL; } if (select_card(&slot->card.regs)) { mmc_log_warn(&log, "Failed to select card\n"); return NULL; } if (SD_CSD_READ_BL_LEN(slot->card.regs.csd) != 0x09) { /* for CSD version 2.0 the value is fixed to 0x09 and means a * block size of 512 */ mmc_log_warn(&log, "Block size expect to be 512\n"); return NULL; } slot->card.blk_size = 512; /* HARDCODED value */ slot->card.blk_count = SD_CSD_V2_CAPACITY(slot->card.regs.csd); slot->card.state = SD_MODE_DATA_TRANSFER_MODE; memset(slot->card.part, 0, sizeof(slot->card.part)); memset(slot->card.subpart, 0, sizeof(slot->card.subpart)); slot->card.part[0].dv_base = 0; slot->card.part[0].dv_size = (unsigned long long) SD_CSD_V2_CAPACITY(slot->card.regs.csd) * 512; return &slot->card; }
tCardInfo *mmc_card_info(int card_no) { tCardInfo *card = &card_info[card_no]; if (!card->initialized && ((card_no == 0) || mmc_detect())) { select_card(card_no); deselect_card(); } return card; }
static int spi_set_init_para(struct rtsx_chip *chip) { struct spi_info *spi = &(chip->spi); int retval; retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8)); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div)); if (retval) { rtsx_trace(chip); return retval; } retval = switch_clock(chip, spi->spi_clock); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; } retval = select_card(chip, SPI_CARD); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; } retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN); if (retval) { rtsx_trace(chip); return retval; } retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN); if (retval) { rtsx_trace(chip); return retval; } wait_timeout(10); retval = spi_init(chip); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); return STATUS_FAIL; } return STATUS_SUCCESS; }
//This function assumes the SD card has been powered for at least a second before being called DSTATUS disk_initialize (void) { unsigned i; init_spi(); init_card_select_pin(); //pull CS high, then send at least 74 clock pulses to the module with SIMO high deselect_card(); for(i = 0; i <= 10; i++){ rec_byte(); } //pull CS low and send CMD0 to reset card and put it in SPI mode select_card(); if (send_cmd(CMD_0, 0x00000000, 0x95) != 1){ deselect_card(); return RES_ERROR; } if(send_cmd(CMD_8, 0x000001AA, 0x87) == 1){ //Check voltage range on card. If a non-one value is returned, card is not sd v.2 if(get_r7_resp(0xAA) != RES_OK){ //returns 1 if card works at 2.7-3.3V and check_pattern is valid deselect_card(); return RES_ERROR; } if(check_ocr_voltage_range() != RES_OK){ deselect_card(); return RES_ERROR; } if(wait_for_card_to_finish_init() != RES_OK){ deselect_card(); return RES_ERROR; } if(check_card_type() != RES_OK){ deselect_card(); return RES_ERROR; } }//close if cmd_8 //else{ //}//Version 1.0 or earlier deselect_card(); return RES_OK; }
DRESULT disk_writep ( const BYTE* buff, /* Pointer to the data to be written, NULL:Initiate/Finalize write operation */ DWORD sc /* Sector number (LBA) or Number of bytes to send */ ) { DRESULT res; WORD byte_count; static WORD bytes_left_in_block; //counter used to write data select_card(); res = RES_ERROR; if (buff) { byte_count = (WORD)sc; while(bytes_left_in_block && byte_count){ send_byte(*buff++); byte_count--; bytes_left_in_block--; }//end of while res = RES_OK; }//end of if(buf) else if (sc) { if(!(card_type & CT_BLOCK)) sc *= 512; //multiply address by 512 if the card is byte addrssed if(send_cmd(WRITE_BLOCK, sc, 0x00) == 0){ send_byte(0xFF); //Send header byte 1 send_byte(0xFE); //Send header byte 2 bytes_left_in_block = 512; } res = RES_OK; }//end of 1st else else{ fill_zeros(bytes_left_in_block); res = check_write_success(); deselect_card(); }//end 2nd else return res; }//End of writep
uint8_t sd_write_block(unsigned long block_address, unsigned char buffer[512]) { //unsigned int block_offset = (block_address*512) & 0x01FF; //block_address = (block_address*512) - block_offset; block_address *= 512; if(sd_raw_locked()) return 0; /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } /* send start byte */ sd_raw_send_byte(0xfe); /* write byte block */ uint16_t i; for(i = 0; i < 512; i++) sd_raw_send_byte(buffer[i]); /* write dummy crc16 */ sd_raw_send_byte(0xff); sd_raw_send_byte(0xff); /* wait while card is busy */ while(sd_raw_rec_byte() != 0xff); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); return 1; }
uint8_t sd_read_block(unsigned long block_address, unsigned char buffer[512]) { //unsigned int block_offset = (block_address*512) & 0x01FF; //block_address = (block_address*512) - block_offset; block_address *= 512; if(sd_raw_locked()) return 0; /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } /* wait for data block (start byte 0xfe) */ while(sd_raw_rec_byte() != 0xfe); /* read byte block */ uint16_t i; for(i = 0; i < 512; i++) buffer[i] = sd_raw_rec_byte(); /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); return 1; }
int main(void) { struct sd_card card; int i; unsigned char buf[1024]; memset(buf, 0, 1024); if (mmchs_init(1)) { printf("Failed to initialize the host controller\n"); return 1; } if (card_goto_idle_state()) { printf("Failed to go into idle state\n"); return 1; } if (card_identification()) { printf("Failed to go card_identification\n"); return 1; } if (card_query_voltage_and_type(&card)) { printf("Failed to go card_query_voltage_and_type\n"); return 1; } if (card_identify(&card)) { printf("Failed to identify card\n"); return 1; } /* We have now initialized the hardware identified the card */ if (card_csd(&card)) { printf("failed to read csd (card specific data)\n"); return 1; } if (select_card(&card)) { printf("Failed to select card\n"); return 1; } if (read_single_block(&card, 0, buf)) { printf("Failed to read a single block\n"); return 1; } /* check signature */ if (!(buf[0x01fe] == 0x55 && buf[0x01ff] == 0xaa)) { printf("Failed to find MBR signature\n"); return 1; } for (i = 0; i < 512; i++) { buf[i] = i % 256; } if (read_single_block(&card, 0, buf)) { printf("Failed to read a single block\n"); return 1; } /* check signature */ if (!(buf[0x01fe] == 0x55 && buf[0x01ff] == 0xaa)) { printf("Failed to find MBR signature\n"); return 1; } /* DESCUCTIVE... */ for (i = 0; i < 512; i++) { buf[i] = i % 256; } if (write_single_block(&card, 0xfffff, buf)) { printf("Failed to write a single block\n"); return 1; } for (i = 0; i < 512; i++) { buf[i] = 0; } if (read_single_block(&card, 0xfffff, buf)) { printf("Failed to write a single block (check)\n"); return 1; } for (i = 0; i < 512; i++) { if (!buf[i] == i % 256) { printf("Failed to write a single block and read it again \n"); return 1; } } printf("Finished\n"); return 0; }
/** * \ingroup sd_raw * Reads informational data from the card. * * This function reads and returns the card's registers * containing manufacturing and status information. * * \note: The information retrieved by this function is * not required in any way to operate on the card, * but it might be nice to display some of the data * to the user. * * \param[in] info A pointer to the structure into which to save the information. * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_get_info(struct sd_raw_info* info) { if(!info || !sd_raw_available()) return 0; memset(info, 0, sizeof(*info)); select_card(); /* read cid register */ if(sd_raw_send_command(CMD_SEND_CID, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(uint8_t i = 0; i < 18; ++i) { 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; } } /* read csd register */ uint8_t csd_read_bl_len = 0; uint8_t csd_c_size_mult = 0; #if SD_RAW_SDHC uint16_t csd_c_size = 0; #else uint32_t csd_c_size = 0; #endif if(sd_raw_send_command(CMD_SEND_CSD, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(uint8_t i = 0; i < 18; ++i) { uint8_t b = sd_raw_rec_byte(); 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 SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { 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 #endif { 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; } } } }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ S0SPCCR = 150; /* Set frequency to 400kHz */ S0SPCR = 0x38; /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) return 0; /* card needs 74 cycles minimum to start up */ for(uint8_t i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); return 0; } } #if SD_RAW_SDHC /* check for version of SD card specification */ 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); } else #endif { /* 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 */ } } /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif 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_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { 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)) { unselect_card(); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ S0SPCCR = 60; /* ~1MHz-- potentially can be faster */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif return 1; }
/** * \ingroup sd_raw * Reads informational data from the card. * * This function reads and returns the card's registers * containing manufacturing and status information. * * \note: The information retrieved by this function is * not required in any way to operate on the card, * but it might be nice to display some of the data * to the user. * * \param[in] info A pointer to the structure into which to save the information. * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_get_info(struct sd_raw_info* info) { if(!info || !sd_raw_available()) return 0; memset(info, 0, sizeof(*info)); select_card(); /* read cid register */ if(sd_raw_send_command(CMD_SEND_CID, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(uint8_t i = 0; i < 18; ++i) { 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; } } /* read csd register */ uint8_t csd_read_bl_len = 0; uint8_t csd_c_size_mult = 0; #if SD_RAW_SDHC uint16_t csd_c_size = 0; #else uint32_t csd_c_size = 0; #endif uint8_t csd_structure = 0; if(sd_raw_send_command(CMD_SEND_CSD, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(uint8_t i = 0; i < 18; ++i) { uint8_t b = sd_raw_rec_byte(); if(i == 0) { csd_structure = b >> 6; } else if(i == 14)
/** * \ingroup sd_raw_read_block * Reads block of raw data from the card. * * \param[in] block_address the address of the block to read * \param[in] block_offset The offset from which to read. * \param[out] raw_buffer The buffer into which to write the data. * \param[in] read_length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read_block(offset_t block_address, offset_t block_offset, uint8_t* raw_buffer, uintptr_t read_length) { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } uint16_t tries = 0; /* wait for data block (start byte 0xfe) */ while((sd_raw_rec_byte() != 0xfe)){ if(tries >= 0x7FFF){ unselect_card(); return 0; } tries++; } #if SD_RAW_SAVE_RAM /* 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; } #else /* read byte block */ // uint8_t* cache = raw_block; uint8_t* cache = raw_buffer; for(uint16_t i = 0; i < 512; ++i) *cache++ = sd_raw_rec_byte(); #endif /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); return 1; }
/** * \ingroup sd_raw * Reads informational data from the card. * * This function reads and returns the card's registers * containing manufacturing and status information. * * \note: The information retrieved by this function is * not required in any way to operate on the card, * but it might be nice to display some of the data * to the user. * * \param[in] info A pointer to the structure into which to save the information. * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_get_info(struct sd_raw_info* info) { uint8_t i; if(!info || !sd_raw_available()) return 0; memset(info, 0, sizeof(*info)); select_card(); /* read cid register */ if(sd_raw_send_command_r1(CMD_SEND_CID, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(i = 0; i < 18; ++i) { 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; } } /* read csd register */ uint8_t csd_read_bl_len = 0; uint8_t csd_c_size_mult = 0; uint16_t csd_c_size = 0; if(sd_raw_send_command_r1(CMD_SEND_CSD, 0)) { unselect_card(); return 0; } while(sd_raw_rec_byte() != 0xfe); for(i = 0; i < 18; ++i) { uint8_t b = sd_raw_rec_byte(); switch(i) { case 5: csd_read_bl_len = b & 0x0f; break; case 6: csd_c_size = (uint16_t) (b & 0x03) << 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) << 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; case 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; break; } } unselect_card(); return 1; }
/** * \ingroup sd_raw * Continuously reads units of \c interval bytes and calls a callback function. * * This function starts reading at the specified offset. Every \c interval bytes, * it calls the callback function with the associated data buffer. * * By returning zero, the callback may stop reading. * * \note Within the callback function, you can not start another read or * write operation. * \note This function only works if the following conditions are met: * - (offset - (offset % 512)) % interval == 0 * - length % interval == 0 * * \param[in] offset Offset from which to start reading. * \param[in] buffer Pointer to a buffer which is at least interval bytes in size. * \param[in] interval Number of bytes to read before calling the callback function. * \param[in] length Number of bytes to read altogether. * \param[in] callback The function to call every interval bytes. * \param[in] p An opaque pointer directly passed to the callback function. * \returns 0 on failure, 1 on success * \see sd_raw_write_interval, sd_raw_read, sd_raw_write */ uint8_t sd_raw_read_interval(uint32_t offset, uint8_t* buffer, uint16_t interval, uint16_t length, sd_raw_read_interval_handler_t callback, void* p) { if(!buffer || interval == 0 || length < interval || !callback) return 0; #if !SD_RAW_SAVE_RAM while(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; } return 1; #else /* address card */ select_card(); uint16_t block_offset; uint16_t read_length; uint8_t* buffer_cur; uint8_t finished = 0; do { /* determine byte count to read at once */ block_offset = offset & 0x01ff; read_length = 512 - block_offset; /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, offset & 0xfffffe00)) { 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(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(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 & 0xfffffe00) + 512; } while(!finished); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); return 1; #endif }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init(bool use_crc, uint8_t speed) { #if !SD_POOR_DESIGN (void)speed; #endif #if !SD_RAW_SAVE_RAM sd_use_crc = use_crc; #else (void)use_crc; #endif sd_errno = 0; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_ss(); /* unselect SS as it may be CS for another SPI device */ unselect_card(); configure_pin_mosi(); configure_pin_sck(); configure_pin_miso(); /* 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); SPSR = 0; // &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) { sd_errno = SDR_ERR_NOCARD; return 0; } /* card needs 74 cycles minimum to start up with SS/CS high */ for(uint8_t i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* now lower CS */ select_card(); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if !SD_RAW_SAVE_RAM if ( sd_use_crc ) { if ( sd_raw_send_command(CMD_CRC_ON_OFF, 1) != (1 << R1_IDLE_STATE) ) { unselect_card(); sd_errno = SDR_ERR_CRC; return 0; } } #endif #if SD_RAW_SDHC /* check for version of SD card specification */ 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) { sd_errno = SDR_ERR_VOLTAGE; return 0; /* card operation voltage range doesn't match */ } if(sd_raw_rec_byte() != 0xaa) { sd_errno = SDR_ERR_PATTERN; return 0; /* wrong test pattern */ } /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* 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 */ } } /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif 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 == 0x1ff) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { if(sd_raw_send_command(CMD_READ_OCR, 0)) { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; 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)) { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ #if SD_POOR_DESIGN switch(speed) { /* f_OSC / 2 */ case 0: SPCR &= ~((1 << SPR1) | (1 << SPR0)); SPSR |= (1 << SPI2X); break; /* f_OSC / 4 */ case 1: SPCR &= ~((1 << SPR1) | (1 << SPR0)); SPSR &= ~(1 << SPI2X); break; /* f_OSC / 8 */ case 2: SPCR |= (1 << SPR0); SPCR &= ~(1 << SPR1); SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 16 */ case 3: SPCR |= (1 << SPR0); SPCR &= ~(1 << SPR1); SPSR &= ~(1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 32 */ case 4: SPCR &= ~(1 << SPR0); SPCR |= (1 << SPR1); SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 64 [two ways of achieving] */ case 5: SPCR &= ~(1 << SPR0); SPCR |= (1 << SPR1); SPSR &= ~(1 << SPI2X); break; /* f_OSC / 128 */ case 6: SPCR |= (1 << SPR1) | (1 << SPR0); SPSR &= ~(1 << SPI2X); break; default: sd_errno = SDR_ERR_COMMS; return 0; } #else // MBI used to use f_OSC / 2 // But owing to the lousy SD card bus, that doesn't work well // Then with the introduction of the revH MightyBoard, they dropped // down to f_OSC / 16. // / * f_OSC / 2 */ // SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ // SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ /* f_OSC / 16 */ SPCR |= ( 1 << SPR0 ); SPCR &= ~( 1 << SPR1 ); SPSR &= ~( 1 << SPI2X ); #endif #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif #if defined(DEBUG_SD) sd_errno = SDR_ERR_FOO; #endif // sd_errno set by sd_raw_read return 1; }
int mmc_read_sectors(IF_MD2(int drive,) unsigned long start, int incount, void* inbuf) { int rc = 0; int lastblock = 0; unsigned long end_block; tCardInfo *card; #ifndef HAVE_MULTIDRIVE int drive = current_card; #endif card = &card_info[drive]; rc = select_card(drive); if (rc) { rc = rc * 10 - 1; goto error; } end_block = start + incount; if (end_block > card->numblocks) { rc = -2; goto error; } /* Some cards don't like reading the very last block with * CMD_READ_MULTIPLE_BLOCK, so make sure this block is always
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init(void) { _sd_infodirty = 1; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* 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); SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) { SD_DEBUG("SD card not available"); return 0; } /* card needs 74 cycles minimum to start up */ uint16_t i; for(i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ uint8_t response; for(i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } } #if SD_RAW_SDHC /* check for version of SD card specification */ 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) { SD_DEBUG("Bad voltage"); return 0; /* card operation voltage range doesn't match */ } if(sd_raw_rec_byte() != 0xaa) { SD_DEBUG("Bad test pattern."); return 0; /* wrong test pattern */ } /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* 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 */ } } /* wait for card to get ready */ for(i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif 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(); SD_DEBUG("Some kind of error."); return 0; } } #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { if(sd_raw_send_command(CMD_READ_OCR, 0)) { unselect_card(); SD_DEBUG("Some kind of error."); 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)) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (unsigned long) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) { SD_DEBUG("Some kind of error."); return 0; } #endif return 1; }
/** * \ingroup sd_raw * Writes raw data to the card. * * \note If write buffering is enabled, you might have to * call sd_raw_sync() before disconnecting the card * to ensure all remaining data has been written. * * \param[in] offset The offset where to start writing. * \param[in] buffer The buffer containing the data to be written. * \param[in] length The number of bytes to write. * \returns 0 on failure, 1 on success. * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval */ uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t length) { #if SD_RAW_WRITE_SUPPORT if(get_pin_locked()) return 0; uint32_t block_address; uint16_t block_offset; uint16_t write_length; while(length > 0) { /* determine byte count to write at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; 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 SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif 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 SD_RAW_WRITE_BUFFERING raw_block_written = 0; if(length == write_length) return 1; #endif } /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_WRITE_SINGLE_BLOCK, block_address)) { unselect_card(); spi_rec_byte(); return 0; } /* send start byte */ spi_send_byte(0xfe); /* write byte block */ spi_send_data(raw_block, 512); /* write dummy crc16 */ spi_send_byte(0xff); spi_send_byte(0xff); /* wait while card is busy */ /* uint16_t i; for(i = 0; i < 0x7fff; ++i) { if(spi_rec_byte() == 0xff) break; } if(i >= 0x7fff) { unselect_card(); spi_rec_byte(); return 0; } */ // obiger code reicht bei langsamen Karten nicht aus! // daher nachfolgende alte Version mit endlos Warteschleife // Wil. while(spi_rec_byte() != 0xff); spi_rec_byte(); /* deaddress card */ unselect_card(); buffer += write_length; offset += write_length; length -= write_length; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif } return 1; #else return 0; #endif }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable output CS */ configure_pin_cs(); unselect_card(); /* initialization procedure */ if(!sd_raw_available()) return 0; /* wait for the card being powered up */ _delay_ms(10); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ spi_low_frequency(); /* card needs 74 cycles minimum to start up */ for(uint8_t i = 0; i < 32; ++i) { /* wait 8 clock cycles */ spi_rec_byte(); } /* address card */ select_card(); printf_P(PSTR("Card reset\n\r")); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); spi_rec_byte(); spi_high_frequency(); return 0; } } printf_P(PSTR("Card: wait\n\r")); /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { // ACMD41 für "dünne" und "normale" SD-Karten (wil) // response = sd_raw_send_command_r1(55, 0); // APP_CMD // response = sd_raw_send_command_r1(41, 0); // SD_SEND_OP_COND (keine 'high capacity') response = sd_raw_send_command_r1(1, 0); // CMD1 (for MMC) if(!(response & (1 << R1_IDLE_STATE))) break; if(i == 0x7fff) { unselect_card(); spi_rec_byte(); spi_high_frequency(); return 0; } } printf_P(PSTR("Card ready\n\r")); /* set block size to 512 bytes */ if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, 512)) { unselect_card(); spi_rec_byte(); spi_high_frequency(); return 0; } /* deaddress card */ unselect_card(); spi_rec_byte(); /* switch to highest SPI frequency possible */ spi_high_frequency(); #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = 0xffffffff; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif return 1; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { uint16_t i; uint8_t response; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* 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); SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ if(!sd_raw_available()) return 0; /* card needs 74 cycles minimum to start up */ for(i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ for(i = 0; ; ++i) { response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); return 0; } } /* wait for card to get ready */ for(i = 0; ; ++i) { response = sd_raw_send_command_r1(CMD_SEND_OP_COND, 0); if(!(response & (1 << R1_IDLE_STATE))) break; if(i == 0x7fff) { unselect_card(); return 0; } } /* set block size to 512 bytes */ if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, 512)) { unselect_card(); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = 0xffffffff; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif return 1; }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(uint32_t offset, uint8_t* buffer, uint16_t length) { uint32_t block_address; uint16_t block_offset; uint16_t read_length; uint16_t i; while(length > 0) { /* determine byte count to read at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!raw_block_written) { if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block))) return 0; } #endif /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, block_address)) { unselect_card(); return 0; } /* wait for data block (start byte 0xfe) */ i = 0; while(sd_raw_rec_byte() != 0xfe) { i++; if (i == 0) { unselect_card(); return 0; } } #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(i = 0; i < 512; ++i) { uint8_t b = sd_raw_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } #else /* read byte block */ uint8_t* cache = raw_block; for(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; #endif /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) { offset_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* 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; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } uint16_t tries = 0; /* wait for data block (start byte 0xfe) */ while((sd_raw_rec_byte() != 0xfe)){ if(tries >= 0x7FFF){ unselect_card(); return 0; } tries++; } #if SD_RAW_SAVE_RAM /* 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; } #else /* 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; #endif /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
/** * \ingroup sd_raw * Writes raw data to the card. * * \note If write buffering is enabled, you might have to * call sd_raw_sync() before disconnecting the card * to ensure all remaining data has been written. * * \param[in] offset The offset where to start writing. * \param[in] buffer The buffer containing the data to be written. * \param[in] length The number of bytes to write. * \returns 0 on failure, 1 on success. * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval */ uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t length) { #if SD_RAW_WRITE_SUPPORT if(get_pin_locked()) return 0; uint32_t block_address; uint16_t block_offset; uint16_t write_length; uint16_t i; while(length > 0) { /* determine byte count to write at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; 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 SD_RAW_WRITE_BUFFERING if(!raw_block_written) { if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block))) return 0; } #endif 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 SD_RAW_WRITE_BUFFERING raw_block_written = 0; if(length == write_length) return 1; #endif } buffer += write_length; /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_WRITE_SINGLE_BLOCK, block_address)) { unselect_card(); return 0; } /* send start byte */ sd_raw_send_byte(0xfe); /* write byte block */ uint8_t* cache = raw_block; for(i = 0; i < 512; ++i) sd_raw_send_byte(*cache++); /* write dummy crc16 */ sd_raw_send_byte(0xff); sd_raw_send_byte(0xff); /* wait while card is busy */ while(sd_raw_rec_byte() != 0xff); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); length -= write_length; offset += write_length; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif } return 1; #else return 0; #endif }
/** * \ingroup sd_raw * Writes raw data to the card. * * \note If write buffering is enabled, you might have to * call sd_raw_sync() before disconnecting the card * to ensure all remaining data has been written. * * \param[in] offset The offset where to start writing. * \param[in] buffer The buffer containing the data to be written. * \param[in] length The number of bytes to write. * \returns 0 on failure, 1 on success. * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval */ uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length) { if(sd_raw_locked()) return 0; offset_t block_address; uint16_t block_offset; uint16_t write_length; while(length > 0) { /* 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 SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif 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 SD_RAW_WRITE_BUFFERING raw_block_written = 0; if(length == write_length) return 1; #endif } /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } /* send start byte */ sd_raw_send_byte(0xfe); /* 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); uint16_t tries = 0; /* wait while card is busy */ while(sd_raw_rec_byte() != 0xff){ if(tries >= 0x7FFF){ unselect_card(); return 0; } tries++; } sd_raw_rec_byte(); /* deaddress card */ unselect_card(); buffer += write_length; offset += write_length; length -= write_length; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif } return 1; }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) { #if !SD_RAW_SAVE_RAM uint8_t attempts = 0; #endif offset_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* 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; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif read_block: /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; return 0; } /* wait for data block (start byte 0xfe) */ uint16_t tries = 0; while(sd_raw_rec_byte() != 0xfe) { if(tries++ >= 0x7FFF) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if SD_RAW_SAVE_RAM /* 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; } /* ignore crc bytes */ sd_raw_rec_byte(); sd_raw_rec_byte(); #else /* 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; /* read crc16 */ if ( sd_use_crc ) { uint16_t crc = sd_raw_rec_byte() << 8; crc |= sd_raw_rec_byte(); if ( crc != sd_crc16(raw_block, (uint16_t)512) ) { unselect_card(); if ( ++attempts < 5 ) { sd_raw_rec_byte(); // pause a little goto read_block; } sd_errno = SDR_ERR_CRC; return 0; } } else { /* ignore crc bytes */ sd_raw_rec_byte(); sd_raw_rec_byte(); } memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; #endif /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { /* Configure Chip-Select Pin*/ configure_pin_ss(); #if defined(AVRNETIO) && defined(AVRNETIO_ADDON) /* enable inputs for reading card status */ DDRD |= (1<<PD7); PORTD |= (1<<PD7); DDRD |= (1<<PD5); PORTD |= (1<<PD5); configure_pin_available(); // configure_pin_locked(); #elif defined(AVRNETIO) && !defined(AVRNETIO_ADDON) /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); configure_pin_available_pullup(); configure_pin_locked_pullup(); #endif /* unselect MMC-Card */ select_card(); unselect_card(); /* SPI-Bus Init */ SPI_init( spi_bus_num ); #if defined(AVRNETIO) && !defined(AVRNETIO_ADDON) /* Power up the MMC-Interface */ configure_power_up(); power_up(); #endif /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) { return 0; } /* card needs 74 cycles minimum to start up */ for(uint8_t i = 0; i < 100; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0xfff) { unselect_card(); return 0; } } #if SD_RAW_SDHC /* check for version of SD card specification */ 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) { unselect_card(); return 0; /* card operation voltage range doesn't match */ } if(sd_raw_rec_byte() != 0xaa) { unselect_card(); return 0; /* wrong test pattern */ } /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* 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 */ } } /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif 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_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { 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)) { unselect_card(); return 0; } /* deaddress card */ unselect_card(); // /* switch to highest SPI frequency possible */ // SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ // SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) { unselect_card(); return 0; } #endif return 1; }