SD acceleration, display file size in menu (fw side)

This commit is contained in:
ikari 2010-12-04 02:19:36 +01:00
parent f4b88ca792
commit 4bc455f12b
19 changed files with 370 additions and 370 deletions

View File

@ -11,4 +11,11 @@
(bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \
))) )))
#define BITBAND_OFF(addr,offset,bit) \
(*((volatile unsigned long *)( \
(((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \
(bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \
)))
#endif #endif

View File

@ -1,6 +1,8 @@
#ifndef _CONFIG_H #ifndef _CONFIG_H
#define _CONFIG_H #define _CONFIG_H
// #define DEBUG_SD
#define VER "0.0.1(NSFW)" #define VER "0.0.1(NSFW)"
#define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define IN_AHBRAM __attribute__ ((section(".ahbram")))
@ -71,4 +73,22 @@
// 1: 3 // 1: 3
#define SSP_DMACH LPC_GPDMACH0 #define SSP_DMACH LPC_GPDMACH0
#define SD_CLKREG LPC_GPIO0
#define SD_CMDREG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO0
#define SD_DAT1REG LPC_GPIO1
#define SD_DAT2REG LPC_GPIO1
#define SD_DAT3REG LPC_GPIO0
#define SD_CLKPIN (7)
#define SD_CMDPIN (9)
#define SD_DAT0PIN (8)
#define SD_DAT1PIN (14)
#define SD_DAT2PIN (15)
#define SD_DAT3PIN (6)
#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
|((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
#endif #endif

View File

@ -62,6 +62,7 @@ void disk_init(void);
/* Will be set to DISK_ERROR if any access on the card fails */ /* Will be set to DISK_ERROR if any access on the card fails */
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR }; enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
extern int sd_offload, ff_sd_offload;
extern volatile enum diskstates disk_state; extern volatile enum diskstates disk_state;
/* Disk type - part of the external API except for ATA2! */ /* Disk type - part of the external API except for ATA2! */

View File

@ -2175,8 +2175,12 @@ FRESULT f_read (
if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
cc = fp->fs->csize - csect; cc = fp->fs->csize - csect;
/* XXX OFFLOAD GOES HERE */ /* XXX OFFLOAD GOES HERE */
if (ff_sd_offload) {
sd_offload = 1;
}
if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
ABORT(fp->fs, FR_DISK_ERR); ABORT(fp->fs, FR_DISK_ERR);
sd_offload = 0;
#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
#if _FS_TINY #if _FS_TINY
if (fp->fs->wflag && fp->fs->winsect - sect < cc) if (fp->fs->wflag && fp->fs->winsect - sect < cc)
@ -2214,7 +2218,7 @@ FRESULT f_read (
mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
#endif #endif
} }
ff_sd_offload = 0;
LEAVE_FF(fp->fs, FR_OK); LEAVE_FF(fp->fs, FR_OK);
} }

View File

@ -48,7 +48,7 @@
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */ #define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ /* To enable fast seek feature, set _USE_FASTSEEK to 1. */

View File

@ -61,6 +61,9 @@ UINT file_read() {
UINT file_write() { UINT file_write() {
UINT bytes_written; UINT bytes_written;
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written); file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
if(bytes_written < sizeof(file_buf)) {
printf("wrote less than expected - card full?\n");
}
return bytes_written; return bytes_written;
} }

View File

@ -70,7 +70,10 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
uint16_t numentries; uint16_t numentries;
uint32_t dirsize; uint32_t dirsize;
uint8_t pass = 0; uint8_t pass = 0;
char buf[10]; char buf[7];
char *size_units[3] = {" ", "k", "M"};
uint32_t entry_fsize;
uint8_t entry_unit_idx;
dir_tgt = this_dir_tgt; dir_tgt = this_dir_tgt;
if(depth==0) { if(depth==0) {
@ -185,7 +188,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
/* write element pointer to current dir structure */ /* write element pointer to current dir structure */
/* printf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt); */ /* printf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt); */
if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(fno.fsize) + 1))&0xffff)) { if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(buf)-1 + 1))&0xffff)) {
printf("switch! old=%lx ", db_tgt); printf("switch! old=%lx ", db_tgt);
db_tgt &= 0xffff0000; db_tgt &= 0xffff0000;
db_tgt += 0x00010000; db_tgt += 0x00010000;
@ -198,7 +201,14 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
- file name - file name
- file size */ - file size */
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */ /* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
snprintf(buf, sizeof(buf), " % 7ldk", fno.fsize/1024); entry_fsize = fno.fsize;
entry_unit_idx = 0;
while(entry_fsize > 9999) {
entry_fsize >>= 10;
entry_unit_idx++;
}
snprintf(buf, sizeof(buf), "% 5ld", entry_fsize);
strncat(buf, size_units[entry_unit_idx], 1);
sram_writeblock(buf, db_tgt, sizeof(buf)-1); sram_writeblock(buf, db_tgt, sizeof(buf)-1);
sram_writebyte(len+1, 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_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1);

View File

@ -97,11 +97,22 @@ void fpga_pgm(uint8_t* filename) {
int MAXRETRIES = 10; int MAXRETRIES = 10;
int retries = MAXRETRIES; int retries = MAXRETRIES;
uint8_t data; uint8_t data;
int i;
tick_t timeout;
// UINT bytes_read;
// uint16_t j;
do { do {
i=0;
timeout = getticks() + 100;
fpga_set_prog_b(0); fpga_set_prog_b(0);
uart_putc('P'); uart_putc('P');
fpga_set_prog_b(1); fpga_set_prog_b(1);
while(!fpga_get_initb()); while(!fpga_get_initb()){
if(getticks() > timeout) {
printf("no response from FPGA trying to initiate configuration!\n");
led_panic();
}
};
LPC_GPIO2->FIOMASK1 = ~(BV(0)); LPC_GPIO2->FIOMASK1 = ~(BV(0));
uart_putc('p'); uart_putc('p');
@ -114,13 +125,17 @@ void fpga_pgm(uint8_t* filename) {
return; return;
} }
uart_putc('C'); uart_putc('C');
for (;;) { for (;;) {
data = rle_file_getc(); data = rle_file_getc();
i++;
if (file_status || file_res) break; /* error or eof */ if (file_status || file_res) break; /* error or eof */
FPGA_SEND_BYTE_SERIAL(data); FPGA_SEND_BYTE_SERIAL(data);
} }
uart_putc('c'); uart_putc('c');
file_close(); file_close();
printf("fpga_pgm: %d bytes programmed\n", i);
delay_ms(1);
} while (!fpga_get_done() && retries--); } while (!fpga_get_done() && retries--);
if(!fpga_get_done()) { if(!fpga_get_done()) {
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES); printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);

View File

@ -35,7 +35,6 @@ void fpga_set_cclk(uint8_t val);
int fpga_get_initb(void); int fpga_get_initb(void);
void fpga_init(void); void fpga_init(void);
uint8_t fpga_test(void);
void fpga_postinit(void); void fpga_postinit(void);
void fpga_pgm(uint8_t* filename); void fpga_pgm(uint8_t* filename);

View File

@ -29,16 +29,19 @@
cmd param function cmd param function
============================================= =============================================
00 bb[hh[ll]] set address to 0xbb0000, 0xbbhh00, or 0xbbhhll 00 bbhhll set address to 0xbbhhll
10 bbhhll set SNES input address mask to 0xbbhhll 01 bbhhll set SNES input address mask to 0xbbhhll
20 bbhhll set SRAM address mask to 0xbbhhll 02 bbhhll set SRAM address mask to 0xbbhhll
3m - set mapper to m 3m - set mapper to m
0=HiROM, 1=LoROM, 2=ExHiROM, 7=Menu 0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu
40 - trigger SD DMA (512b from SD to memory)
80 - read with increment 80 - read with increment
81 - read w/o increment 81 - read w/o increment
90 {xx}* write xx with increment 90 {xx}* write xx with increment
91 {xx}* write xx w/o increment 91 {xx}* write xx w/o increment
Eu - set memory unit (u=0: "ROM"; u=1: SRAM)
F0 - receive test token (to see if FPGA is alive) F0 - receive test token (to see if FPGA is alive)
F1 - receive status
*/ */
@ -66,7 +69,7 @@ void set_mcu_addr(uint32_t address) {
void set_saveram_mask(uint32_t mask) { void set_saveram_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x20); FPGA_TX_BYTE(0x02);
FPGA_TX_BYTE((mask>>16)&0xff); FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff); FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff); FPGA_TX_BYTE((mask)&0xff);
@ -75,7 +78,7 @@ void set_saveram_mask(uint32_t mask) {
void set_rom_mask(uint32_t mask) { void set_rom_mask(uint32_t mask) {
FPGA_SELECT(); FPGA_SELECT();
FPGA_TX_BYTE(0x10); FPGA_TX_BYTE(0x01);
FPGA_TX_BYTE((mask>>16)&0xff); FPGA_TX_BYTE((mask>>16)&0xff);
FPGA_TX_BYTE((mask>>8)&0xff); FPGA_TX_BYTE((mask>>8)&0xff);
FPGA_TX_BYTE((mask)&0xff); FPGA_TX_BYTE((mask)&0xff);
@ -97,3 +100,25 @@ uint8_t fpga_test() {
return result; return result;
} }
uint8_t fpga_status() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
void fpga_sd2ram() {
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x40); /* DO DMA */
FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
while(FPGA_RX_BYTE() & 0x80);
FPGA_DESELECT();
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
}

View File

@ -47,7 +47,8 @@
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW) #define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW)
void fpga_spi_init(void); void fpga_spi_init(void);
void fpga_spi_test(void); uint8_t fpga_test(void);
uint8_t fpga_status(void);
void spi_fpga(void); void spi_fpga(void);
void spi_sd(void); void spi_sd(void);
void spi_none(void); void spi_none(void);
@ -55,5 +56,6 @@ void set_mcu_addr(uint32_t);
void set_saveram_mask(uint32_t); void set_saveram_mask(uint32_t);
void set_rom_mask(uint32_t); void set_rom_mask(uint32_t);
void set_mapper(uint8_t val); void set_mapper(uint8_t val);
void fpga_sd2ram(void);
#endif #endif

View File

@ -23,15 +23,19 @@
#include "cli.h" #include "cli.h"
#include "sdnative.h" #include "sdnative.h"
#include "crc.h" #include "crc.h"
#include "smc.h"
#define EMC0TOGGLE (3<<4) #define EMC0TOGGLE (3<<4)
#define MR0R (1<<1) #define MR0R (1<<1)
int i; int i;
int sd_offload = 0, ff_sd_offload = 0;
/* FIXME HACK */ /* FIXME HACK */
volatile enum diskstates disk_state; volatile enum diskstates disk_state;
extern volatile tick_t ticks; extern volatile tick_t ticks;
extern snes_romprops_t romprops;
int main(void) { int main(void) {
LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
LPC_GPIO1->FIODIR = 0; LPC_GPIO1->FIODIR = 0;
@ -58,25 +62,12 @@ int main(void) {
/* do this last because the peripheral init()s change PCLK dividers */ /* do this last because the peripheral init()s change PCLK dividers */
clock_init(); clock_init();
// sd_init();
sdn_init(); sdn_init();
// while(1);
fpga_spi_init(); fpga_spi_init();
delay_ms(10);
printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY); printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
file_init(); file_init();
cic_init(1); cic_init(1);
/* uart_putc('S');
for(p1=0; p1<8192; p1++) {
file_read();
}
file_close();
uart_putc('E');
uart_putcrlf();
printf("sizeof(struct FIL): %d\n", sizeof(file_handle));
uart_trace(file_buf, 0, 512);*/
/* setup timer (fpga clk) */ /* setup timer (fpga clk) */
LPC_TIM3->CTCR=0; LPC_TIM3->CTCR=0;
LPC_TIM3->EMR=EMC0TOGGLE; LPC_TIM3->EMR=EMC0TOGGLE;
@ -103,16 +94,6 @@ restart:
uint32_t mem_dir_id = sram_readlong(SRAM_DIRID); uint32_t mem_dir_id = sram_readlong(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); 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); 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 */ mem_magic=0x12938712; /* always rescan card for now */
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) { if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
@ -172,11 +153,12 @@ restart:
printf("test sram\n"); printf("test sram\n");
while(!sram_reliable()); while(!sram_reliable());
printf("ok\n"); printf("ok\n");
sram_hexdump(SRAM_DB_ADDR, 0x200); //sram_hexdump(SRAM_DB_ADDR, 0x200);
//sram_hexdump(SRAM_MENU_ADDR, 0x400);
while(!cmd) { while(!cmd) {
cmd=menu_main_loop(); cmd=menu_main_loop();
printf("derp %d\n", cmd); printf("cmd: %d\n", cmd);
sleep_ms(50); sleep_ms(50);
uart_putc('-'); uart_putc('-');
switch(cmd) { switch(cmd) {
@ -192,13 +174,13 @@ sram_hexdump(SRAM_DB_ADDR, 0x200);
} else { } else {
printf("No SRAM\n"); printf("No SRAM\n");
} }
save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR);
set_mcu_ovr(0); set_mcu_ovr(0);
snes_reset(1); snes_reset(1);
delay_ms(100); delay_ms(100);
snes_reset(0); snes_reset(0);
break; break;
case SNES_CMD_SETRTC: case SNES_CMD_SETRTC:
cmd=0; /* stay in loop */
break; break;
default: default:
printf("unknown cmd: %d\n", cmd); printf("unknown cmd: %d\n", cmd);
@ -230,18 +212,17 @@ save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR);
} }
} }
if(snes_reset_state) { if(snes_reset_state) {
delay_ms(10);
reset_count++; reset_count++;
} else { } else {
sram_reliable(); sram_reliable();
snes_main_loop(); snes_main_loop();
} }
if(reset_count>100) { if(reset_count>4) {
reset_count=0; reset_count=0;
set_mcu_ovr(1); set_mcu_ovr(1);
snes_reset(1); snes_reset(1);
delay_ms(100); delay_ms(100);
if(romprops.ramsize_bytes && fpga_test() == 0xa5) { if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
writeled(1); writeled(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
writeled(0); writeled(0);

View File

@ -39,9 +39,13 @@
#include "memory.h" #include "memory.h"
#include "snes.h" #include "snes.h"
#include "timer.h" #include "timer.h"
#include "rle.h"
#include "diskio.h"
char* hex = "0123456789ABCDEF"; char* hex = "0123456789ABCDEF";
extern snes_romprops_t romprops;
void sram_hexdump(uint32_t addr, uint32_t len) { void sram_hexdump(uint32_t addr, uint32_t len) {
static uint8_t buf[16]; static uint8_t buf[16];
uint32_t ptr; uint32_t ptr;
@ -162,25 +166,30 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
UINT bytes_read; UINT bytes_read;
DWORD filesize; DWORD filesize;
UINT count=0; UINT count=0;
tick_t tickstmp, ticksstart, ticks_read=0, ticks_tx=0, ticks_total=0;
ticksstart=getticks();
printf("%s\n", filename);
file_open(filename, FA_READ); file_open(filename, FA_READ);
filesize = file_handle.fsize;
smc_id(&romprops);
set_mcu_addr(base_addr);
printf("no nervous breakdown beyond this point! or else!\n");
if(file_res) { if(file_res) {
uart_putc('?'); uart_putc('?');
uart_putc(0x30+file_res); uart_putc(0x30+file_res);
return 0; return 0;
} }
filesize = file_handle.fsize;
smc_id(&romprops);
set_mcu_addr(base_addr);
printf("no nervous breakdown beyond this point! or else!\n");
f_lseek(&file_handle, romprops.offset); f_lseek(&file_handle, romprops.offset);
FPGA_DESELECT(); // FPGA_DESELECT();
FPGA_SELECT(); // FPGA_SELECT();
FPGA_TX_BYTE(0x91); /* write w/ increment */ // FPGA_TX_BYTE(0x91); /* write w/ increment */
for(;;) { for(;;) {
/* SPI_OFFLOAD=1; */ ff_sd_offload=1;
tickstmp=getticks();
bytes_read = file_read(); bytes_read = file_read();
ticks_read+=getticks()-tickstmp;
if (file_res || !bytes_read) break; if (file_res || !bytes_read) break;
if(!(count++ % 32)) { if(!(count++ % 512)) {
toggle_read_led(); toggle_read_led();
/* bounce_busy_led(); */ /* bounce_busy_led(); */
uart_putc('.'); uart_putc('.');
@ -188,14 +197,17 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
// for(int j=0; j<bytes_read; j++) { // for(int j=0; j<bytes_read; j++) {
// FPGA_TX_BYTE(file_buf[j]); // FPGA_TX_BYTE(file_buf[j]);
// } // }
FPGA_TX_BLOCK(file_buf, 512); //tickstmp = getticks();
// FPGA_TX_BLOCK(file_buf, 512);
//ticks_tx+=getticks()-tickstmp;
} }
FPGA_TX_BYTE(0x00); /* dummy tx for increment+write pulse */ // FPGA_TX_BYTE(0x00); /* dummy tx for increment+write pulse */
FPGA_DESELECT(); // FPGA_DESELECT();
file_close(); file_close();
set_mapper(romprops.mapper_id); set_mapper(romprops.mapper_id);
printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id); printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
ticks_total=getticks()-ticksstart;
printf("%u ticks in read, %u ticks in tx, %u ticks total\n", ticks_read, ticks_tx, ticks_total);
uint32_t rammask; uint32_t rammask;
uint32_t rommask; uint32_t rommask;
@ -212,7 +224,7 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask); printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
set_saveram_mask(rammask); set_saveram_mask(rammask);
set_rom_mask(rommask); set_rom_mask(rommask);
readled(0);
return (uint32_t)filesize; return (uint32_t)filesize;
} }
@ -238,6 +250,26 @@ uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
return (uint32_t)filesize; return (uint32_t)filesize;
} }
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
uint8_t data;
set_mcu_addr(base_addr);
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) return 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x91);
for(;;) {
data = rle_file_getc();
if (file_res || file_status) break;
FPGA_TX_BYTE(data);
}
FPGA_TX_BYTE(0x00); /* dummy tx */
FPGA_DESELECT();
file_close();
return (uint32_t)filesize;
}
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) { void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
uint32_t count = 0; uint32_t count = 0;
@ -318,3 +350,14 @@ uint8_t sram_reliable() {
rdyled(result); rdyled(result);
return result; return result;
} }
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
set_mcu_addr(base_addr);
FPGA_SELECT();
FPGA_TX_BYTE(0x91);
for(uint32_t i=0; i<len; i++) {
FPGA_TX_BYTE(val);
}
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}

View File

@ -45,6 +45,7 @@
uint32_t load_rom(uint8_t* filename, uint32_t base_addr); uint32_t load_rom(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram(uint8_t* filename, uint32_t base_addr); uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr);
void sram_hexdump(uint32_t addr, uint32_t len); void sram_hexdump(uint32_t addr, uint32_t len);
uint8_t sram_readbyte(uint32_t addr); uint8_t sram_readbyte(uint32_t addr);
uint16_t sram_readshort(uint32_t addr); uint16_t sram_readshort(uint32_t addr);
@ -58,6 +59,6 @@ void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr); void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr);
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size); uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable(void); uint8_t sram_reliable(void);
void sram_memset(uint32_t base_adde, uint32_t len, uint8_t val);
snes_romprops_t romprops;
#endif #endif

View File

@ -1,5 +1,4 @@
#include <arm/NXP/LPC17xx/LPC17xx.h> #include <arm/NXP/LPC17xx/LPC17xx.h>
#include <arm/bits.h>
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
#include "crc.h" #include "crc.h"
@ -10,13 +9,18 @@
#include "led.h" #include "led.h"
#include "sdnative.h" #include "sdnative.h"
#include "fileops.h" #include "fileops.h"
#include "bits.h"
#include "fpga_spi.h"
#define MAX_CARDS 1 #define MAX_CARDS 1
// SD/MMC commands // SD/MMC commands
#define GO_IDLE_STATE 0 #define GO_IDLE_STATE 0
#define SEND_OP_COND 1 #define SEND_OP_COND 1
#define ALL_SEND_CID 2
#define SEND_RELATIVE_ADDR 3
#define SWITCH_FUNC 6 #define SWITCH_FUNC 6
#define SELECT_CARD 7
#define SEND_IF_COND 8 #define SEND_IF_COND 8
#define SEND_CSD 9 #define SEND_CSD 9
#define SEND_CID 10 #define SEND_CID 10
@ -41,6 +45,7 @@
#define CRC_ON_OFF 59 #define CRC_ON_OFF 59
// SD ACMDs // SD ACMDs
#define SD_SET_BUS_WIDTH 6
#define SD_STATUS 13 #define SD_STATUS 13
#define SD_SEND_NUM_WR_BLOCKS 22 #define SD_SEND_NUM_WR_BLOCKS 22
#define SD_SET_WR_BLK_ERASE_COUNT 23 #define SD_SET_WR_BLK_ERASE_COUNT 23
@ -62,20 +67,6 @@
#define CARD_SD (1<<0) #define CARD_SD (1<<0)
#define CARD_SDHC (1<<1) #define CARD_SDHC (1<<1)
#define SD_CLKREG LPC_GPIO0
#define SD_CMDREG LPC_GPIO0
#define SD_DAT0REG LPC_GPIO0
#define SD_DAT1REG LPC_GPIO1
#define SD_DAT2REG LPC_GPIO1
#define SD_DAT3REG LPC_GPIO0
#define SD_CLKPIN (7)
#define SD_CMDPIN (9)
#define SD_DAT0PIN (8)
#define SD_DAT1PIN (14)
#define SD_DAT2PIN (15)
#define SD_DAT3PIN (6)
/* /*
1 DAT3/SS P0.6 1 DAT3/SS P0.6
2 CMD/DI P0.9 2 CMD/DI P0.9
@ -118,7 +109,7 @@ uint8_t cmd[6]={0,0,0,0,0,0};
uint8_t rsp[17]; uint8_t rsp[17];
uint8_t csd[17]; uint8_t csd[17];
uint8_t ccs=0; uint8_t ccs=0;
uint8_t rca1, rca2; uint32_t rca;
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE }; enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT }; enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT };
@ -204,8 +195,12 @@ static inline void wiggle_fast_pos1(void) {
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
} }
static inline void wait_busy(void) {
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
wiggle_fast_neg1();
}
wiggle_fast_neg(4);
}
/* /*
send_command_slow send_command_slow
@ -215,9 +210,8 @@ static inline void wiggle_fast_pos1(void) {
int send_command_slow(uint8_t* cmd, uint8_t* rsp){ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
uint8_t shift, i=6; uint8_t shift, i=6;
int rsplen; int rsplen;
// printf("send_command_slow: sending CMD:\n"); uint8_t cmdno = *cmd & 0x3f;
wiggle_slow_pos(5); wiggle_slow_pos(5);
// uart_trace(cmd, 0, 6);
switch(*cmd & 0x3f) { switch(*cmd & 0x3f) {
case 0: case 0:
rsplen = 0; rsplen = 0;
@ -254,12 +248,11 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
if(rsplen) { if(rsplen) {
uint16_t timeout=1000; uint16_t timeout=1000;
/* wait for responsebob */
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
wiggle_slow_neg(1); wiggle_slow_neg(1);
} }
// printf("timeout=%d\n", timeout);
if(!timeout) { if(!timeout) {
printf("CMD%d timed out\n", cmdno);
return 0; /* no response within timeout */ return 0; /* no response within timeout */
} }
@ -287,11 +280,11 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
*/ */
int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
uint8_t datshift=8, cmdshift, i=6; uint8_t datshift=8, cmdshift, i=6;
uint8_t cmdno = *cmd & 0x3f;
int rsplen, dat=0, waitbusy=0, datcnt=512, j=0; int rsplen, dat=0, waitbusy=0, datcnt=512, j=0;
static int state=CMD_RSP; static int state=CMD_RSP;
// printf("send_command_fast: sending CMD:\n"); wiggle_fast_pos(9); /* give the card >=8 cycles after last command */
wiggle_fast_pos(9); DBG_SD printf("send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
// uart_trace(cmd, 0, 6);
switch(*cmd & 0x3f) { switch(*cmd & 0x3f) {
case 0: case 0:
rsplen = 0; rsplen = 0;
@ -319,32 +312,32 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
while(i--) { while(i--) {
uint8_t data = *cmd;
cmdshift = 8; cmdshift = 8;
do { do {
cmdshift--; cmdshift--;
uint8_t data = *cmd;
*cmd<<=1;
if(data&0x80) { if(data&0x80) {
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1; BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
} else { } else {
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
} }
data<<=1;
wiggle_fast_pos1(); wiggle_fast_pos1();
} while (cmdshift); } while (cmdshift);
cmd++; cmd++;
} }
wiggle_fast_pos(1); wiggle_fast_pos1();
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0; BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
if(rsplen) { if(rsplen) {
uint16_t timeout=65535; uint32_t timeout=2000000;
/* wait for responsebob */ /* wait for response */
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
wiggle_fast_neg1(); wiggle_fast_neg1();
} }
// printf("timeout=%d\n", timeout);
if(!timeout) { if(!timeout) {
printf("CMD%d timed out\n", cmdno);
return 0; /* no response within timeout */ return 0; /* no response within timeout */
} }
@ -355,7 +348,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
do { do {
if(dat) { if(dat) {
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
// printf("data start\n"); DBG_SD printf("data start during response\n");
j=datcnt; j=datcnt;
state=CMD_RSPDAT; state=CMD_RSPDAT;
break; break;
@ -365,7 +358,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
wiggle_fast_neg1(); wiggle_fast_neg1();
} while (cmdshift); } while (cmdshift);
if(state==1)break; if(state==CMD_RSPDAT)break;
*rsp=cmddata; *rsp=cmddata;
cmddata=0; cmddata=0;
rsp++; rsp++;
@ -373,7 +366,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
if(state==CMD_RSPDAT) { /* process response+data */ if(state==CMD_RSPDAT) { /* process response+data */
int startbit=1; int startbit=1;
printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j); DBG_SD printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j);
datshift=8; datshift=8;
while(1) { while(1) {
cmdshift--; cmdshift--;
@ -385,16 +378,14 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
rsp++; rsp++;
i--; i--;
if(!i) { if(!i) {
printf("response end\n"); DBG_SD printf("response end\n");
if(j) state=CMD_DAT; /* response over, remaining data */ if(j) state=CMD_DAT; /* response over, remaining data */
break; break;
} }
} }
if(!startbit) { if(!startbit) {
datshift-=4; datshift-=4;
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) datdata |= SD_DAT << datshift;
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
if(!datshift) { if(!datshift) {
datshift=8; datshift=8;
*buf=datdata; *buf=datdata;
@ -413,25 +404,26 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
state=CMD_DAT; state=CMD_DAT;
j=datcnt; j=datcnt;
datshift=8; datshift=8;
// printf("response over, waiting for data...\n"); DBG_SD printf("response over, waiting for data...\n");
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1(); wiggle_fast_neg1();
} }
wiggle_fast_neg1(); /* eat the start bit */ wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
fpga_sd2ram();
state=CMD_RSP;
return rsplen;
}
} }
if(state==CMD_DAT) { /* transfer rest of data */ if(state==CMD_DAT) { /* transfer rest of data */
// printf("remaining data: %d\n", j); DBG_SD printf("remaining data: %d\n", j);
if(datshift==8) { if(datshift==8) {
while(1) { while(1) {
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) datdata |= SD_DAT << 4;
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4;
wiggle_fast_neg1(); wiggle_fast_neg1();
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) datdata |= SD_DAT;
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
wiggle_fast_neg1(); wiggle_fast_neg1();
*buf=datdata; *buf=datdata;
@ -444,9 +436,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
while(1) { while(1) {
datshift-=4; datshift-=4;
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) datdata |= SD_DAT << datshift;
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
if(!datshift) { if(!datshift) {
datshift=8; datshift=8;
*buf=datdata; *buf=datdata;
@ -463,17 +453,18 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
if(dat) wiggle_fast_neg(17); if(dat) wiggle_fast_neg(17);
if(waitbusy) { if(waitbusy) {
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { DBG_SD printf("waitbusy after send_cmd\n");
wiggle_fast_neg1(); wait_busy();
}
} }
state=CMD_RSP; state=CMD_RSP;
} }
rsp-=rsplen;
DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]);
return rsplen; return rsplen;
} }
void make_crc7(uint8_t* cmd) { static inline void make_crc7(uint8_t* cmd) {
cmd[5]=crc7update(0, cmd[0]); cmd[5]=crc7update(0, cmd[0]);
cmd[5]=crc7update(cmd[5], cmd[1]); cmd[5]=crc7update(cmd[5], cmd[1]);
cmd[5]=crc7update(cmd[5], cmd[2]); cmd[5]=crc7update(cmd[5], cmd[2]);
@ -482,65 +473,85 @@ void make_crc7(uint8_t* cmd) {
cmd[5]=(cmd[5] << 1) | 1; 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;
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_fast(cmdbuf, rsp, dat);
}
int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
if(!(cmd_fast(APP_CMD, rca, 0, NULL, rsp))) {
return 0;
}
return cmd_fast(cmd, param, crc, dat, rsp);
}
void stream_datablock(uint8_t *buf) { void stream_datablock(uint8_t *buf) {
// uint8_t datshift=8; // uint8_t datshift=8;
int j=512; int j=512;
uint8_t datdata=0; uint8_t datdata=0;
uint16_t timeout=65535; uint32_t timeout=1000000;
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg1(); wiggle_fast_neg1();
} }
wiggle_fast_neg1(); /* eat the start bit */ wiggle_fast_neg1(); /* eat the start bit */
if(sd_offload) {
fpga_sd2ram();
} else {
while(1) {
datdata = SD_DAT << 4;
wiggle_fast_neg1();
datdata |= SD_DAT;
wiggle_fast_neg1();
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; *buf=datdata;
datdata=0;
buf++; buf++;
j--; j--;
if(!j) break; if(!j) break;
} }
*/
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 */ /* eat the crc for now */
wiggle_fast_neg(17); wiggle_fast_neg(17);
}
} }
void send_datablock(uint8_t *buf) { void send_datablock(uint8_t *buf) {
uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512; uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512;
uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift; uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift;
//uart_trace(buf, 0, 512);
wiggle_fast_pos(1); wiggle_fast_pos1();
// 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_DAT0REG->FIODIR, SD_DAT0PIN) = 1;
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1; BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1;
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1; BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1;
@ -551,7 +562,7 @@ void send_datablock(uint8_t *buf) {
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
wiggle_fast_pos(1); /* send start bit to card */ wiggle_fast_pos1(); /* send start bit to card */
crcshift=8; crcshift=8;
while(cnt--) { while(cnt--) {
datshift=8; datshift=8;
@ -577,7 +588,7 @@ void send_datablock(uint8_t *buf) {
} else { } else {
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
} }
wiggle_fast_pos(1); wiggle_fast_pos1();
} while (datshift); } while (datshift);
crcshift-=2; crcshift-=2;
@ -603,27 +614,27 @@ void send_datablock(uint8_t *buf) {
datshift=16; datshift=16;
do { do {
datshift--; datshift--;
if((crc0 >> datshift)&1) { if((crc0 >> datshift) & 1) {
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
} else { } else {
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
} }
if((crc1 >> datshift)&1) { if((crc1 >> datshift) & 1) {
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
} else { } else {
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
} }
if((crc2 >> datshift)&1) { if((crc2 >> datshift) & 1) {
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
} else { } else {
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
} }
if((crc3 >> datshift)&1) { if((crc3 >> datshift) & 1) {
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
} else { } else {
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
} }
wiggle_fast_pos(1); wiggle_fast_pos1();
} while(datshift); } while(datshift);
/* send end bit */ /* send end bit */
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
@ -631,88 +642,73 @@ void send_datablock(uint8_t *buf) {
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
wiggle_fast_pos(1); wiggle_fast_pos1();
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
wiggle_fast_neg(4); wiggle_fast_neg(3);
dat0=0; dat0=0;
datshift=3; datshift=4;
do { do {
datshift--; datshift--;
dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift); dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift);
wiggle_fast_neg(1); wiggle_fast_neg1();
} while (datshift); } while (datshift);
DBG_SD printf("crc %02x\n", dat0);
if(dat0!=2) { if((dat0 & 7) != 2) {
printf("crc error! %02x\n", dat0); printf("crc error! %02x\n", dat0);
while(1); while(1);
} }
wiggle_fast_neg(1); if(dat0 & 8) {
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { printf("missing start bit in CRC status response...\n");
wiggle_fast_neg(1); }
} wiggle_fast_neg(2);
wait_busy();
} }
void read_block(uint32_t address, uint8_t *buf) { void read_block(uint32_t address, uint8_t *buf) {
if(during_blocktrans == TRANS_READ && (last_block == address-1)) { if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
//uart_putc('r');
stream_datablock(buf); stream_datablock(buf);
last_block=address; last_block=address;
} else { } else {
if(during_blocktrans) { if(during_blocktrans) {
//printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address);
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
cmd[0]=0x40+STOP_TRANSMISSION; cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
cmd[5]=0x61;
send_command_fast(cmd, rsp, NULL);
} }
last_block=address; last_block=address;
if(!ccs) address <<= 9; if(!ccs) {
cmd[0]=0x40+READ_MULTIPLE_BLOCK; address <<= 9;
cmd[1]=address>>24; }
cmd[2]=address>>16; cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
cmd[3]=address>>8;
cmd[4]=address;
make_crc7(cmd);
send_command_fast(cmd, rsp, buf);
// uart_trace(cmd, 0, 6);
// uart_trace(rsp, 0, rsplen);
during_blocktrans = TRANS_READ; during_blocktrans = TRANS_READ;
} }
// uart_trace(buf, 0, 512);
} }
void write_block(uint32_t address, uint8_t* buf) { void write_block(uint32_t address, uint8_t* buf) {
if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) { if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) {
wait_busy();
send_datablock(buf); send_datablock(buf);
last_block=address; last_block=address;
} else { } else {
if(during_blocktrans) { if(during_blocktrans) {
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
cmd[0]=0x40+STOP_TRANSMISSION; cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
cmd[5]=0x61;
send_command_fast(cmd, rsp, NULL);
} }
wait_busy();
last_block=address; last_block=address;
if(!ccs) address <<= 9; if(!ccs) {
cmd[0]=0x40+WRITE_MULTIPLE_BLOCK; address <<= 9;
cmd[1]=address>>24; }
cmd[2]=address>>16; /* only send cmd & get response */
cmd[3]=address>>8; cmd_fast(WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp);
cmd[4]=address; DBG_SD printf("write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]);
make_crc7(cmd); wiggle_fast_pos(8);
send_command_fast(cmd, rsp, NULL); /* only send cmd & get response */
send_datablock(buf); send_datablock(buf);
during_blocktrans = TRANS_WRITE; during_blocktrans = TRANS_WRITE;
} }
@ -737,200 +733,74 @@ DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) __attribute_
DRESULT sdn_initialize(BYTE drv) { DRESULT sdn_initialize(BYTE drv) {
uint8_t cmd[6]={0,0,0,0,0,0}; /* command */
uint8_t rsp[17]; /* space for response */ uint8_t rsp[17]; /* space for response */
int rsplen; int rsplen;
uint8_t hcs=0; uint8_t hcs=0;
if(drv>=MAX_CARDS) rca = 0;
if(drv>=MAX_CARDS) {
return STA_NOINIT|STA_NODISK; return STA_NOINIT|STA_NODISK;
}
if(sdn_status(drv) & STA_NODISK) {
return STA_NOINIT|STA_NODISK;
}
/* if the card is sending data from before a reset we try to deselect it /* if the card is sending data from before a reset we try to deselect it
prior to initialization */ prior to initialization */
for(rsplen=0; rsplen<2042; rsplen++) { for(rsplen=0; rsplen<2042; rsplen++) {
if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) { if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
printf("card seems to be sending data, attempting deselect\n"); printf("card seems to be sending data, attempting deselect\n");
cmd[0]=0x40+7; cmd_slow(SELECT_CARD, 0, 0, NULL, rsp);
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
if(send_command_slow(cmd, rsp)) {
printf("card was sending data, CMD7 succeeded\n");
} else {
printf("CMD7 deselect no response! D:\n");
}
} }
wiggle_slow_neg(1); wiggle_slow_neg(1);
} }
cmd[0]=0x40+GO_IDLE_STATE;
cmd[5]=0x95;
printf("sd_init start\n"); printf("sd_init start\n");
if((rsplen=send_command_slow(cmd, rsp))) { cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
// printf("CMD0 response?!:\n");
// uart_trace(rsp, 0, rsplen);
}
wiggle_slow_pos(1000); if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
cmd[0]=0x40+SEND_IF_COND; DBG_SD printf("CMD8 response:\n");
cmd[3]=0x01; DBG_SD uart_trace(rsp, 0, rsplen);
cmd[4]=0xaa;
cmd[5]=0x87;
if((rsplen=send_command_slow(cmd, rsp))) {
// uart_trace(cmd, 0, 6);
// printf("CMD8 response:\n");
// uart_trace(rsp, 0, rsplen);
hcs=1; hcs=1;
} }
while(1) { while(1) {
cmd[0]=0x40+APP_CMD; if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
cmd[5]=0x65;
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("CMD55 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD55 no response!\n");
}
cmd[0]=0x40+41;
cmd[1]=hcs<<6;
cmd[2]=0xfc; /* 2.7-3.6V */
cmd[3]=0x00;
cmd[4]=0x00;
cmd[5]=hcs ? 0x53 : 0xc1;
// printf("send ACMD41 hcs=%d\n", hcs);
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("ACMD41 response:\n");
// uart_trace(rsp, 0, rsplen);
// printf("busy=%d\n ccs=%d\n", rsp[1]>>7, (rsp[1]>>6)&1);
} else {
printf("ACMD41 no response!\n"); printf("ACMD41 no response!\n");
} }
if(rsp[1]&0x80) break; if(rsp[1]&0x80) break;
} }
ccs = (rsp[1]>>6) & 1; /* SDHC */ ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
cmd[0]=0x40+2; cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
cmd[1]=0; if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
cmd[2]=0; rca=(rsp[1]<<24) | (rsp[2]<<16);
cmd[3]=0; printf("RCA: %04lx\n", rca>>16);
cmd[4]=0;
cmd[5]=0x4d;
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("CMD2 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD2 no response!\n");
}
cmd[0]=0x40+3;
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
cmd[5]=0x21;
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("CMD3 response:\n");
// uart_trace(rsp, 0, rsplen);
rca1=rsp[1];
rca2=rsp[2];
// printf("RCA: %02x%02x\n", rca1, rca2);
} else { } else {
printf("CMD3 no response!\n"); printf("CMD3 no response!\n");
rca1=0; rca=0;
rca2=0;
} }
cmd[0]=0x40+9;
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
/* record CSD for getinfo */ /* record CSD for getinfo */
if((rsplen=send_command_slow(cmd, csd))) { cmd_slow(SEND_CSD, rca, 0, NULL, rsp);
// printf("CMD9 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD9 no response!\n");
}
cmd[0]=0x40+7;
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
/* select the card */ /* select the card */
if((rsplen=send_command_slow(cmd, rsp))) { if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) {
// printf("CMD7 response:\n");
// uart_trace(rsp, 0, rsplen);
printf("card selected!\n"); printf("card selected!\n");
} else { } else {
printf("CMD7 no response!\n"); printf("CMD7 no response!\n");
} }
cmd[0]=0x40+13;
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
/* get card status */ /* get card status */
if((rsplen=send_command_fast(cmd, rsp, NULL))) { cmd_slow(SEND_STATUS, rca, 0, NULL, rsp);
// printf("CMD13 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD13 no response!\n");
}
/* set bus width */ /* set bus width */
cmd[0]=0x40+55; acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
if((rsplen=send_command_slow(cmd, rsp))) { /* set block length */
// printf("CMD55 response:\n"); cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD55 no response!\n");
}
cmd[0]=0x40+6;
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=2;
make_crc7(cmd);
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("CMD55 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("ACMD6 no response!\n");
}
/* int i;
printf("start 4MB streaming test\n");
for(i=0; i<8192; i++) {
read_block(i, file_buf);
}
printf("end 4MB streaming test\n");*/
printf("SD init complete. SDHC/XC=%d\n", ccs); printf("SD init complete. SDHC/XC=%d\n", ccs);
disk_state = DISK_OK;
during_blocktrans = TRANS_NONE;
return sdn_status(drv); return sdn_status(drv);
} }
@ -955,28 +825,30 @@ void disk_init(void) __attribute__ ((weak, alias("sdn_init")));
DSTATUS sdn_status(BYTE drv) { DSTATUS sdn_status(BYTE drv) {
if (SDCARD_DETECT) if (SDCARD_DETECT) {
if (SDCARD_WP) if (SDCARD_WP) {
return STA_PROTECT; return STA_PROTECT;
else } else {
return RES_OK; return RES_OK;
else }
} else {
return STA_NOINIT|STA_NODISK; return STA_NOINIT|STA_NODISK;
}
} }
DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status"))); DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status")));
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) { DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
uint32_t capacity; uint32_t capacity;
if (drv >= MAX_CARDS) if (drv >= MAX_CARDS) {
return RES_NOTRDY; return RES_NOTRDY;
}
if (sdn_status(drv) & STA_NODISK) if (sdn_status(drv) & STA_NODISK) {
return RES_NOTRDY; return RES_NOTRDY;
}
if (page != 0) if (page != 0) {
return RES_ERROR; return RES_ERROR;
}
if (ccs) { if (ccs) {
/* Special CSD for SDHC cards */ /* Special CSD for SDHC cards */
capacity = (1 + getbits(csd,127-69+8,22)) * 1024; capacity = (1 + getbits(csd,127-69+8,22)) * 1024;
@ -993,6 +865,8 @@ DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
di->disktype = DISK_TYPE_SD; di->disktype = DISK_TYPE_SD;
di->sectorsize = 2; di->sectorsize = 2;
di->sectorcount = capacity; di->sectorcount = capacity;
printf("card capacity: %lu sectors\n", capacity);
return RES_OK; return RES_OK;
} }
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo"))); DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
@ -1003,9 +877,9 @@ DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
if(drv >= MAX_CARDS) { if(drv >= MAX_CARDS) {
return RES_NOTRDY; return RES_NOTRDY;
} }
if (sdn_status(drv) & STA_NODISK) if (sdn_status(drv) & STA_NODISK) {
return RES_NOTRDY; return RES_NOTRDY;
}
for(sec=0; sec<count; sec++) { for(sec=0; sec<count; sec++) {
write_block(sector+sec, buf); write_block(sector+sec, buf);
buf+=512; buf+=512;
@ -1017,9 +891,10 @@ DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __att
/* Detect changes of SD card 0 */ /* Detect changes of SD card 0 */
void sdn_changed() { void sdn_changed() {
if (SDCARD_DETECT) if (SDCARD_DETECT) {
disk_state = DISK_CHANGED; disk_state = DISK_CHANGED;
else } else {
disk_state = DISK_REMOVED; disk_state = DISK_REMOVED;
}
} }

View File

@ -3,8 +3,16 @@
#ifndef SDNATIVE_H #ifndef SDNATIVE_H
#define SDNATIVE_H #define SDNATIVE_H
#ifdef DEBUG_SD
#define DBG_SD
#else
#define DBG_SD while(0)
#endif
#include "diskio.h" #include "diskio.h"
extern int sd_offload;
/* These functions are weak-aliased to disk_... */ /* These functions are weak-aliased to disk_... */
void sdn_init(void); void sdn_init(void);
DSTATUS sdn_status(BYTE drv); DSTATUS sdn_status(BYTE drv);

View File

@ -29,6 +29,8 @@
#include "uart.h" #include "uart.h"
#include "smc.h" #include "smc.h"
snes_romprops_t romprops;
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0}; uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t countAllASCII(uint8_t* data, int size) { uint8_t countAllASCII(uint8_t* data, int size) {
uint8_t res = 0; uint8_t res = 0;

View File

@ -39,6 +39,8 @@
uint8_t initloop=1; uint8_t initloop=1;
uint32_t saveram_crc, saveram_crc_old; uint32_t saveram_crc, saveram_crc_old;
extern snes_romprops_t romprops;
void snes_init() { void snes_init() {
/* put reset level on reset pin */ /* put reset level on reset pin */
BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1; BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1;
@ -135,5 +137,5 @@ uint8_t menu_main_loop() {
void get_selected_name(uint8_t* fn) { void get_selected_name(uint8_t* fn) {
uint32_t addr = sram_readlong(SRAM_PARAM_ADDR); uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
printf("fd addr=%lx\n", addr); printf("fd addr=%lx\n", addr);
sram_readblock(fn, addr+10+SRAM_MENU_ADDR, 256); sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
} }

View File

@ -62,13 +62,15 @@ int sort_cmp_elem(const void* elem1, const void* elem2) {
/* get truncated string from database */ /* get truncated string from database */
void sort_getstring_for_dirent(char *ptr, uint32_t addr) { void sort_getstring_for_dirent(char *ptr, uint32_t addr) {
stat_getstring++; uint8_t leaf_offset;
if(addr & 0x80000000) { if(addr & 0x80000000) {
/* is directory link, name offset 6 */ /* is directory link, name offset 4 */
sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20); leaf_offset = sram_readbyte(addr + 4 + SRAM_MENU_ADDR);
sram_readblock(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, 20);
} else { } else {
/* is file link, name offset 10 */ /* is file link, name offset 6 */
sram_readblock(ptr, addr+10+SRAM_MENU_ADDR, 20); leaf_offset = sram_readbyte(addr + 6 + SRAM_MENU_ADDR);
sram_readblock(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, 20);
} }
ptr[20]=0; ptr[20]=0;
} }