int sd_send_command(unsigned char cmd, uint32_t arg) { unsigned char n, res, *p; if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ cmd &= 0x7F; res = sd_send_command(CMD55, 0); if (res > 1) return res; } /* Select the card and wait for ready */ sd_spi_release(); /* raise CS, then sends 8 clocks (some cards require this) */ sd_spi_lower_cs(); if(sd_spi_wait(true) != 0xFF) return 0xFF; /* Send command packet */ sd_spi_transmit_byte(cmd); /* Start + Command index */ #if 0 sd_spi_transmit_byte((unsigned char)(arg >> 24)); /* Argument[31..24] */ sd_spi_transmit_byte((unsigned char)(arg >> 16)); /* Argument[23..16] */ sd_spi_transmit_byte((unsigned char)(arg >> 8)); /* Argument[15..8] */ sd_spi_transmit_byte((unsigned char)arg); /* Argument[7..0] */ #else /* sdcc sadly unable to figure this out for itself yet */ p = ((unsigned char *)&arg)+3; sd_spi_transmit_byte(*(p--)); /* Argument[31..24] */ sd_spi_transmit_byte(*(p--)); /* Argument[23..16] */ sd_spi_transmit_byte(*(p--)); /* Argument[15..8] */ sd_spi_transmit_byte(*p); /* Argument[7..0] */ #endif /* there's only a few commands (in native mode) that need correct CRCs */ n = 0x01; /* Dummy CRC + Stop */ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ sd_spi_transmit_byte(n); /* Receive command response */ if (cmd == CMD12) sd_spi_receive_byte(); /* Skip a stuff byte when stop reading */ n = 20; /* Wait for a valid response */ do { res = sd_spi_receive_byte(); } while ((res & 0x80) && --n); return res; /* Return with the response value */ }
uint8_t devsd_transfer_sector1(void) { uint8_t attempt; bool success; sd_drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK; for(attempt=0; attempt<8; attempt++){ if(sd_send_command(blk_op.is_read ? CMD17 : CMD24, /* for byte addressed cards, shift LBA to convert to byte address */ (blk_op.blkdev->driver_data & CT_BLOCK) ? blk_op.lba : (blk_op.lba << 9) ) == 0){ if(blk_op.is_read){ success = (sd_spi_wait(false) == 0xFE); if(success){ sd_spi_receive_sector(); //sd_spi_wait(false); } }else{ success = false; if(sd_spi_wait(true) == 0xFF){ sd_spi_transmit_byte(0xFE); sd_spi_transmit_sector(); sd_spi_transmit_byte(0xFF); /* dummy CRC */ sd_spi_transmit_byte(0xFF); success = ((sd_spi_wait(false) & 0x1F) == 0x05); } } }else success = false; sd_spi_release(); if(success) return 1; kputs("sd: failed, retrying.\n"); } udata.u_error = EIO; return 0; }