From 561477ec53bdad901303075b38684215246a3e6d Mon Sep 17 00:00:00 2001 From: ikari Date: Tue, 23 Nov 2010 23:54:51 +0100 Subject: [PATCH] SD native write support (still needs error handling), DB creation update (display file sizes) --- src/Makefile | 2 +- src/config.h | 19 ++- src/ff.c | 1 + src/filetypes.c | 14 +- src/fpga_spi.c | 2 +- src/fpga_spi.h | 16 +-- src/main.c | 24 +++- src/sdnative.c | 335 ++++++++++++++++++++++++++++++++++++++++-------- src/snes.c | 2 +- src/sort.c | 4 +- src/spi.c | 167 +++++++++--------------- src/spi.h | 18 +-- src/uart.h | 2 + src/xmodem.c | 2 +- 14 files changed, 413 insertions(+), 195 deletions(-) diff --git a/src/Makefile b/src/Makefile index 82ef750..ce99315 100644 --- a/src/Makefile +++ b/src/Makefile @@ -73,7 +73,7 @@ ASRC = startup.S crc.S # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) # Use s -mcall-prologues when you really need size... #OPT = 2 -OPT = s +OPT = 2 # Debugging format. DEBUG = dwarf-2 diff --git a/src/config.h b/src/config.h index c538e18..a8f22e5 100644 --- a/src/config.h +++ b/src/config.h @@ -36,13 +36,11 @@ #define CONFIG_UART_BAUDRATE 921600 #define CONFIG_UART_DEADLOCKABLE -#define SPI_SD 1 -#define SPI_FPGA 0 +#define SSP_CLK_DIVISOR_FAST 4 +#define SSP_CLK_DIVISOR_SLOW 250 -#define SSP_CLK_DIVISOR_FAST 4 -#define SSP_CLK_DIVISOR_SLOW 250 #define SSP_CLK_DIVISOR_FPGA_FAST 6 -#define SSP_CLK_DIVISOR_FPGA_SLOW 16 +#define SSP_CLK_DIVISOR_FPGA_SLOW 20 #define SNES_RESET_REG LPC_GPIO1 #define SNES_RESET_BIT 29 @@ -62,4 +60,15 @@ #define QSORT_MAXELEM 1024 +#define SSP_REGS LPC_SSP0 +#define SSP_PCLKREG PCLKSEL1 +// 1: PCLKSEL0 +#define SSP_PCLKBIT 10 +// 1: 20 +#define SSP_DMAID_TX 0 +// 1: 2 +#define SSP_DMAID_RX 1 +// 1: 3 +#define SSP_DMACH LPC_GPDMACH0 + #endif diff --git a/src/ff.c b/src/ff.c index c3d69c4..80f0037 100644 --- a/src/ff.c +++ b/src/ff.c @@ -2174,6 +2174,7 @@ FRESULT f_read ( if (cc) { /* Read maximum contiguous sectors directly */ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ cc = fp->fs->csize - csect; +/* XXX OFFLOAD GOES HERE */ if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ diff --git a/src/filetypes.c b/src/filetypes.c index a66001e..0eb43d1 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -24,7 +24,6 @@ filetypes.c: directory scanning and file type detection */ -#include #include #include "config.h" #include "uart.h" @@ -71,6 +70,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) { uint16_t numentries; uint32_t dirsize; uint8_t pass = 0; + char buf[10]; dir_tgt = this_dir_tgt; if(depth==0) { @@ -198,10 +198,12 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) { - file name - file size */ /* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */ - sram_writebyte(len+1, db_tgt); - sram_writeblock(path, db_tgt + sizeof(len), pathlen + 1); - sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1); - db_tgt += sizeof(len) + pathlen + sizeof(fno.fsize) + 1; + snprintf(buf, sizeof(buf), " % 7ldk", fno.fsize/1024); + sram_writeblock(buf, db_tgt, sizeof(buf)-1); + sram_writebyte(len+1, db_tgt + sizeof(buf)-1); + sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1); +// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1); + db_tgt += sizeof(len) + pathlen + sizeof(buf)-1 + 1; break; case TYPE_UNKNOWN: default: @@ -224,7 +226,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) { } } else uart_putc(0x30+res); } - printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end); +// printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end); sram_writelong(db_tgt, SRAM_DB_ADDR+4); sram_writelong(dir_end, SRAM_DB_ADDR+8); return crc; diff --git a/src/fpga_spi.c b/src/fpga_spi.c index 8058523..586c018 100644 --- a/src/fpga_spi.c +++ b/src/fpga_spi.c @@ -52,7 +52,7 @@ #include "timer.h" void fpga_spi_init(void) { - spi_init(SPI_SPEED_FPGA_FAST, SPI_FPGA); + spi_init(SPI_SPEED_FPGA_FAST); } void set_mcu_addr(uint32_t address) { diff --git a/src/fpga_spi.h b/src/fpga_spi.h index 9fcb508..12fbd89 100644 --- a/src/fpga_spi.h +++ b/src/fpga_spi.h @@ -36,15 +36,15 @@ #define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) #define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) -#define FPGA_TX_SYNC() spi_tx_sync(SPI_FPGA) -#define FPGA_TX_BYTE(x) spi_tx_byte(x, SPI_FPGA) -#define FPGA_RX_BYTE() spi_rx_byte(SPI_FPGA) -#define FPGA_TXRX_BYTE(x) spi_txrx_byte(x, SPI_FPGA) -#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y,SPI_FPGA) -#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y,SPI_FPGA) +#define FPGA_TX_SYNC() spi_tx_sync() +#define FPGA_TX_BYTE(x) spi_tx_byte(x) +#define FPGA_RX_BYTE() spi_rx_byte() +#define FPGA_TXRX_BYTE(x) spi_txrx_byte(x) +#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y) +#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y) -#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST, SPI_FPGA) -#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW, SPI_FPGA) +#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST) +#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW) void fpga_spi_init(void); void fpga_spi_test(void); diff --git a/src/main.c b/src/main.c index bb3b9d2..9071a5f 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,6 @@ #include "ff.h" #include "diskio.h" #include "spi.h" -#include "sdcard.h" #include "fileops.h" #include "fpga.h" #include "fpga_spi.h" @@ -23,6 +22,7 @@ #include "tests.h" #include "cli.h" #include "sdnative.h" +#include "crc.h" #define EMC0TOGGLE (3<<4) #define MR0R (1<<1) @@ -54,15 +54,13 @@ int main(void) { timer_init(); uart_init(); fpga_spi_init(); - spi_preinit(SPI_FPGA); - spi_preinit(SPI_SD); + spi_preinit(); /* do this last because the peripheral init()s change PCLK dividers */ clock_init(); // sd_init(); sdn_init(); // while(1); - fpga_spi_init(); delay_ms(10); printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY); @@ -105,6 +103,16 @@ restart: uint32_t mem_dir_id = sram_readlong(SRAM_DIRID); uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); +/* printf("savetest..."); + int i; + uint16_t testcrc = 0; + for(i=0; i<128; i++) { + testcrc = crc_xmodem_update(testcrc, 0xff); + } + printf("testcrc = %04x\n", testcrc); + save_sram((uint8_t*)"/pretty long filename here you know.bin", 0x400000, SRAM_DB_ADDR); + printf("it's over!\n"); + while(1)cli_entrycheck(); */ printf("mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id); mem_magic=0x12938712; /* always rescan card for now */ if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) { @@ -142,7 +150,6 @@ restart: load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR); load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); } - /* load menu */ uart_putc('('); load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR); @@ -161,19 +168,23 @@ restart: snes_reset(0); uint8_t cmd = 0; + uint32_t filesize=0; printf("test sram\n"); while(!sram_reliable()); printf("ok\n"); sram_hexdump(SRAM_DB_ADDR, 0x200); + while(!cmd) { cmd=menu_main_loop(); + printf("derp %d\n", cmd); sleep_ms(50); + uart_putc('-'); switch(cmd) { case SNES_CMD_LOADROM: get_selected_name(file_lfn); set_mcu_ovr(1); printf("Selected name: %s\n", file_lfn); - load_rom(file_lfn, SRAM_ROM_ADDR); + filesize = load_rom(file_lfn, SRAM_ROM_ADDR); if(romprops.ramsize_bytes) { strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm"); printf("SRM file: %s\n", file_lfn); @@ -181,6 +192,7 @@ sram_hexdump(SRAM_DB_ADDR, 0x200); } else { printf("No SRAM\n"); } +save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR); set_mcu_ovr(0); snes_reset(1); delay_ms(100); diff --git a/src/sdnative.c b/src/sdnative.c index 3f8c809..d27ee3d 100644 --- a/src/sdnative.c +++ b/src/sdnative.c @@ -120,7 +120,10 @@ uint8_t csd[17]; uint8_t ccs=0; uint8_t rca1, rca2; -int during_blocktrans = 0; +enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE }; +enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT }; + +int during_blocktrans = TRANS_NONE; uint32_t last_block = 0; /** @@ -161,18 +164,18 @@ static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) { static inline void wiggle_slow_pos(uint16_t times) { while(times--) { - delay_us(5); + delay_us(2); BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - delay_us(5); + delay_us(2); BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; } } static inline void wiggle_slow_neg(uint16_t times) { while(times--) { - delay_us(5); + delay_us(2); BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - delay_us(5); + delay_us(2); BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; } } @@ -191,6 +194,18 @@ static inline void wiggle_fast_neg(uint16_t times) { } } +static inline void wiggle_fast_neg1(void) { + BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; + BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; +} + +static inline void wiggle_fast_pos1(void) { + BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; + BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; +} + + + /* send_command_slow @@ -272,10 +287,10 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){ */ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ uint8_t datshift=8, cmdshift, i=6; - int rsplen, dat=0, datcnt=512, j=0; - static int state=0; + int rsplen, dat=0, waitbusy=0, datcnt=512, j=0; + static int state=CMD_RSP; // printf("send_command_fast: sending CMD:\n"); - wiggle_fast_pos(5); + wiggle_fast_pos(9); // uart_trace(cmd, 0, 6); switch(*cmd & 0x3f) { case 0: @@ -286,15 +301,18 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ case 10: rsplen = 17; break; + case 12: + rsplen = 6; + waitbusy = 1; + break; case 17: case 18: dat = 1; default: rsplen = 6; } - if(dat && (buf==NULL)) { - printf("error: buf is null but data transfer expected.\n"); + printf("send_command_fast error: buf is null but data transfer expected.\n"); return 0; } /* send command */ @@ -311,7 +329,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ } else { BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; } - wiggle_fast_pos(1); + wiggle_fast_pos1(); } while (cmdshift); cmd++; } @@ -323,7 +341,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ uint16_t timeout=65535; /* wait for responsebob */ while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { - wiggle_fast_neg(1); + wiggle_fast_neg1(); } // printf("timeout=%d\n", timeout); if(!timeout) { @@ -339,13 +357,13 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { // printf("data start\n"); j=datcnt; - state=1; + state=CMD_RSPDAT; break; } } cmdshift--; cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; - wiggle_fast_neg(1); + wiggle_fast_neg1(); } while (cmdshift); if(state==1)break; *rsp=cmddata; @@ -353,7 +371,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ rsp++; } - if(state==1) { /* process response+data */ + if(state==CMD_RSPDAT) { /* process response+data */ int startbit=1; printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j); datshift=8; @@ -368,14 +386,15 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ i--; if(!i) { printf("response end\n"); - if(j) state=2; /* response over, remaining data */ + if(j) state=CMD_DAT; /* response over, remaining data */ break; } } if(!startbit) { - datshift--; - datdata |= (BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift; - + datshift-=4; + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift; if(!datshift) { datshift=8; *buf=datdata; @@ -386,42 +405,69 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ } } startbit=0; - wiggle_fast_neg(1); + wiggle_fast_neg1(); } } - if(dat && state!=2) { /* response ended before data */ - state=2; + if(dat && state != CMD_DAT) { /* response ended before data */ + state=CMD_DAT; j=datcnt; datshift=8; // printf("response over, waiting for data...\n"); while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg(1); + wiggle_fast_neg1(); } - wiggle_fast_neg(1); /* eat the start bit */ + wiggle_fast_neg1(); /* eat the start bit */ } - if(state==2) { /* transfer rest of data */ + if(state==CMD_DAT) { /* transfer rest of data */ // printf("remaining data: %d\n", j); - while(1) { - datshift-=4; - datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) - |((SD_DAT1REG->FIOPIN >> 13) & 0x6) - |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift; - if(!datshift) { - datshift=8; + if(datshift==8) { + while(1) { + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4; + wiggle_fast_neg1(); + + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)); + wiggle_fast_neg1(); + *buf=datdata; datdata=0; buf++; j--; if(!j) break; } - wiggle_fast_neg(1); + } else { + + while(1) { + datshift-=4; + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift; + if(!datshift) { + datshift=8; + *buf=datdata; + datdata=0; + buf++; + j--; + if(!j) break; + } + wiggle_fast_neg1(); + } } } /* just eat the crcs for now */ - wiggle_fast_neg(17); - state=3; + if(dat) wiggle_fast_neg(17); + + if(waitbusy) { + while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { + wiggle_fast_neg1(); + } + } + state=CMD_RSP; } return rsplen; } @@ -436,18 +482,19 @@ void make_crc7(uint8_t* cmd) { cmd[5]=(cmd[5] << 1) | 1; } -void stream_datablock(uint8_t* buf) { - uint8_t datshift=8; +void stream_datablock(uint8_t *buf) { +// uint8_t datshift=8; int j=512; uint8_t datdata=0; uint16_t timeout=65535; while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg(1); + wiggle_fast_neg1(); } - wiggle_fast_neg(1); /* eat the start bit */ + wiggle_fast_neg1(); /* eat the start bit */ while(1) { +/* datshift-=4; datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) |((SD_DAT1REG->FIOPIN >> 13) & 0x6) @@ -460,20 +507,164 @@ void stream_datablock(uint8_t* buf) { j--; if(!j) break; } - wiggle_fast_neg(1); +*/ + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4; + wiggle_fast_neg1(); + + datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) + |((SD_DAT1REG->FIOPIN >> 13) & 0x6) + |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)); + + wiggle_fast_neg1(); + + *buf=datdata; + datdata=0; + buf++; + j--; + if(!j) break; } /* eat the crc for now */ wiggle_fast_neg(17); } -void read_block(uint32_t address, uint8_t* buf) { - if(during_blocktrans && (last_block == address-1)) { +void send_datablock(uint8_t *buf) { + uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512; + uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift; +//uart_trace(buf, 0, 512); + wiggle_fast_pos(1); +// printf("send_datablock: wait for card\n"); + /* wait - card might be busy */ + while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { + wiggle_fast_neg(1); + printf("."); + } + BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1; + BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1; + BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1; + BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1; + + BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; + BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; + BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; + BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; + + wiggle_fast_pos(1); /* send start bit to card */ + crcshift=8; + while(cnt--) { + datshift=8; + do { + datshift-=4; + if(((*buf)>>datshift) & 0x8) { + BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + } else { + BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; + } + if(((*buf)>>datshift) & 0x4) { + BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; + } else { + BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; + } + if(((*buf)>>datshift) & 0x2){ + BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; + } else { + BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; + } + if(((*buf)>>datshift) & 0x1){ + BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; + } else { + BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; + } + wiggle_fast_pos(1); + } while (datshift); + + crcshift-=2; + dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift; + dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift; + dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift; + dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift; + if(!crcshift) { + crc0 = crc_xmodem_update(crc0, dat0); + crc1 = crc_xmodem_update(crc1, dat1); + crc2 = crc_xmodem_update(crc2, dat2); + crc3 = crc_xmodem_update(crc3, dat3); + crcshift=8; + dat0=0; + dat1=0; + dat2=0; + dat3=0; + } + buf++; + } +// printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3); + /* send crcs */ + datshift=16; + do { + datshift--; + if((crc0 >> datshift)&1) { + BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; + } else { + BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; + } + if((crc1 >> datshift)&1) { + BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; + } else { + BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; + } + if((crc2 >> datshift)&1) { + BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; + } else { + BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; + } + if((crc3 >> datshift)&1) { + BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + } else { + BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; + } + wiggle_fast_pos(1); + } while(datshift); + /* send end bit */ + BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; + BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; + BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; + BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + + wiggle_fast_pos(1); + + BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; + BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; + BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; + BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; + + wiggle_fast_neg(4); + dat0=0; + + datshift=3; + do { + datshift--; + dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift); + wiggle_fast_neg(1); + } while (datshift); + + if(dat0!=2) { + printf("crc error! %02x\n", dat0); + while(1); + } + wiggle_fast_neg(1); + while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { + wiggle_fast_neg(1); + } +} + +void read_block(uint32_t address, uint8_t *buf) { + if(during_blocktrans == TRANS_READ && (last_block == address-1)) { stream_datablock(buf); last_block=address; } else { if(during_blocktrans) { - /* send STOP_TRANSMISSION */ + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ cmd[0]=0x40+STOP_TRANSMISSION; cmd[1]=0; cmd[2]=0; @@ -493,11 +684,40 @@ void read_block(uint32_t address, uint8_t* buf) { send_command_fast(cmd, rsp, buf); // uart_trace(cmd, 0, 6); // uart_trace(rsp, 0, rsplen); - during_blocktrans = 1; + during_blocktrans = TRANS_READ; } // uart_trace(buf, 0, 512); } +void write_block(uint32_t address, uint8_t* buf) { + if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) { + send_datablock(buf); + last_block=address; + } else { + if(during_blocktrans) { + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ + cmd[0]=0x40+STOP_TRANSMISSION; + cmd[1]=0; + cmd[2]=0; + cmd[3]=0; + cmd[4]=0; + cmd[5]=0x61; + send_command_fast(cmd, rsp, NULL); + } + last_block=address; + if(!ccs) address <<= 9; + cmd[0]=0x40+WRITE_MULTIPLE_BLOCK; + cmd[1]=address>>24; + cmd[2]=address>>16; + cmd[3]=address>>8; + cmd[4]=address; + make_crc7(cmd); + send_command_fast(cmd, rsp, NULL); /* only send cmd & get response */ + send_datablock(buf); + during_blocktrans = TRANS_WRITE; + } +} + // // Public functions // @@ -520,15 +740,14 @@ DRESULT sdn_initialize(BYTE drv) { uint8_t cmd[6]={0,0,0,0,0,0}; /* command */ uint8_t rsp[17]; /* space for response */ int rsplen; - uint8_t hcs=0, data; + uint8_t hcs=0; if(drv>=MAX_CARDS) return STA_NOINIT|STA_NODISK; - data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN); /* if the card is sending data from before a reset we try to deselect it prior to initialization */ - for(rsplen=0; rsplen<1042; rsplen++) { - if((data != BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { + for(rsplen=0; rsplen<2042; rsplen++) { + if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) { printf("card seems to be sending data, attempting deselect\n"); cmd[0]=0x40+7; cmd[1]=0; @@ -542,7 +761,6 @@ DRESULT sdn_initialize(BYTE drv) { printf("CMD7 deselect no response! D:\n"); } } - data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN); wiggle_slow_neg(1); } cmd[0]=0x40+GO_IDLE_STATE; @@ -638,6 +856,7 @@ DRESULT sdn_initialize(BYTE drv) { cmd[4]=0; make_crc7(cmd); + /* record CSD for getinfo */ if((rsplen=send_command_slow(cmd, csd))) { // printf("CMD9 response:\n"); // uart_trace(rsp, 0, rsplen); @@ -652,6 +871,7 @@ DRESULT sdn_initialize(BYTE drv) { cmd[4]=0; make_crc7(cmd); + /* select the card */ if((rsplen=send_command_slow(cmd, rsp))) { // printf("CMD7 response:\n"); // uart_trace(rsp, 0, rsplen); @@ -667,6 +887,7 @@ DRESULT sdn_initialize(BYTE drv) { cmd[4]=0; make_crc7(cmd); + /* get card status */ if((rsplen=send_command_fast(cmd, rsp, NULL))) { // printf("CMD13 response:\n"); // uart_trace(rsp, 0, rsplen); @@ -674,6 +895,7 @@ DRESULT sdn_initialize(BYTE drv) { printf("CMD13 no response!\n"); } + /* set bus width */ cmd[0]=0x40+55; cmd[1]=rca1; cmd[2]=rca2; @@ -776,8 +998,21 @@ DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) { DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo"))); DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) { - return RES_OK; + uint8_t sec; + uint8_t *buf = (uint8_t*)buffer; + if(drv >= MAX_CARDS) { + return RES_NOTRDY; + } + if (sdn_status(drv) & STA_NODISK) + return RES_NOTRDY; + + for(sec=0; secPCLKSEL1), 10, 0, 1 }, /* SSP0 */ - { LPC_SSP1, LPC_GPDMACH1, (uint32_t*)&(LPC_SC->PCLKSEL0), 20, 2, 3 } /* SSP1 */ -}; - -void spi_preinit(int device) { - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); +void spi_preinit() { /* Set clock prescaler to 1:1 */ - BITBAND(*(ssp->SSP_PCLKREG), ssp->SSP_PCLKBIT) = 1; + BITBAND(LPC_SC->SSP_PCLKREG, SSP_PCLKBIT) = 1; } -void spi_init(spi_speed_t speed, int device) { - - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); +void spi_init(spi_speed_t speed) { /* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */ - ssp->SSP_REGS->CR0 = (8-1); + SSP_REGS->CR0 = (8-1); /* set clock prescaler */ if (speed == SPI_SPEED_FAST) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST; } else if (speed == SPI_SPEED_SLOW) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW; } else if (speed == SPI_SPEED_FPGA_FAST) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST; } else { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW; } /* Enable SSP */ - ssp->SSP_REGS->CR1 = BV(1); + SSP_REGS->CR1 = BV(1); /* Enable DMA controller, little-endian mode */ BITBAND(LPC_SC->PCONP, 29) = 1; LPC_GPDMA->DMACConfig = 1; } -void spi_tx_sync(int device) { - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - +void spi_tx_sync() { /* Wait until TX fifo is flushed */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ; + while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; } -void spi_tx_byte(uint8_t data, int device) { - - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - +void spi_tx_byte(uint8_t data) { /* Wait until TX fifo can accept data */ - while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ; + while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ; /* Send byte */ - ssp->SSP_REGS->DR = data; + SSP_REGS->DR = data; } -uint8_t spi_txrx_byte(uint8_t data, int device) { - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - +uint8_t spi_txrx_byte(uint8_t data) { /* Wait until SSP is not busy */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ; + while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; /* Clear RX fifo */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) - (void) ssp->SSP_REGS->DR; + while (BITBAND(SSP_REGS->SR, SSP_RNE)) + (void) SSP_REGS->DR; /* Transmit a single dummy byte */ - ssp->SSP_REGS->DR = data; + SSP_REGS->DR = data; /* Wait until answer has been received */ - while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ; + while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ; - return ssp->SSP_REGS->DR; + return SSP_REGS->DR; } -uint8_t spi_rx_byte(int device) { - - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - +uint8_t spi_rx_byte() { /* Wait until SSP is not busy */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ; + while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; /* Clear RX fifo */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) - (void) ssp->SSP_REGS->DR; + while (BITBAND(SSP_REGS->SR, SSP_RNE)) + (void) SSP_REGS->DR; /* Transmit a single dummy byte */ - ssp->SSP_REGS->DR = 0xff; + SSP_REGS->DR = 0xff; /* Wait until answer has been received */ - while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ; + while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ; - return ssp->SSP_REGS->DR; + return SSP_REGS->DR; } -void spi_tx_block(const void *ptr, unsigned int length, int device) { +void spi_tx_block(const void *ptr, unsigned int length) { const uint8_t *data = (const uint8_t *)ptr; - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - while (length--) { /* Wait until TX fifo can accept data */ - while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ; + while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ; - ssp->SSP_REGS->DR = *data++; + SSP_REGS->DR = *data++; } } -void spi_rx_block(void *ptr, unsigned int length, int device) { +void spi_rx_block(void *ptr, unsigned int length) { uint8_t *data = (uint8_t *)ptr; unsigned int txlen = length; - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - /* Wait until SSP is not busy */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ; + while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; /* Clear RX fifo */ - while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) - (void) ssp->SSP_REGS->DR; + while (BITBAND(SSP_REGS->SR, SSP_RNE)) + (void) SSP_REGS->DR; if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) { /* Odd length or unaligned buffer */ while (length > 0) { /* Wait until TX or RX FIFO are ready */ - while (txlen > 0 && !BITBAND(ssp->SSP_REGS->SR, SSP_TNF) && - !BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ; + while (txlen > 0 && !BITBAND(SSP_REGS->SR, SSP_TNF) && + !BITBAND(SSP_REGS->SR, SSP_RNE)) ; /* Try to receive data */ - while (length > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) { - *data++ = ssp->SSP_REGS->DR; + while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) { + *data++ = SSP_REGS->DR; length--; } /* Send dummy data until TX full or RX ready */ - while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF) && !BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) { + while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) { txlen--; - ssp->SSP_REGS->DR = 0xff; + SSP_REGS->DR = 0xff; } } } else { /* Clear interrupt flags of DMA channels 0 */ - LPC_GPDMA->DMACIntTCClear = BV(device); - LPC_GPDMA->DMACIntErrClr = BV(device); + LPC_GPDMA->DMACIntTCClear = BV(0); + LPC_GPDMA->DMACIntErrClr = BV(0); /* Set up RX DMA channel */ - ssp->SSP_DMACH->DMACCSrcAddr = (uint32_t)&ssp->SSP_REGS->DR; - ssp->SSP_DMACH->DMACCDestAddr = (uint32_t)ptr; - ssp->SSP_DMACH->DMACCLLI = 0; // no linked list - ssp->SSP_DMACH->DMACCControl = length + SSP_DMACH->DMACCSrcAddr = (uint32_t)&SSP_REGS->DR; + SSP_DMACH->DMACCDestAddr = (uint32_t)ptr; + SSP_DMACH->DMACCLLI = 0; // no linked list + SSP_DMACH->DMACCControl = length | (0 << 12) // source burst size 1 (FIXME: Check if larger possible/useful) | (0 << 15) // destination burst size 1 | (0 << 18) // source transfer width 1 byte @@ -211,52 +171,49 @@ void spi_rx_block(void *ptr, unsigned int length, int device) { | (0 << 26) // source address not incremented | (1 << 27) // destination address incremented ; - ssp->SSP_DMACH->DMACCConfig = 1 // enable channel - | (ssp->SSP_DMAID_RX << 1) // data source SSP RX + SSP_DMACH->DMACCConfig = 1 // enable channel + | (SSP_DMAID_RX << 1) // data source SSP RX | (2 << 11) // transfer from peripheral to memory ; /* Enable RX FIFO DMA */ - ssp->SSP_REGS->DMACR = 1; + SSP_REGS->DMACR = 1; /* Write bytes into TX FIFO */ // FIXME: Any value in doing this using DMA too? while (txlen > 0) { - while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) { + while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) { txlen--; - ssp->SSP_REGS->DR = 0xff; + SSP_REGS->DR = 0xff; } } /* Wait until DMA channel disables itself */ - while (ssp->SSP_DMACH->DMACCConfig & 1) ; + while (SSP_DMACH->DMACCConfig & 1) ; /* Disable RX FIFO DMA */ - ssp->SSP_REGS->DMACR = 0; + SSP_REGS->DMACR = 0; } } -void spi_set_speed(spi_speed_t speed, int device) { - /* select interface */ - ssp_props *ssp = &(SSP_SEL[device]); - +void spi_set_speed(spi_speed_t speed) { /* Wait until TX fifo is empty */ - while (!BITBAND(ssp->SSP_REGS->SR, 0)) ; + while (!BITBAND(SSP_REGS->SR, 0)) ; /* Disable SSP (FIXME: Is this required?) */ - ssp->SSP_REGS->CR1 = 0; + SSP_REGS->CR1 = 0; /* Change clock divisor */ if (speed == SPI_SPEED_FAST) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST; } else if (speed == SPI_SPEED_SLOW) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW; } else if (speed == SPI_SPEED_FPGA_FAST) { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST; } else { - ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW; + SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW; } /* Enable SSP */ - ssp->SSP_REGS->CR1 = BV(1); + SSP_REGS->CR1 = BV(1); } diff --git a/src/spi.h b/src/spi.h index 7bebac8..33203eb 100644 --- a/src/spi.h +++ b/src/spi.h @@ -33,30 +33,30 @@ typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FPGA_SLOW } spi_speed_t; /* Pre-Initialize SPI interface (PCLK divider before PLL setup) */ -void spi_preinit(int device); +void spi_preinit(void); /* Initialize SPI interface */ -void spi_init(spi_speed_t speed, int device); +void spi_init(spi_speed_t speed); /* Transmit a single byte */ -void spi_tx_byte(uint8_t data, int device); +void spi_tx_byte(uint8_t data); /* Transmit a single byte and return received data */ -uint8_t spi_txrx_byte(uint8_t data, int device); +uint8_t spi_txrx_byte(uint8_t data); /* Transmit a data block */ -void spi_tx_block(const void *data, unsigned int length, int device); +void spi_tx_block(const void *data, unsigned int length); /* Receive a single byte */ -uint8_t spi_rx_byte(int device); +uint8_t spi_rx_byte(void); /* Receive a data block */ -void spi_rx_block(void *data, unsigned int length, int device); +void spi_rx_block(void *data, unsigned int length); /* Switch speed of SPI interface */ -void spi_set_speed(spi_speed_t speed, int device); +void spi_set_speed(spi_speed_t speed); /* wait for SPI TX FIFO to become empty */ -void spi_tx_sync(int device); +void spi_tx_sync(void); #endif diff --git a/src/uart.h b/src/uart.h index 0fe1bef..32912de 100644 --- a/src/uart.h +++ b/src/uart.h @@ -7,6 +7,7 @@ #ifndef UART_H #define UART_H +#include #include //#ifdef CONFIG_UART_DEBUG @@ -28,6 +29,7 @@ void uart_puthex(uint8_t num); void uart_trace(void *ptr, uint16_t start, uint16_t len); void uart_flush(void); int printf(const char *fmt, ...); +int snprintf(char *str, size_t size, const char *format, ...); #define uart_putcrlf() uart_putc('\n') #else diff --git a/src/xmodem.c b/src/xmodem.c index e3e9ba8..9ce0cd1 100644 --- a/src/xmodem.c +++ b/src/xmodem.c @@ -20,7 +20,7 @@ void xmodem_rxfile(FIL* fil) { FRESULT res; uart_flush(); do { - sleep_ms(10000); + delay_ms(10000); uart_putc(ASC_NAK); } while (uart_getc() != ASC_SOH); do {