SD native write support (still needs error handling), DB creation update (display file sizes)

This commit is contained in:
ikari
2010-11-23 23:54:51 +01:00
parent b1a04c5f05
commit 561477ec53
14 changed files with 413 additions and 195 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -24,7 +24,6 @@
filetypes.c: directory scanning and file type detection
*/
#include <stdio.h>
#include <string.h>
#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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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; sec<count; sec++) {
write_block(sector+sec, buf);
buf+=512;
}
return RES_OK;
}
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write")));
/* Detect changes of SD card 0 */

View File

@@ -135,5 +135,5 @@ uint8_t menu_main_loop() {
void get_selected_name(uint8_t* fn) {
uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
printf("fd addr=%lx\n", addr);
sram_readblock(fn, addr+1+SRAM_MENU_ADDR, 256);
sram_readblock(fn, addr+10+SRAM_MENU_ADDR, 256);
}

View File

@@ -67,8 +67,8 @@ stat_getstring++;
/* is directory link, name offset 6 */
sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20);
} else {
/* is file link, name offset 65 */
sram_readblock(ptr, addr+1+SRAM_MENU_ADDR, 20);
/* is file link, name offset 10 */
sram_readblock(ptr, addr+10+SRAM_MENU_ADDR, 20);
}
ptr[20]=0;
}

167
src/spi.c
View File

@@ -36,174 +36,134 @@
#define SSP_RFF 3 // Receive FIFO full
#define SSP_BSY 4 // Busy
typedef struct {
LPC_SSP_TypeDef *SSP_REGS;
LPC_GPDMACH_TypeDef *SSP_DMACH;
uint32_t *SSP_PCLKREG;
int SSP_PCLKBIT;
int SSP_DMAID_TX;
int SSP_DMAID_RX;
} ssp_props;
static ssp_props SSP_SEL[2] = {
{ LPC_SSP0, LPC_GPDMACH0, (uint32_t*)&(LPC_SC->PCLKSEL1), 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 <length> 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);
}

View File

@@ -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

View File

@@ -7,6 +7,7 @@
#ifndef UART_H
#define UART_H
#include <stdio.h>
#include <stdint.h>
//#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

View File

@@ -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 {