bootloader: reinstate slow SD initialization
This commit is contained in:
parent
8ad34f1ab7
commit
c4d3756a18
@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes_bootldr
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c
|
||||
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c crc.c
|
||||
|
||||
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
|
||||
|
||||
@ -67,7 +67,7 @@ SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sd
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC = startup.S crc.S
|
||||
ASRC = startup.S
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "uart.h"
|
||||
#include "led.h"
|
||||
#include "sdnative.h"
|
||||
#include "fileops.h"
|
||||
#include "bits.h"
|
||||
|
||||
#define MAX_CARDS 1
|
||||
@ -152,6 +153,24 @@ static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void wiggle_slow_pos(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_slow_neg(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_pos(uint16_t times) {
|
||||
while(times--) {
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
@ -183,6 +202,77 @@ static inline void wait_busy(void) {
|
||||
wiggle_fast_neg(4);
|
||||
}
|
||||
|
||||
/*
|
||||
send_command_slow
|
||||
send SD command and put response in rsp.
|
||||
returns length of response or 0 if there was no response
|
||||
*/
|
||||
int send_command_slow(uint8_t* cmd, uint8_t* rsp){
|
||||
uint8_t shift, i=6;
|
||||
int rsplen;
|
||||
uint8_t cmdno = *cmd & 0x3f;
|
||||
wiggle_slow_pos(5);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 0:
|
||||
rsplen = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 9:
|
||||
case 10:
|
||||
rsplen = 17;
|
||||
break;
|
||||
default:
|
||||
rsplen = 6;
|
||||
}
|
||||
/* send command */
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
|
||||
while(i--) {
|
||||
shift = 8;
|
||||
do {
|
||||
shift--;
|
||||
uint8_t data = *cmd;
|
||||
*cmd<<=1;
|
||||
if(data&0x80) {
|
||||
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
|
||||
}
|
||||
wiggle_slow_pos(1);
|
||||
} while (shift);
|
||||
cmd++;
|
||||
}
|
||||
|
||||
wiggle_slow_pos(1);
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
|
||||
|
||||
if(rsplen) {
|
||||
uint16_t timeout=1000;
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
if(!timeout) {
|
||||
DBG_SD printf("CMD%d timed out\n", cmdno);
|
||||
return 0; /* no response within timeout */
|
||||
}
|
||||
|
||||
i=rsplen;
|
||||
while(i--) {
|
||||
shift = 8;
|
||||
uint8_t data=0;
|
||||
do {
|
||||
shift--;
|
||||
data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift;
|
||||
wiggle_slow_neg(1);
|
||||
} while (shift);
|
||||
*rsp=data;
|
||||
rsp++;
|
||||
}
|
||||
}
|
||||
return rsplen;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send_command_fast
|
||||
send SD command and put response in rsp.
|
||||
@ -381,6 +471,28 @@ static inline void make_crc7(uint8_t* cmd) {
|
||||
cmd[5]=(cmd[5] << 1) | 1;
|
||||
}
|
||||
|
||||
int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
cmdbuf[1] = param >> 24;
|
||||
cmdbuf[2] = param >> 16;
|
||||
cmdbuf[3] = param >> 8;
|
||||
cmdbuf[4] = param;
|
||||
if(!crc) {
|
||||
make_crc7(cmdbuf);
|
||||
} else {
|
||||
cmdbuf[5] = crc;
|
||||
}
|
||||
return send_command_slow(cmdbuf, rsp);
|
||||
}
|
||||
|
||||
int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) {
|
||||
return 0;
|
||||
}
|
||||
return cmd_slow(cmd, param, crc, dat, rsp);
|
||||
}
|
||||
|
||||
int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
@ -416,6 +528,7 @@ void stream_datablock(uint8_t *buf) {
|
||||
while(1) {
|
||||
datdata = SD_DAT << 4;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
datdata |= SD_DAT;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
@ -633,20 +746,20 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
for(rsplen=0; rsplen<2042; rsplen++) {
|
||||
if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
|
||||
DBG_SD printf("card seems to be sending data, attempting deselect\n");
|
||||
cmd_fast(SELECT_CARD, 0, 0, NULL, rsp);
|
||||
cmd_slow(SELECT_CARD, 0, 0, NULL, rsp);
|
||||
}
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
DBG_SD printf("sd_init start\n");
|
||||
cmd_fast(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
|
||||
cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
|
||||
|
||||
if((rsplen=cmd_fast(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
|
||||
if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
|
||||
DBG_SD printf("CMD8 response:\n");
|
||||
DBG_SD uart_trace(rsp, 0, rsplen);
|
||||
hcs=1;
|
||||
}
|
||||
while(1) {
|
||||
if(!(acmd_fast(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
|
||||
if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
|
||||
DBG_SD printf("ACMD41 no response!\n");
|
||||
}
|
||||
if(rsp[1]&0x80) break;
|
||||
@ -654,8 +767,8 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
|
||||
ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
|
||||
|
||||
cmd_fast(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
|
||||
if(cmd_fast(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
|
||||
cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
|
||||
if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
|
||||
rca=(rsp[1]<<24) | (rsp[2]<<16);
|
||||
DBG_SD printf("RCA: %04lx\n", rca>>16);
|
||||
} else {
|
||||
@ -664,23 +777,23 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
}
|
||||
|
||||
/* record CSD for getinfo */
|
||||
cmd_fast(SEND_CSD, rca, 0, NULL, rsp);
|
||||
cmd_slow(SEND_CSD, rca, 0, NULL, rsp);
|
||||
|
||||
/* select the card */
|
||||
if(cmd_fast(SELECT_CARD, rca, 0, NULL, rsp)) {
|
||||
if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) {
|
||||
DBG_SD printf("card selected!\n");
|
||||
} else {
|
||||
DBG_SD printf("CMD7 no response!\n");
|
||||
}
|
||||
|
||||
/* get card status */
|
||||
cmd_fast(SEND_STATUS, rca, 0, NULL, rsp);
|
||||
cmd_slow(SEND_STATUS, rca, 0, NULL, rsp);
|
||||
|
||||
/* set bus width */
|
||||
acmd_fast(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
|
||||
acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
|
||||
|
||||
/* set block length */
|
||||
cmd_fast(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
|
||||
cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
|
||||
|
||||
DBG_SD printf("SD init complete. SDHC/XC=%d\n", ccs);
|
||||
disk_state = DISK_OK;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user