SD native mode bitbanging (4-bit). No write support yet

This commit is contained in:
ikari
2010-11-22 00:46:56 +01:00
parent 254b602529
commit c5ff79a9d2
21 changed files with 1780 additions and 486 deletions

View File

@@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c sdcard.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c
# List Assembler source files here.

View File

@@ -1,7 +1,7 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#define VER "0.0.1"
#define VER "0.0.1(NSFW)"
#define IN_AHBRAM __attribute__ ((section(".ahbram")))

View File

@@ -33,7 +33,6 @@
WCHAR ff_convert(WCHAR w, UINT dir) {
return w;
}*/
void file_init() {
file_res=f_mount(0, &fatfs);
}
@@ -44,6 +43,9 @@ void file_open_by_filinfo(FILINFO* fno) {
void file_open(uint8_t* filename, BYTE flags) {
file_res = f_open(&file_handle, (TCHAR*)filename, flags);
file_block_off = sizeof(file_buf);
file_block_max = sizeof(file_buf);
file_status = file_res ? FILE_ERR : FILE_OK;
}
void file_close() {
@@ -79,3 +81,12 @@ UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
file_res = f_write(&file_handle, buf, size, &bytes_written);
return bytes_written;
}
uint8_t file_getc() {
if(file_block_off == file_block_max) {
file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
file_block_off = 0;
}
return file_buf[file_block_off++];
}

View File

@@ -29,11 +29,15 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "ff.h"
enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF };
BYTE file_buf[512];
FATFS fatfs;
FIL file_handle;
FRESULT file_res;
uint8_t file_lfn[258];
uint16_t file_block_off, file_block_max;
enum filestates file_status;
void file_init(void);
void file_open(uint8_t* filename, BYTE flags);
@@ -43,4 +47,6 @@ UINT file_read(void);
UINT file_write(void);
UINT file_readblock(void* buf, uint32_t addr, uint16_t size);
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size);
uint8_t file_getc(void);
#endif

View File

@@ -170,22 +170,22 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
numentries++;
if(pass) {
if(mkdb) {
snes_romprops_t romprops;
/* snes_romprops_t romprops; */
path[len]='/';
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
uint16_t pathlen = strlen(path);
switch(type) {
case TYPE_SMC:
/* file_open_by_filinfo(&fno);
/* file_open_by_filinfo(&fno);
if(file_res){
printf("ZOMG NOOOO %d\n", file_res);
}
smc_id(&romprops);
file_close();
*/
file_close(); */
/* 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(romprops) + sizeof(len) + pathlen + 1))&0xffff)) {
if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(fno.fsize) + 1))&0xffff)) {
printf("switch! old=%lx ", db_tgt);
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
@@ -195,11 +195,13 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
dir_tgt += 4;
/* save element:
- index of last slash character
- file name */
- file name
- file size */
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
sram_writebyte(len+1, db_tgt);
sram_writeblock(path, db_tgt + sizeof(len), pathlen + 1);
db_tgt += sizeof(len) + pathlen + 1;
sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
db_tgt += sizeof(len) + pathlen + sizeof(fno.fsize) + 1;
break;
case TYPE_UNKNOWN:
default:
@@ -222,6 +224,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
}
} else uart_putc(0x30+res);
}
printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
sram_writelong(db_tgt, SRAM_DB_ADDR+4);
sram_writelong(dir_end, SRAM_DB_ADDR+8);
return crc;

View File

@@ -51,6 +51,7 @@
#include "spi.h"
#include "led.h"
#include "timer.h"
#include "rle.h"
void fpga_set_prog_b(uint8_t val) {
if(val)
@@ -95,6 +96,7 @@ void fpga_postinit() {
void fpga_pgm(uint8_t* filename) {
int MAXRETRIES = 10;
int retries = MAXRETRIES;
uint8_t data;
do {
fpga_set_prog_b(0);
uart_putc('P');
@@ -103,7 +105,6 @@ void fpga_pgm(uint8_t* filename) {
LPC_GPIO2->FIOMASK1 = ~(BV(0));
uart_putc('p');
UINT bytes_read;
/* open configware file */
file_open(filename, FA_READ);
@@ -112,14 +113,13 @@ void fpga_pgm(uint8_t* filename) {
uart_putc(0x30+file_res);
return;
}
uart_putc('C');
for (;;) {
bytes_read = file_read();
if (file_res || bytes_read == 0) break; /* error or eof */
for(int i=0; i<bytes_read; i++) {
FPGA_SEND_BYTE_SERIAL(file_buf[i]);
}
data = rle_file_getc();
if (file_status || file_res) break; /* error or eof */
FPGA_SEND_BYTE_SERIAL(data);
}
uart_putc('c');
file_close();
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {

View File

@@ -22,6 +22,7 @@
#include "cic.h"
#include "tests.h"
#include "cli.h"
#include "sdnative.h"
#define EMC0TOGGLE (3<<4)
#define MR0R (1<<1)
@@ -40,7 +41,7 @@ int main(void) {
LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */
| BV(3) | BV(5); /* SSP0 (FPGA) except SS */
LPC_PINCON->PINSEL0 = BV(31) /* SSP0 */
| BV(13) | BV(15) | BV(17) | BV(19) /* SSP1 (SD) */
/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */
| BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
/* pull-down CIC data lines */
@@ -58,7 +59,10 @@ int main(void) {
/* do this last because the peripheral init()s change PCLK dividers */
clock_init();
sd_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);
@@ -82,7 +86,7 @@ int main(void) {
LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1;
fpga_init();
fpga_pgm((uint8_t*)"/sd2snes/main.bit");
fpga_pgm((uint8_t*)"/main.bit.rle");
restart:
if(get_cic_state() == CIC_PAIR) {
printf("PAIR MODE ENGAGED!\n");
@@ -102,6 +106,7 @@ restart:
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
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)) {
/* generate fs footprint (interesting files only) */
uint32_t curr_dir_id = scan_dir(fs_path, 0, 0);
@@ -159,7 +164,6 @@ restart:
printf("test sram\n");
while(!sram_reliable());
printf("ok\n");
sram_hexdump(SRAM_DB_ADDR, 0x200);
while(!cmd) {
cmd=menu_main_loop();

View File

@@ -174,6 +174,8 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
}
f_lseek(&file_handle, romprops.offset);
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0x91); /* write w/ increment */
for(;;) {
/* SPI_OFFLOAD=1; */
bytes_read = file_read();
@@ -183,14 +185,13 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
/* bounce_busy_led(); */
uart_putc('.');
}
FPGA_SELECT();
FPGA_TX_BYTE(0x91); /* write w/ increment */
for(int j=0; j<bytes_read; j++) {
FPGA_TX_BYTE(file_buf[j]);
}
FPGA_TX_BYTE(0x00); /* dummy tx for increment+write pulse */
FPGA_DESELECT();
// for(int j=0; j<bytes_read; j++) {
// FPGA_TX_BYTE(file_buf[j]);
// }
FPGA_TX_BLOCK(file_buf, 512);
}
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);

790
src/sdnative.c Normal file
View File

@@ -0,0 +1,790 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <arm/bits.h>
#include <stdio.h>
#include "config.h"
#include "crc.h"
#include "diskio.h"
#include "spi.h"
#include "timer.h"
#include "uart.h"
#include "led.h"
#include "sdnative.h"
#include "fileops.h"
#define MAX_CARDS 1
// SD/MMC commands
#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define SWITCH_FUNC 6
#define SEND_IF_COND 8
#define SEND_CSD 9
#define SEND_CID 10
#define STOP_TRANSMISSION 12
#define SEND_STATUS 13
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define READ_MULTIPLE_BLOCK 18
#define WRITE_BLOCK 24
#define WRITE_MULTIPLE_BLOCK 25
#define PROGRAM_CSD 27
#define SET_WRITE_PROT 28
#define CLR_WRITE_PROT 29
#define SEND_WRITE_PROT 30
#define ERASE_WR_BLK_STAR_ADDR 32
#define ERASE_WR_BLK_END_ADDR 33
#define ERASE 38
#define LOCK_UNLOCK 42
#define APP_CMD 55
#define GEN_CMD 56
#define READ_OCR 58
#define CRC_ON_OFF 59
// SD ACMDs
#define SD_STATUS 13
#define SD_SEND_NUM_WR_BLOCKS 22
#define SD_SET_WR_BLK_ERASE_COUNT 23
#define SD_SEND_OP_COND 41
#define SD_SET_CLR_CARD_DETECT 42
#define SD_SEND_SCR 51
// R1 status bits
#define STATUS_IN_IDLE 1
#define STATUS_ERASE_RESET 2
#define STATUS_ILLEGAL_COMMAND 4
#define STATUS_CRC_ERROR 8
#define STATUS_ERASE_SEQ_ERROR 16
#define STATUS_ADDRESS_ERROR 32
#define STATUS_PARAMETER_ERROR 64
/* Card types - cardtype == 0 is MMC */
#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
5 Clock P0.7
7 DAT0/DO P0.8
8 DAT1/IRQ P1.14
9 DAT2/NC P1.15
*/
/* SD init procedure
=================
- initial clock frequency: ~100kHz
- cycle the clock for at least 74 cycles (some more may be safer)
- send CMD0
- send CMD8 (SEND_OP_COND); if no response -> HCS=0; else HCS=1
- send ACMD41 until OCR[31] (busy) becomes 1 (means: ready)
- if OCR[30] (CCS) set -> SDHC; else SDSC
- send CMD2 (read CID) (maybe log some stuff from the CID)
- send CMD3 (read RCA), store RCA
== end of initialisation ==
- send CMD9 (read CSD) with RCA, maybe do sth with TRAN_SPEED
- send CMD7 with RCA, select card, put card in tran
- maybe send CMD13 with RCA to check state (tran)
- send ACMD51 with RCA to read SCR (maybe, to check 4bit support)
- increase clock speed
- send ACMD6 with RCA to set 4bit bus width
- send transfer cmds
*/
/*
static CMD payloads. (no CRC calc required)
- CMD0: 0x40 0x00 0x00 0x00 0x00 0x95
- CMD8: 0x48 0x00 0x00 0x01 0xaa 0x87
- CMD2: 0x42 0x00 0x00 0x00 0x00 0x4d
- CMD3: 0x43 0x00 0x00 0x00 0x00 0x21
- CMD55: 0x77 0x00 0x00 0x00 0x00 0x65
*/
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;
int during_blocktrans = 0;
uint32_t last_block = 0;
/**
* getbits - read value from bit buffer
* @buffer: pointer to the data buffer
* @start : index of the first bit in the value
* @bits : number of bits in the value
*
* This function returns a value from the memory region passed as
* buffer, starting with bit "start" and "bits" bit long. The buffer
* is assumed to be MSB first, passing 0 for start will read starting
* from the highest-value bit of the first byte of the buffer.
*/
static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
uint8_t *buf = buffer;
uint32_t result = 0;
if ((start % 8) != 0) {
/* Unaligned start */
result += buf[start / 8] & (0xff >> (start % 8));
bits -= 8 - (start % 8);
start += 8 - (start % 8);
}
while (bits >= 8) {
result = (result << 8) + buf[start / 8];
start += 8;
bits -= 8;
}
if (bits > 0) {
result = result << bits;
result = result + (buf[start / 8] >> (8-bits));
} else if (bits < 0) {
/* Fraction of a single byte */
result = result >> -bits;
}
return result;
}
static inline void wiggle_slow_pos(uint16_t times) {
while(times--) {
delay_us(5);
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
delay_us(5);
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
}
}
static inline void wiggle_slow_neg(uint16_t times) {
while(times--) {
delay_us(5);
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
delay_us(5);
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
}
}
static inline void wiggle_fast_pos(uint16_t times) {
while(times--) {
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
}
}
static inline void wiggle_fast_neg(uint16_t times) {
while(times--) {
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
}
}
/*
send_command_slow
send SD command and put response in rsp.
returns length of response or 0 if there was no response
*/
int send_command_slow(uint8_t* cmd, uint8_t* rsp){
uint8_t shift, i=6;
int rsplen;
// printf("send_command_slow: sending CMD:\n");
wiggle_slow_pos(5);
// uart_trace(cmd, 0, 6);
switch(*cmd & 0x3f) {
case 0:
rsplen = 0;
break;
case 2:
case 9:
case 10:
rsplen = 17;
break;
default:
rsplen = 6;
}
/* send command */
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
while(i--) {
shift = 8;
do {
shift--;
uint8_t data = *cmd;
*cmd<<=1;
if(data&0x80) {
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
} else {
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
}
wiggle_slow_pos(1);
} while (shift);
cmd++;
}
wiggle_slow_pos(1);
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
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) {
return 0; /* no response within timeout */
}
i=rsplen;
while(i--) {
shift = 8;
uint8_t data=0;
do {
shift--;
data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift;
wiggle_slow_neg(1);
} while (shift);
*rsp=data;
rsp++;
}
}
return rsplen;
}
/*
send_command_fast
send SD command and put response in rsp.
returns length of response or 0 if there was no response
*/
int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
uint8_t datshift=8, cmdshift, i=6;
int rsplen, dat=0, datcnt=512, j=0;
static int state=0;
// printf("send_command_fast: sending CMD:\n");
wiggle_fast_pos(5);
// uart_trace(cmd, 0, 6);
switch(*cmd & 0x3f) {
case 0:
rsplen = 0;
break;
case 2:
case 9:
case 10:
rsplen = 17;
break;
case 17:
case 18:
dat = 1;
default:
rsplen = 6;
}
if(dat && (buf==NULL)) {
printf("error: buf is null but data transfer expected.\n");
return 0;
}
/* send command */
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
while(i--) {
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;
}
wiggle_fast_pos(1);
} while (cmdshift);
cmd++;
}
wiggle_fast_pos(1);
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
if(rsplen) {
uint16_t timeout=65535;
/* wait for responsebob */
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
wiggle_fast_neg(1);
}
// printf("timeout=%d\n", timeout);
if(!timeout) {
return 0; /* no response within timeout */
}
i=rsplen;
uint8_t cmddata=0, datdata=0;
while(i--) { /* process response */
cmdshift = 8;
do {
if(dat) {
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
// printf("data start\n");
j=datcnt;
state=1;
break;
}
}
cmdshift--;
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
wiggle_fast_neg(1);
} while (cmdshift);
if(state==1)break;
*rsp=cmddata;
cmddata=0;
rsp++;
}
if(state==1) { /* process response+data */
int startbit=1;
printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j);
datshift=8;
while(1) {
cmdshift--;
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
if(!cmdshift) {
cmdshift=8;
*rsp=cmddata;
cmddata=0;
rsp++;
i--;
if(!i) {
printf("response end\n");
if(j) state=2; /* response over, remaining data */
break;
}
}
if(!startbit) {
datshift--;
datdata |= (BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift;
if(!datshift) {
datshift=8;
*buf=datdata;
datdata=0;
buf++;
j--;
if(!j) break;
}
}
startbit=0;
wiggle_fast_neg(1);
}
}
if(dat && state!=2) { /* response ended before data */
state=2;
j=datcnt;
datshift=8;
// printf("response over, waiting for data...\n");
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg(1);
}
wiggle_fast_neg(1); /* eat the start bit */
}
if(state==2) { /* transfer rest of data */
// printf("remaining data: %d\n", j);
while(1) {
datshift-=4;
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
if(!datshift) {
datshift=8;
*buf=datdata;
datdata=0;
buf++;
j--;
if(!j) break;
}
wiggle_fast_neg(1);
}
}
/* just eat the crcs for now */
wiggle_fast_neg(17);
state=3;
}
return rsplen;
}
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]);
cmd[5]=crc7update(cmd[5], cmd[3]);
cmd[5]=crc7update(cmd[5], cmd[4]);
cmd[5]=(cmd[5] << 1) | 1;
}
void stream_datablock(uint8_t* buf) {
uint8_t datshift=8;
int j=512;
uint8_t datdata=0;
uint16_t timeout=65535;
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
wiggle_fast_neg(1);
}
wiggle_fast_neg(1); /* eat the start bit */
while(1) {
datshift-=4;
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
if(!datshift) {
datshift=8;
*buf=datdata;
datdata=0;
buf++;
j--;
if(!j) break;
}
wiggle_fast_neg(1);
}
/* eat the crc for now */
wiggle_fast_neg(17);
}
void read_block(uint32_t address, uint8_t* buf) {
if(during_blocktrans && (last_block == address-1)) {
stream_datablock(buf);
last_block=address;
} else {
if(during_blocktrans) {
/* send STOP_TRANSMISSION */
cmd[0]=0x40+STOP_TRANSMISSION;
cmd[1]=0;
cmd[2]=0;
cmd[3]=0;
cmd[4]=0;
cmd[5]=0x61;
send_command_fast(cmd, rsp, NULL);
}
last_block=address;
if(!ccs) address <<= 9;
cmd[0]=0x40+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);
during_blocktrans = 1;
}
// uart_trace(buf, 0, 512);
}
//
// Public functions
//
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
uint8_t sec;
if(drv >= MAX_CARDS) {
return RES_PARERR;
}
for(sec=0; sec<count; sec++) {
read_block(sector+sec, buffer);
buffer+=512;
}
return RES_OK;
}
DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_read")));
DRESULT sdn_initialize(BYTE drv) {
uint8_t cmd[6]={0,0,0,0,0,0}; /* command */
uint8_t rsp[17]; /* space for response */
int rsplen;
uint8_t hcs=0, data;
if(drv>=MAX_CARDS)
return STA_NOINIT|STA_NODISK;
data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
/* if the card is sending data from before a reset we try to deselect it
prior to initialization */
for(rsplen=0; rsplen<1042; rsplen++) {
if((data != BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
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");
}
}
data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
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);
}
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);
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 {
printf("ACMD41 no response!\n");
}
if(rsp[1]&0x80) break;
}
ccs = (rsp[1]>>6) & 1; /* SDHC */
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);
} else {
printf("CMD3 no response!\n");
rca1=0;
rca2=0;
}
cmd[0]=0x40+9;
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
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);
if((rsplen=send_command_slow(cmd, rsp))) {
// printf("CMD7 response:\n");
// uart_trace(rsp, 0, rsplen);
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);
if((rsplen=send_command_fast(cmd, rsp, NULL))) {
// printf("CMD13 response:\n");
// uart_trace(rsp, 0, rsplen);
} else {
printf("CMD13 no response!\n");
}
cmd[0]=0x40+55;
cmd[1]=rca1;
cmd[2]=rca2;
cmd[3]=0;
cmd[4]=0;
make_crc7(cmd);
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+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);
return sdn_status(drv);
}
DSTATUS disk_initialize(BYTE drv) __attribute__ ((weak, alias("sdn_initialize")));
void sdn_init(void) {
/* enable GPIO interrupt on SD detect pin, both edges */
NVIC_EnableIRQ(EINT3_IRQn);
SD_DT_INT_SETUP();
/* disconnect SSP1 */
LPC_PINCON->PINSEL0 &= ~(BV(13) | BV(15) | BV(17) | BV(19));
/* prepare GPIOs */
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1;
}
void disk_init(void) __attribute__ ((weak, alias("sdn_init")));
DSTATUS sdn_status(BYTE drv) {
if (SDCARD_DETECT)
if (SDCARD_WP)
return STA_PROTECT;
else
return RES_OK;
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)
return RES_NOTRDY;
if (sdn_status(drv) & STA_NODISK)
return RES_NOTRDY;
if (page != 0)
return RES_ERROR;
if (ccs) {
/* Special CSD for SDHC cards */
capacity = (1 + getbits(csd,127-69+8,22)) * 1024;
} else {
/* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */
uint8_t exponent = 2 + getbits(csd, 127-49+8, 3);
capacity = 1 + getbits(csd, 127-73+8, 12);
exponent += getbits(csd, 127-83+8,4) - 9;
while (exponent--) capacity *= 2;
}
diskinfo0_t *di = buffer;
di->validbytes = sizeof(diskinfo0_t);
di->disktype = DISK_TYPE_SD;
di->sectorsize = 2;
di->sectorcount = capacity;
return RES_OK;
}
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
return RES_OK;
}
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write")));
/* Detect changes of SD card 0 */
void sdn_changed() {
if (SDCARD_DETECT)
disk_state = DISK_CHANGED;
else
disk_state = DISK_REMOVED;
}

19
src/sdnative.h Normal file
View File

@@ -0,0 +1,19 @@
/* DISCLAIMER */
#ifndef SDNATIVE_H
#define SDNATIVE_H
#include "diskio.h"
/* These functions are weak-aliased to disk_... */
void sdn_init(void);
DSTATUS sdn_status(BYTE drv);
DSTATUS sdn_initialize(BYTE drv);
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer);
void sdn_changed(void);
#endif

View File

@@ -98,7 +98,7 @@ void smc_id(snes_romprops_t* props) {
}
}
}
printf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); // */
//printf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); // */
if(score>=maxscore) {
score_idx=num;
maxscore=score;
@@ -166,7 +166,6 @@ printf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); // */
props->ramsize_bytes = 0;
}
/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
f_lseek(&file_handle, 0);
}
uint8_t smc_headerscore(snes_header_t* header) {

View File

@@ -154,7 +154,7 @@ void spi_tx_block(const void *ptr, unsigned int length, int device) {
ssp_props *ssp = &(SSP_SEL[device]);
while (length--) {
/* Wait until TX fifo can accept data */
/* Wait until TX fifo can accept data */
while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ;
ssp->SSP_REGS->DR = *data++;

View File

@@ -47,11 +47,9 @@ void timer_init(void) {
BITBAND(LPC_SC->PCLKSEL1, 26) = 1;
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1;
/* enable SysTick */
// XXX SysTick_Config(SysTick->CALIB & SysTick_CALIB_TENMS_Msk);
SysTick_Config(SysTick->CALIB & SysTick_CALIB_TENMS_Msk);
}
extern int testval;
void delay_us(unsigned int time) {
/* Prepare RIT */
LPC_RIT->RICOUNTER = 0;