SD acceleration, display file size in menu (fw side)
This commit is contained in:
parent
f4b88ca792
commit
4bc455f12b
@ -11,4 +11,11 @@
|
||||
(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
|
||||
|
||||
20
src/config.h
20
src/config.h
@ -1,6 +1,8 @@
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
// #define DEBUG_SD
|
||||
|
||||
#define VER "0.0.1(NSFW)"
|
||||
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
|
||||
|
||||
@ -71,4 +73,22 @@
|
||||
// 1: 3
|
||||
#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
|
||||
|
||||
@ -62,6 +62,7 @@ void disk_init(void);
|
||||
/* Will be set to DISK_ERROR if any access on the card fails */
|
||||
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
|
||||
|
||||
extern int sd_offload, ff_sd_offload;
|
||||
extern volatile enum diskstates disk_state;
|
||||
|
||||
/* Disk type - part of the external API except for ATA2! */
|
||||
|
||||
6
src/ff.c
6
src/ff.c
@ -2175,8 +2175,12 @@ FRESULT f_read (
|
||||
if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
|
||||
cc = fp->fs->csize - csect;
|
||||
/* XXX OFFLOAD GOES HERE */
|
||||
if (ff_sd_offload) {
|
||||
sd_offload = 1;
|
||||
}
|
||||
if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
|
||||
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_TINY
|
||||
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 */
|
||||
#endif
|
||||
}
|
||||
|
||||
ff_sd_offload = 0;
|
||||
LEAVE_FF(fp->fs, FR_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
/* 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. */
|
||||
|
||||
|
||||
|
||||
@ -61,6 +61,9 @@ UINT file_read() {
|
||||
UINT file_write() {
|
||||
UINT 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;
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +70,10 @@ 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];
|
||||
char buf[7];
|
||||
char *size_units[3] = {" ", "k", "M"};
|
||||
uint32_t entry_fsize;
|
||||
uint8_t entry_unit_idx;
|
||||
|
||||
dir_tgt = this_dir_tgt;
|
||||
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 */
|
||||
/* 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);
|
||||
db_tgt &= 0xffff0000;
|
||||
db_tgt += 0x00010000;
|
||||
@ -198,7 +201,14 @@ 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)); */
|
||||
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_writebyte(len+1, db_tgt + sizeof(buf)-1);
|
||||
sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1);
|
||||
|
||||
17
src/fpga.c
17
src/fpga.c
@ -97,11 +97,22 @@ void fpga_pgm(uint8_t* filename) {
|
||||
int MAXRETRIES = 10;
|
||||
int retries = MAXRETRIES;
|
||||
uint8_t data;
|
||||
int i;
|
||||
tick_t timeout;
|
||||
// UINT bytes_read;
|
||||
// uint16_t j;
|
||||
do {
|
||||
i=0;
|
||||
timeout = getticks() + 100;
|
||||
fpga_set_prog_b(0);
|
||||
uart_putc('P');
|
||||
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));
|
||||
uart_putc('p');
|
||||
|
||||
@ -114,13 +125,17 @@ void fpga_pgm(uint8_t* filename) {
|
||||
return;
|
||||
}
|
||||
uart_putc('C');
|
||||
|
||||
for (;;) {
|
||||
data = rle_file_getc();
|
||||
i++;
|
||||
if (file_status || file_res) break; /* error or eof */
|
||||
FPGA_SEND_BYTE_SERIAL(data);
|
||||
}
|
||||
uart_putc('c');
|
||||
file_close();
|
||||
printf("fpga_pgm: %d bytes programmed\n", i);
|
||||
delay_ms(1);
|
||||
} while (!fpga_get_done() && retries--);
|
||||
if(!fpga_get_done()) {
|
||||
printf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
|
||||
|
||||
@ -35,7 +35,6 @@ void fpga_set_cclk(uint8_t val);
|
||||
int fpga_get_initb(void);
|
||||
|
||||
void fpga_init(void);
|
||||
uint8_t fpga_test(void);
|
||||
void fpga_postinit(void);
|
||||
void fpga_pgm(uint8_t* filename);
|
||||
|
||||
|
||||
@ -29,16 +29,19 @@
|
||||
|
||||
cmd param function
|
||||
=============================================
|
||||
00 bb[hh[ll]] set address to 0xbb0000, 0xbbhh00, or 0xbbhhll
|
||||
10 bbhhll set SNES input address mask to 0xbbhhll
|
||||
20 bbhhll set SRAM address mask to 0xbbhhll
|
||||
00 bbhhll set address to 0xbbhhll
|
||||
01 bbhhll set SNES input address mask to 0xbbhhll
|
||||
02 bbhhll set SRAM address mask to 0xbbhhll
|
||||
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
|
||||
81 - read w/o increment
|
||||
90 {xx}* write xx with 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)
|
||||
F1 - receive status
|
||||
|
||||
*/
|
||||
|
||||
@ -66,7 +69,7 @@ void set_mcu_addr(uint32_t address) {
|
||||
|
||||
void set_saveram_mask(uint32_t mask) {
|
||||
FPGA_SELECT();
|
||||
FPGA_TX_BYTE(0x20);
|
||||
FPGA_TX_BYTE(0x02);
|
||||
FPGA_TX_BYTE((mask>>16)&0xff);
|
||||
FPGA_TX_BYTE((mask>>8)&0xff);
|
||||
FPGA_TX_BYTE((mask)&0xff);
|
||||
@ -75,7 +78,7 @@ void set_saveram_mask(uint32_t mask) {
|
||||
|
||||
void set_rom_mask(uint32_t mask) {
|
||||
FPGA_SELECT();
|
||||
FPGA_TX_BYTE(0x10);
|
||||
FPGA_TX_BYTE(0x01);
|
||||
FPGA_TX_BYTE((mask>>16)&0xff);
|
||||
FPGA_TX_BYTE((mask>>8)&0xff);
|
||||
FPGA_TX_BYTE((mask)&0xff);
|
||||
@ -97,3 +100,25 @@ uint8_t fpga_test() {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -47,7 +47,8 @@
|
||||
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW)
|
||||
|
||||
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_sd(void);
|
||||
void spi_none(void);
|
||||
@ -55,5 +56,6 @@ void set_mcu_addr(uint32_t);
|
||||
void set_saveram_mask(uint32_t);
|
||||
void set_rom_mask(uint32_t);
|
||||
void set_mapper(uint8_t val);
|
||||
void fpga_sd2ram(void);
|
||||
|
||||
#endif
|
||||
|
||||
39
src/main.c
39
src/main.c
@ -23,15 +23,19 @@
|
||||
#include "cli.h"
|
||||
#include "sdnative.h"
|
||||
#include "crc.h"
|
||||
#include "smc.h"
|
||||
|
||||
#define EMC0TOGGLE (3<<4)
|
||||
#define MR0R (1<<1)
|
||||
|
||||
int i;
|
||||
|
||||
int sd_offload = 0, ff_sd_offload = 0;
|
||||
/* FIXME HACK */
|
||||
volatile enum diskstates disk_state;
|
||||
extern volatile tick_t ticks;
|
||||
extern snes_romprops_t romprops;
|
||||
|
||||
int main(void) {
|
||||
LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
|
||||
LPC_GPIO1->FIODIR = 0;
|
||||
@ -58,25 +62,12 @@ int main(void) {
|
||||
/* 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);
|
||||
file_init();
|
||||
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) */
|
||||
LPC_TIM3->CTCR=0;
|
||||
LPC_TIM3->EMR=EMC0TOGGLE;
|
||||
@ -103,16 +94,6 @@ 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)) {
|
||||
@ -172,11 +153,12 @@ restart:
|
||||
printf("test sram\n");
|
||||
while(!sram_reliable());
|
||||
printf("ok\n");
|
||||
sram_hexdump(SRAM_DB_ADDR, 0x200);
|
||||
//sram_hexdump(SRAM_DB_ADDR, 0x200);
|
||||
//sram_hexdump(SRAM_MENU_ADDR, 0x400);
|
||||
|
||||
while(!cmd) {
|
||||
cmd=menu_main_loop();
|
||||
printf("derp %d\n", cmd);
|
||||
printf("cmd: %d\n", cmd);
|
||||
sleep_ms(50);
|
||||
uart_putc('-');
|
||||
switch(cmd) {
|
||||
@ -192,13 +174,13 @@ 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);
|
||||
snes_reset(0);
|
||||
break;
|
||||
case SNES_CMD_SETRTC:
|
||||
cmd=0; /* stay in loop */
|
||||
break;
|
||||
default:
|
||||
printf("unknown cmd: %d\n", cmd);
|
||||
@ -230,18 +212,17 @@ save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR);
|
||||
}
|
||||
}
|
||||
if(snes_reset_state) {
|
||||
delay_ms(10);
|
||||
reset_count++;
|
||||
} else {
|
||||
sram_reliable();
|
||||
snes_main_loop();
|
||||
}
|
||||
if(reset_count>100) {
|
||||
if(reset_count>4) {
|
||||
reset_count=0;
|
||||
set_mcu_ovr(1);
|
||||
snes_reset(1);
|
||||
delay_ms(100);
|
||||
if(romprops.ramsize_bytes && fpga_test() == 0xa5) {
|
||||
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
|
||||
writeled(1);
|
||||
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
||||
writeled(0);
|
||||
|
||||
71
src/memory.c
71
src/memory.c
@ -39,9 +39,13 @@
|
||||
#include "memory.h"
|
||||
#include "snes.h"
|
||||
#include "timer.h"
|
||||
#include "rle.h"
|
||||
#include "diskio.h"
|
||||
|
||||
char* hex = "0123456789ABCDEF";
|
||||
|
||||
extern snes_romprops_t romprops;
|
||||
|
||||
void sram_hexdump(uint32_t addr, uint32_t len) {
|
||||
static uint8_t buf[16];
|
||||
uint32_t ptr;
|
||||
@ -162,25 +166,30 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
|
||||
UINT bytes_read;
|
||||
DWORD filesize;
|
||||
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);
|
||||
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) {
|
||||
uart_putc('?');
|
||||
uart_putc(0x30+file_res);
|
||||
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);
|
||||
FPGA_DESELECT();
|
||||
FPGA_SELECT();
|
||||
FPGA_TX_BYTE(0x91); /* write w/ increment */
|
||||
// FPGA_DESELECT();
|
||||
// FPGA_SELECT();
|
||||
// FPGA_TX_BYTE(0x91); /* write w/ increment */
|
||||
for(;;) {
|
||||
/* SPI_OFFLOAD=1; */
|
||||
ff_sd_offload=1;
|
||||
tickstmp=getticks();
|
||||
bytes_read = file_read();
|
||||
ticks_read+=getticks()-tickstmp;
|
||||
if (file_res || !bytes_read) break;
|
||||
if(!(count++ % 32)) {
|
||||
if(!(count++ % 512)) {
|
||||
toggle_read_led();
|
||||
/* bounce_busy_led(); */
|
||||
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++) {
|
||||
// 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_DESELECT();
|
||||
// FPGA_TX_BYTE(0x00); /* dummy tx for increment+write pulse */
|
||||
// FPGA_DESELECT();
|
||||
file_close();
|
||||
set_mapper(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 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);
|
||||
set_saveram_mask(rammask);
|
||||
set_rom_mask(rommask);
|
||||
|
||||
readled(0);
|
||||
return (uint32_t)filesize;
|
||||
}
|
||||
|
||||
@ -238,6 +250,26 @@ uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
|
||||
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) {
|
||||
uint32_t count = 0;
|
||||
@ -318,3 +350,14 @@ uint8_t sram_reliable() {
|
||||
rdyled(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();
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
|
||||
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_rle(uint8_t* filename, uint32_t base_addr);
|
||||
void sram_hexdump(uint32_t addr, uint32_t len);
|
||||
uint8_t sram_readbyte(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);
|
||||
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
|
||||
uint8_t sram_reliable(void);
|
||||
void sram_memset(uint32_t base_adde, uint32_t len, uint8_t val);
|
||||
|
||||
snes_romprops_t romprops;
|
||||
#endif
|
||||
|
||||
487
src/sdnative.c
487
src/sdnative.c
@ -1,5 +1,4 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <arm/bits.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "crc.h"
|
||||
@ -10,13 +9,18 @@
|
||||
#include "led.h"
|
||||
#include "sdnative.h"
|
||||
#include "fileops.h"
|
||||
#include "bits.h"
|
||||
#include "fpga_spi.h"
|
||||
|
||||
#define MAX_CARDS 1
|
||||
|
||||
// SD/MMC commands
|
||||
#define GO_IDLE_STATE 0
|
||||
#define SEND_OP_COND 1
|
||||
#define ALL_SEND_CID 2
|
||||
#define SEND_RELATIVE_ADDR 3
|
||||
#define SWITCH_FUNC 6
|
||||
#define SELECT_CARD 7
|
||||
#define SEND_IF_COND 8
|
||||
#define SEND_CSD 9
|
||||
#define SEND_CID 10
|
||||
@ -41,6 +45,7 @@
|
||||
#define CRC_ON_OFF 59
|
||||
|
||||
// SD ACMDs
|
||||
#define SD_SET_BUS_WIDTH 6
|
||||
#define SD_STATUS 13
|
||||
#define SD_SEND_NUM_WR_BLOCKS 22
|
||||
#define SD_SET_WR_BLK_ERASE_COUNT 23
|
||||
@ -62,20 +67,6 @@
|
||||
#define CARD_SD (1<<0)
|
||||
#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
|
||||
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 csd[17];
|
||||
uint8_t ccs=0;
|
||||
uint8_t rca1, rca2;
|
||||
uint32_t rca;
|
||||
|
||||
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void wait_busy(void) {
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg(4);
|
||||
}
|
||||
|
||||
/*
|
||||
send_command_slow
|
||||
@ -215,9 +210,8 @@ static inline void wiggle_fast_pos1(void) {
|
||||
int send_command_slow(uint8_t* cmd, uint8_t* rsp){
|
||||
uint8_t shift, i=6;
|
||||
int rsplen;
|
||||
// printf("send_command_slow: sending CMD:\n");
|
||||
uint8_t cmdno = *cmd & 0x3f;
|
||||
wiggle_slow_pos(5);
|
||||
// uart_trace(cmd, 0, 6);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 0:
|
||||
rsplen = 0;
|
||||
@ -254,12 +248,11 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
|
||||
|
||||
if(rsplen) {
|
||||
uint16_t timeout=1000;
|
||||
/* wait for responsebob */
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
// printf("timeout=%d\n", timeout);
|
||||
if(!timeout) {
|
||||
printf("CMD%d timed out\n", cmdno);
|
||||
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){
|
||||
uint8_t datshift=8, cmdshift, i=6;
|
||||
uint8_t cmdno = *cmd & 0x3f;
|
||||
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(9);
|
||||
// uart_trace(cmd, 0, 6);
|
||||
wiggle_fast_pos(9); /* give the card >=8 cycles after last command */
|
||||
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]);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 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;
|
||||
|
||||
while(i--) {
|
||||
uint8_t data = *cmd;
|
||||
cmdshift = 8;
|
||||
do {
|
||||
cmdshift--;
|
||||
uint8_t data = *cmd;
|
||||
*cmd<<=1;
|
||||
if(data&0x80) {
|
||||
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
|
||||
}
|
||||
data<<=1;
|
||||
wiggle_fast_pos1();
|
||||
} while (cmdshift);
|
||||
cmd++;
|
||||
}
|
||||
|
||||
wiggle_fast_pos(1);
|
||||
wiggle_fast_pos1();
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
|
||||
|
||||
if(rsplen) {
|
||||
uint16_t timeout=65535;
|
||||
/* wait for responsebob */
|
||||
uint32_t timeout=2000000;
|
||||
/* wait for response */
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
// printf("timeout=%d\n", timeout);
|
||||
if(!timeout) {
|
||||
printf("CMD%d timed out\n", cmdno);
|
||||
return 0; /* no response within timeout */
|
||||
}
|
||||
|
||||
@ -355,7 +348,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
do {
|
||||
if(dat) {
|
||||
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
// printf("data start\n");
|
||||
DBG_SD printf("data start during response\n");
|
||||
j=datcnt;
|
||||
state=CMD_RSPDAT;
|
||||
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;
|
||||
wiggle_fast_neg1();
|
||||
} while (cmdshift);
|
||||
if(state==1)break;
|
||||
if(state==CMD_RSPDAT)break;
|
||||
*rsp=cmddata;
|
||||
cmddata=0;
|
||||
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 */
|
||||
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;
|
||||
while(1) {
|
||||
cmdshift--;
|
||||
@ -385,16 +378,14 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
rsp++;
|
||||
i--;
|
||||
if(!i) {
|
||||
printf("response end\n");
|
||||
DBG_SD printf("response end\n");
|
||||
if(j) state=CMD_DAT; /* response over, remaining data */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!startbit) {
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
|
||||
datdata |= SD_DAT << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*buf=datdata;
|
||||
@ -413,25 +404,26 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
state=CMD_DAT;
|
||||
j=datcnt;
|
||||
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) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
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 */
|
||||
// printf("remaining data: %d\n", j);
|
||||
DBG_SD printf("remaining data: %d\n", j);
|
||||
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;
|
||||
datdata |= SD_DAT << 4;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
|
||||
datdata |= SD_DAT;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
*buf=datdata;
|
||||
@ -444,9 +436,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
|
||||
while(1) {
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
|
||||
datdata |= SD_DAT << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*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(waitbusy) {
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
DBG_SD printf("waitbusy after send_cmd\n");
|
||||
wait_busy();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void make_crc7(uint8_t* cmd) {
|
||||
static inline void make_crc7(uint8_t* cmd) {
|
||||
cmd[5]=crc7update(0, cmd[0]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[1]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[2]);
|
||||
@ -482,65 +473,85 @@ void make_crc7(uint8_t* cmd) {
|
||||
cmd[5]=(cmd[5] << 1) | 1;
|
||||
}
|
||||
|
||||
int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
cmdbuf[1] = param >> 24;
|
||||
cmdbuf[2] = param >> 16;
|
||||
cmdbuf[3] = param >> 8;
|
||||
cmdbuf[4] = param;
|
||||
if(!crc) {
|
||||
make_crc7(cmdbuf);
|
||||
} else {
|
||||
cmdbuf[5] = crc;
|
||||
}
|
||||
return send_command_slow(cmdbuf, rsp);
|
||||
}
|
||||
|
||||
int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) {
|
||||
return 0;
|
||||
}
|
||||
return cmd_slow(cmd, param, crc, dat, rsp);
|
||||
}
|
||||
|
||||
int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
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) {
|
||||
// uint8_t datshift=8;
|
||||
int j=512;
|
||||
uint8_t datdata=0;
|
||||
uint16_t timeout=65535;
|
||||
uint32_t timeout=1000000;
|
||||
|
||||
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
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;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
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 */
|
||||
wiggle_fast_neg(17);
|
||||
}
|
||||
}
|
||||
|
||||
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(".");
|
||||
}
|
||||
|
||||
wiggle_fast_pos1();
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 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_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos(1); /* send start bit to card */
|
||||
wiggle_fast_pos1(); /* send start bit to card */
|
||||
crcshift=8;
|
||||
while(cnt--) {
|
||||
datshift=8;
|
||||
@ -577,7 +588,7 @@ void send_datablock(uint8_t *buf) {
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos(1);
|
||||
wiggle_fast_pos1();
|
||||
} while (datshift);
|
||||
|
||||
crcshift-=2;
|
||||
@ -603,27 +614,27 @@ void send_datablock(uint8_t *buf) {
|
||||
datshift=16;
|
||||
do {
|
||||
datshift--;
|
||||
if((crc0 >> datshift)&1) {
|
||||
if((crc0 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
if((crc1 >> datshift)&1) {
|
||||
if((crc1 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
}
|
||||
if((crc2 >> datshift)&1) {
|
||||
if((crc2 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
}
|
||||
if((crc3 >> datshift)&1) {
|
||||
if((crc3 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos(1);
|
||||
wiggle_fast_pos1();
|
||||
} while(datshift);
|
||||
/* send end bit */
|
||||
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_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos(1);
|
||||
wiggle_fast_pos1();
|
||||
|
||||
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);
|
||||
wiggle_fast_neg(3);
|
||||
dat0=0;
|
||||
|
||||
datshift=3;
|
||||
datshift=4;
|
||||
do {
|
||||
datshift--;
|
||||
dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift);
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
} while (datshift);
|
||||
|
||||
if(dat0!=2) {
|
||||
DBG_SD printf("crc %02x\n", dat0);
|
||||
if((dat0 & 7) != 2) {
|
||||
printf("crc error! %02x\n", dat0);
|
||||
while(1);
|
||||
}
|
||||
wiggle_fast_neg(1);
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg(1);
|
||||
}
|
||||
if(dat0 & 8) {
|
||||
printf("missing start bit in CRC status response...\n");
|
||||
}
|
||||
wiggle_fast_neg(2);
|
||||
wait_busy();
|
||||
}
|
||||
|
||||
void read_block(uint32_t address, uint8_t *buf) {
|
||||
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
|
||||
//uart_putc('r');
|
||||
stream_datablock(buf);
|
||||
last_block=address;
|
||||
} else {
|
||||
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 */
|
||||
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);
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
}
|
||||
last_block=address;
|
||||
if(!ccs) address <<= 9;
|
||||
cmd[0]=0x40+READ_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, buf);
|
||||
// uart_trace(cmd, 0, 6);
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
if(!ccs) {
|
||||
address <<= 9;
|
||||
}
|
||||
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
|
||||
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)) {
|
||||
wait_busy();
|
||||
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);
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
}
|
||||
wait_busy();
|
||||
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 */
|
||||
if(!ccs) {
|
||||
address <<= 9;
|
||||
}
|
||||
/* only send cmd & get response */
|
||||
cmd_fast(WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp);
|
||||
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]);
|
||||
wiggle_fast_pos(8);
|
||||
send_datablock(buf);
|
||||
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) {
|
||||
|
||||
uint8_t cmd[6]={0,0,0,0,0,0}; /* command */
|
||||
uint8_t rsp[17]; /* space for response */
|
||||
int rsplen;
|
||||
uint8_t hcs=0;
|
||||
if(drv>=MAX_CARDS)
|
||||
rca = 0;
|
||||
if(drv>=MAX_CARDS) {
|
||||
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
|
||||
prior to initialization */
|
||||
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;
|
||||
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");
|
||||
}
|
||||
cmd_slow(SELECT_CARD, 0, 0, NULL, rsp);
|
||||
}
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
cmd[0]=0x40+GO_IDLE_STATE;
|
||||
cmd[5]=0x95;
|
||||
printf("sd_init start\n");
|
||||
if((rsplen=send_command_slow(cmd, rsp))) {
|
||||
// printf("CMD0 response?!:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
}
|
||||
cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
|
||||
|
||||
wiggle_slow_pos(1000);
|
||||
cmd[0]=0x40+SEND_IF_COND;
|
||||
cmd[3]=0x01;
|
||||
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);
|
||||
if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
|
||||
DBG_SD printf("CMD8 response:\n");
|
||||
DBG_SD uart_trace(rsp, 0, rsplen);
|
||||
hcs=1;
|
||||
}
|
||||
while(1) {
|
||||
cmd[0]=0x40+APP_CMD;
|
||||
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 {
|
||||
if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
|
||||
printf("ACMD41 no response!\n");
|
||||
}
|
||||
if(rsp[1]&0x80) break;
|
||||
}
|
||||
|
||||
ccs = (rsp[1]>>6) & 1; /* SDHC */
|
||||
ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
|
||||
|
||||
cmd[0]=0x40+2;
|
||||
cmd[1]=0;
|
||||
cmd[2]=0;
|
||||
cmd[3]=0;
|
||||
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);
|
||||
cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
|
||||
if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
|
||||
rca=(rsp[1]<<24) | (rsp[2]<<16);
|
||||
printf("RCA: %04lx\n", rca>>16);
|
||||
} else {
|
||||
printf("CMD3 no response!\n");
|
||||
rca1=0;
|
||||
rca2=0;
|
||||
rca=0;
|
||||
}
|
||||
|
||||
cmd[0]=0x40+9;
|
||||
cmd[1]=rca1;
|
||||
cmd[2]=rca2;
|
||||
cmd[3]=0;
|
||||
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);
|
||||
} 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);
|
||||
cmd_slow(SEND_CSD, rca, 0, NULL, rsp);
|
||||
|
||||
/* select the card */
|
||||
if((rsplen=send_command_slow(cmd, rsp))) {
|
||||
// printf("CMD7 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) {
|
||||
printf("card selected!\n");
|
||||
} else {
|
||||
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 */
|
||||
if((rsplen=send_command_fast(cmd, rsp, NULL))) {
|
||||
// printf("CMD13 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
} else {
|
||||
printf("CMD13 no response!\n");
|
||||
}
|
||||
cmd_slow(SEND_STATUS, rca, 0, NULL, rsp);
|
||||
|
||||
/* set bus width */
|
||||
cmd[0]=0x40+55;
|
||||
cmd[1]=rca1;
|
||||
cmd[2]=rca2;
|
||||
cmd[3]=0;
|
||||
cmd[4]=0;
|
||||
make_crc7(cmd);
|
||||
acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
|
||||
|
||||
if((rsplen=send_command_slow(cmd, rsp))) {
|
||||
// printf("CMD55 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
} else {
|
||||
printf("CMD55 no response!\n");
|
||||
}
|
||||
/* set block length */
|
||||
cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
|
||||
|
||||
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);
|
||||
|
||||
disk_state = DISK_OK;
|
||||
during_blocktrans = TRANS_NONE;
|
||||
return sdn_status(drv);
|
||||
}
|
||||
|
||||
@ -955,28 +825,30 @@ void disk_init(void) __attribute__ ((weak, alias("sdn_init")));
|
||||
|
||||
|
||||
DSTATUS sdn_status(BYTE drv) {
|
||||
if (SDCARD_DETECT)
|
||||
if (SDCARD_WP)
|
||||
if (SDCARD_DETECT) {
|
||||
if (SDCARD_WP) {
|
||||
return STA_PROTECT;
|
||||
else
|
||||
} else {
|
||||
return RES_OK;
|
||||
else
|
||||
}
|
||||
} else {
|
||||
return STA_NOINIT|STA_NODISK;
|
||||
}
|
||||
}
|
||||
DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status")));
|
||||
|
||||
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
|
||||
uint32_t capacity;
|
||||
|
||||
if (drv >= MAX_CARDS)
|
||||
if (drv >= MAX_CARDS) {
|
||||
return RES_NOTRDY;
|
||||
|
||||
if (sdn_status(drv) & STA_NODISK)
|
||||
}
|
||||
if (sdn_status(drv) & STA_NODISK) {
|
||||
return RES_NOTRDY;
|
||||
|
||||
if (page != 0)
|
||||
}
|
||||
if (page != 0) {
|
||||
return RES_ERROR;
|
||||
|
||||
}
|
||||
if (ccs) {
|
||||
/* Special CSD for SDHC cards */
|
||||
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->sectorsize = 2;
|
||||
di->sectorcount = capacity;
|
||||
|
||||
printf("card capacity: %lu sectors\n", capacity);
|
||||
return RES_OK;
|
||||
}
|
||||
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) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if (sdn_status(drv) & STA_NODISK)
|
||||
if (sdn_status(drv) & STA_NODISK) {
|
||||
return RES_NOTRDY;
|
||||
|
||||
}
|
||||
for(sec=0; sec<count; sec++) {
|
||||
write_block(sector+sec, buf);
|
||||
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 */
|
||||
void sdn_changed() {
|
||||
if (SDCARD_DETECT)
|
||||
if (SDCARD_DETECT) {
|
||||
disk_state = DISK_CHANGED;
|
||||
else
|
||||
} else {
|
||||
disk_state = DISK_REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,16 @@
|
||||
#ifndef SDNATIVE_H
|
||||
#define SDNATIVE_H
|
||||
|
||||
#ifdef DEBUG_SD
|
||||
#define DBG_SD
|
||||
#else
|
||||
#define DBG_SD while(0)
|
||||
#endif
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
extern int sd_offload;
|
||||
|
||||
/* These functions are weak-aliased to disk_... */
|
||||
void sdn_init(void);
|
||||
DSTATUS sdn_status(BYTE drv);
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
#include "uart.h"
|
||||
#include "smc.h"
|
||||
|
||||
snes_romprops_t romprops;
|
||||
|
||||
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
|
||||
uint8_t countAllASCII(uint8_t* data, int size) {
|
||||
uint8_t res = 0;
|
||||
|
||||
@ -39,6 +39,8 @@
|
||||
|
||||
uint8_t initloop=1;
|
||||
uint32_t saveram_crc, saveram_crc_old;
|
||||
extern snes_romprops_t romprops;
|
||||
|
||||
void snes_init() {
|
||||
/* put reset level on reset pin */
|
||||
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) {
|
||||
uint32_t addr = sram_readlong(SRAM_PARAM_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);
|
||||
}
|
||||
|
||||
12
src/sort.c
12
src/sort.c
@ -62,13 +62,15 @@ int sort_cmp_elem(const void* elem1, const void* elem2) {
|
||||
|
||||
/* get truncated string from database */
|
||||
void sort_getstring_for_dirent(char *ptr, uint32_t addr) {
|
||||
stat_getstring++;
|
||||
uint8_t leaf_offset;
|
||||
if(addr & 0x80000000) {
|
||||
/* is directory link, name offset 6 */
|
||||
sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20);
|
||||
/* is directory link, name offset 4 */
|
||||
leaf_offset = sram_readbyte(addr + 4 + SRAM_MENU_ADDR);
|
||||
sram_readblock(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, 20);
|
||||
} else {
|
||||
/* is file link, name offset 10 */
|
||||
sram_readblock(ptr, addr+10+SRAM_MENU_ADDR, 20);
|
||||
/* is file link, name offset 6 */
|
||||
leaf_offset = sram_readbyte(addr + 6 + SRAM_MENU_ADDR);
|
||||
sram_readblock(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, 20);
|
||||
}
|
||||
ptr[20]=0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user