SPI offloading -> 5x loading speed (needs code cleanup)

This commit is contained in:
ikari
2009-12-22 03:06:26 +01:00
parent b37fc1b846
commit 63febb92c6
15 changed files with 508 additions and 82 deletions

View File

@@ -80,6 +80,8 @@ DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer);
void disk_init(void);
uint8_t SD_SPI_OFFLOAD;
/* Will be set to DISK_ERROR if any access on the card fails */
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };

View File

@@ -60,6 +60,7 @@
#include "ff.h" /* FatFs declarations */
#include "diskio.h" /* Include file for user provided disk functions */
#include "uart.h"
#include "fpga.h"
/*--------------------------------------------------------------------------
@@ -1603,8 +1604,12 @@ FRESULT f_read (
cc = btr / SS(fs); /* When left bytes >= SS(fs), */
if (cc) { /* Read maximum contiguous sectors directly */
if (cc > fp->csect) cc = fp->csect;
if(SPI_OFFLOAD) {
SD_SPI_OFFLOAD = 1;
}
if (disk_read(fs->drive, rbuff, sect, (BYTE)cc) != RES_OK)
goto fr_error;
SD_SPI_OFFLOAD = 0;
fp->csect -= (BYTE)(cc - 1);
fp->curr_sect += cc - 1;
rcnt = cc * SS(fs);
@@ -1619,10 +1624,13 @@ FRESULT f_read (
}
}
SPI_OFFLOAD = 0;
return FR_OK;
fr_error: /* Abort this file due to an unrecoverable error */
fp->flag |= FA__ERROR;
SPI_OFFLOAD = 0;
SD_SPI_OFFLOAD = 0;
return FR_RW_ERROR;
}

View File

@@ -55,6 +55,10 @@ void fpga_init() {
DDRD |= _BV(PD3) | _BV(PD4); // PD3, PD4 are outputs
DDRA = ~_BV(PA3); // PA3 is input <- DONE
DDRB |= _BV(PB2); // DMA_CTRL preinit
PORTB |= _BV(PB2);
SPI_OFFLOAD=0;
set_cclk(0); // initial clk=0
}
@@ -64,7 +68,7 @@ int fpga_get_done(void) {
void fpga_postinit() {
DDRA |= _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA4) | _BV(PA5) | _BV(PA6); // MAPPER+NEXTADDR output
DDRB |= _BV(PB2) | _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK
DDRB |= _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK
DDRD |= _BV(PD7); // turn PD7 into output
}

View File

@@ -20,6 +20,7 @@ void set_avr_addr_en(uint8_t val);
void set_avr_mapper(uint8_t val);
void set_avr_bank(uint8_t val);
uint8_t SPI_OFFLOAD;
#define FPGA_TEST_TOKEN (0xa5)

View File

@@ -48,6 +48,7 @@
#include "spi.h"
#include "avrcompat.h"
#include "filetypes.h"
#include "sdcard.h"
void writetest(void) {
// HERE BE LIONS, GET IN THE CAR
@@ -116,12 +117,6 @@ void poison_memory(void) {
}
#endif
void avr_goto_addr(const uint32_t val) {
AVR_ADDR_RESET();
for(uint32_t i=0; i<val; i++) {
AVR_NEXTADDR();
}
}
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)
int main(void) __attribute__((OS_main));
#endif
@@ -189,7 +184,41 @@ restart:
uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
while(0) {
SD_SPI_OFFLOAD=1;
sd_read(0, file_buf, 32L, 1);
// sram_writeblock((void*)file_buf, 0, 0x200);
sram_hexdump(0,0x10);
uart_putc('+');
}
/* here be strange monsters */
while(0){
// uint16_t hurdur1 = 0, hurdur2 = 0;
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
PORTB |= _BV(PB2);
DDRB |= _BV(PB2);
PORTB &= ~_BV(PB2);
DDRB &= ~_BV(PB7); // tristate SCK
PORTB |= _BV(PB2);
DDRB &= ~_BV(PB2);
while(!(PINB & _BV(PB2))) {
}
DDRB |= _BV(PB7);
_delay_ms(1);
// dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2);
}
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint
dprintf("curr dir id = %x\n", curr_dir_id);
@@ -207,7 +236,7 @@ restart:
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
dprintf("done\n");
sram_hexdump(SRAM_DB_ADDR, 0x400);
// sram_hexdump(SRAM_DB_ADDR, 0x400);
} else {
dprintf("saved dir id = %x\n", saved_dir_id);
dprintf("different card, consistent db, loading db...\n");
@@ -229,10 +258,14 @@ restart:
led_pwm();
// sram_hexdump(0, 0x200);
uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin");
set_rom_mask(0x3fffff); // force mirroring off
uart_putc(')');
uart_putcrlf();
// sram_hexdump(0, 0x200);
// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
sram_writebyte(0, SRAM_CMD_ADDR);
@@ -256,6 +289,7 @@ restart:
set_avr_ena(0);
dprintf("Selected name: %s\n", file_lfn);
load_rom(file_lfn);
// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
if(romprops.ramsize_bytes) {
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
dprintf("SRM file: %s\n", file_lfn);
@@ -281,7 +315,6 @@ restart:
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0;
while(fpga_test() == FPGA_TEST_TOKEN) {
dprintf("%02X\n", fpga_test());
snes_reset_now=get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {

View File

@@ -124,7 +124,7 @@ void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
}
uint32_t load_rom(uint8_t* filename) {
uint8_t dummy;
// uint8_t dummy;
set_avr_bank(0);
UINT bytes_read;
DWORD filesize;
@@ -132,18 +132,25 @@ uint32_t load_rom(uint8_t* filename) {
file_open(filename, FA_READ);
filesize = file_handle.fsize;
smc_id(&romprops);
dprintf("no nervous breakdown beyond this point! or else!\n");
if(file_res) {
uart_putc('?');
uart_putc(0x30+file_res);
return 0;
}
f_lseek(&file_handle, romprops.offset);
spi_none();
for(;;) {
SPI_OFFLOAD=1;
spi_none();
bytes_read = file_read();
spi_none();
if (file_res || !bytes_read) break;
spi_fpga();
if(!(count++ % 8)) {
// toggle_busy_led();
bounce_busy_led();
uart_putc('.');
}
/* spi_fpga();
spiTransferByte(0x91); // write w/ increment
if(!(count++ % 8)) {
// toggle_busy_led();
@@ -156,7 +163,7 @@ uint32_t load_rom(uint8_t* filename) {
loop_until_bit_is_set(SPSR, SPIF);
dummy = SPDR;
}
spiTransferByte(0x00); // dummy tx for increment+write pulse
spiTransferByte(0x00); // dummy tx for increment+write pulse */
}
file_close();
spi_none();

View File

@@ -60,6 +60,7 @@
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/crc16.h>
#include <util/delay.h>
#include "config.h"
#include "avrcompat.h"
#include "crc7.h"
@@ -308,6 +309,8 @@ static void sdInit(const uint8_t card) {
uint8_t i;
uint16_t counter;
SD_SPI_OFFLOAD = 0;
counter = 0xffff;
do {
// Prepare for ACMD, send CMD55: APP_CMD
@@ -557,24 +560,46 @@ DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
// Get data
crc = 0;
// Initiate data exchange over SPI
SPDR = 0xff;
for (i=0; i<512; i++) {
// Wait until data has been received
loop_until_bit_is_set(SPSR, SPIF);
tmp = SPDR;
// Transmit the next byte while we store the current one
if(SD_SPI_OFFLOAD) {
// uart_putc('O');
PORTB |= _BV(PB2);
DDRB |= _BV(PB2);
PORTB &= ~_BV(PB2);
PORTB |= _BV(PB2);
PORTB &= ~_BV(PB7);
DDRB &= ~_BV(PB7); // tristate SCK
// SPCR=0;
DDRB &= ~_BV(PB2);
_delay_us(1);
loop_until_bit_is_set(PINB, PB2);
DDRB |= _BV(PB2);
// SPCR=0b01010000;
SD_SPI_OFFLOAD = 0;
deselectCard(drv);
DDRB |= _BV(PB7);
return RES_OK;
SPDR = 0xff;
*(buffer++) = tmp;
} else {
// Initiate data exchange over SPI
SPDR = 0xff;
for (i=0; i<512; i++) {
// Wait until data has been received
loop_until_bit_is_set(SPSR, SPIF);
tmp = SPDR;
// Transmit the next byte while we store the current one
SPDR = 0xff;
*(buffer++) = tmp;
#ifdef CONFIG_SD_DATACRC
crc = _crc_xmodem_update(crc, tmp);
crc = _crc_xmodem_update(crc, tmp);
#endif
}
}
// Wait until the first CRC byte is received
loop_until_bit_is_set(SPSR, SPIF);
// Check CRC
recvcrc = (SPDR << 8) + spiTransferByte(0xff);
#ifdef CONFIG_SD_DATACRC
@@ -586,7 +611,6 @@ DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
continue;
}
#endif
break;
}
deselectCard(drv);