Firmware: optimize non-sector-aligned SD DMA reads

This commit is contained in:
ikari 2012-01-14 01:13:36 +01:00
parent afc26397b1
commit b272a6fc1c
3 changed files with 58 additions and 16 deletions

View File

@ -47,9 +47,15 @@
s: Bit 2 = partial, Bit 1:0 = target
target: see above
60 sssseeee set SD DMA partial transfer start+end
ssss = start offset (msb first)
eeee = end offset (msb first)
60 xsssyeee set SD DMA partial transfer parameters
x: 0 = read from sector start (skip until
start offset reached)
8 = assume mid-sector position and read
immediately
sss = start offset (msb first)
y: 0 = skip rest of SD sector
8 = stop mid-sector if end offset reached
eee = end offset (msb first)
8p - read (RAM only)
p: 0 = no increment after read
@ -98,7 +104,7 @@
15 SD DMA busy (0=idle, 1=busy)
14 DAC read pointer MSB
13 MSU read pointer MSB
12 [TODO SD DMA CRC status (0=ok, 1=error); valid after bit 15 -> 0]
12 reserved (0)
11 reserved (0)
10 reserved (0)
9 reserved (0)
@ -239,7 +245,7 @@ void fpga_sddma(uint8_t tgt, uint8_t partial) {
}
DBG_SD printf("...complete\n");
FPGA_DESELECT();
if(test<5)printf("loopy: %ld %02x\n", test, status);
// if(test<5)printf("loopy: %ld %02x\n", test, status);
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
}

View File

@ -35,6 +35,8 @@ int i;
int sd_offload = 0, ff_sd_offload = 0, sd_offload_tgt = 0;
int sd_offload_partial = 0;
int sd_offload_start_mid = 0;
int sd_offload_end_mid = 0;
uint16_t sd_offload_partial_start = 0;
uint16_t sd_offload_partial_end = 0;

View File

@ -115,11 +115,12 @@ uint8_t cid[17];
uint8_t ccs=0;
uint32_t rca;
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE, TRANS_MID };
enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT };
int during_blocktrans = TRANS_NONE;
uint32_t last_block = 0;
uint16_t last_offset = 0;
volatile int sd_changed;
@ -395,7 +396,6 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
printf("CMD%d timed out\n", cmdno);
return 0; /* no response within timeout */
}
i=rsplen;
uint8_t cmddata=0, datdata=0;
while(i--) { /* process response */
@ -460,20 +460,31 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
state=CMD_DAT;
j=datcnt;
datshift=8;
timeout=2000000;
DBG_SD printf("response over, waiting for data...\n");
/* wait for data start bit on DAT0 */
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1();
}
//printf("%ld\n", timeout);
DBG_SD if(!timeout) printf("timed out!\n");
wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
if(sd_offload_partial) {
if(sd_offload_partial_start != 0) {
if(during_blocktrans == TRANS_MID) sd_offload_partial_start |= 0x8000;
}
if(sd_offload_partial_end != 512) {
sd_offload_partial_end |= 0x8000;
}
DBG_SD printf("new partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end);
fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end);
fpga_sddma(sd_offload_tgt, 1);
sd_offload_partial=0;
// sd_offload_partial=0;
last_offset=sd_offload_partial_end;
} else {
fpga_sddma(sd_offload_tgt, 0);
last_offset=0;
}
state=CMD_RSP;
return rsplen;
@ -597,17 +608,24 @@ int stream_datablock(uint8_t *buf) {
uint32_t timeout=1000000;
DBG_SD printf("stream_datablock: wait for ready...\n");
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1();
if(during_blocktrans != TRANS_MID) {
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1();
}
DBG_SD if(!timeout) printf("timeout!\n");
wiggle_fast_neg1(); /* eat the start bit */
}
DBG_SD if(!timeout) printf("timeout!\n");
wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
if(sd_offload_partial) {
if(sd_offload_partial_start != 0) {
if(during_blocktrans == TRANS_MID) sd_offload_partial_start |= 0x8000;
}
if(sd_offload_partial_end != 512) {
sd_offload_partial_end |= 0x8000;
}
DBG_SD printf("str partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end);
fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end);
fpga_sddma(sd_offload_tgt, 1);
sd_offload_partial=0;
} else {
fpga_sddma(sd_offload_tgt, 0);
}
@ -772,7 +790,21 @@ void read_block(uint32_t address, uint8_t *buf) {
#else
stream_datablock(buf);
#endif
last_block=address;
last_block = address;
last_offset = sd_offload_partial_end & 0x1ff;
if(sd_offload_partial && sd_offload_partial_end != 512) {
during_blocktrans = TRANS_MID;
}
sd_offload_partial = 0;
} else if (during_blocktrans == TRANS_MID
&& last_block == address
&& last_offset == sd_offload_partial_start
&& sd_offload_partial) {
stream_datablock(buf);
last_offset = sd_offload_partial_end & 0x1ff;
sd_offload_partial_start |= 0x8000;
during_blocktrans = TRANS_READ;
sd_offload_partial = 0;
} else {
if(during_blocktrans) {
// uart_putc('_');
@ -780,7 +812,7 @@ void read_block(uint32_t address, uint8_t *buf) {
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
}
last_block=address;
last_block = address;
if(!ccs) {
address <<= 9;
}
@ -792,8 +824,10 @@ void read_block(uint32_t address, uint8_t *buf) {
#else
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
#endif
sd_offload_partial = 0;
during_blocktrans = TRANS_READ;
}
// printf("trans state = %d\n", during_blocktrans);
}
void write_block(uint32_t address, uint8_t* buf) {