SD native write support (still needs error handling), DB creation update (display file sizes)
This commit is contained in:
@@ -73,7 +73,7 @@ ASRC = startup.S crc.S
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
# Use s -mcall-prologues when you really need size...
|
||||
#OPT = 2
|
||||
OPT = s
|
||||
OPT = 2
|
||||
|
||||
# Debugging format.
|
||||
DEBUG = dwarf-2
|
||||
|
||||
19
src/config.h
19
src/config.h
@@ -36,13 +36,11 @@
|
||||
#define CONFIG_UART_BAUDRATE 921600
|
||||
#define CONFIG_UART_DEADLOCKABLE
|
||||
|
||||
#define SPI_SD 1
|
||||
#define SPI_FPGA 0
|
||||
#define SSP_CLK_DIVISOR_FAST 4
|
||||
#define SSP_CLK_DIVISOR_SLOW 250
|
||||
|
||||
#define SSP_CLK_DIVISOR_FAST 4
|
||||
#define SSP_CLK_DIVISOR_SLOW 250
|
||||
#define SSP_CLK_DIVISOR_FPGA_FAST 6
|
||||
#define SSP_CLK_DIVISOR_FPGA_SLOW 16
|
||||
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
|
||||
|
||||
#define SNES_RESET_REG LPC_GPIO1
|
||||
#define SNES_RESET_BIT 29
|
||||
@@ -62,4 +60,15 @@
|
||||
|
||||
#define QSORT_MAXELEM 1024
|
||||
|
||||
#define SSP_REGS LPC_SSP0
|
||||
#define SSP_PCLKREG PCLKSEL1
|
||||
// 1: PCLKSEL0
|
||||
#define SSP_PCLKBIT 10
|
||||
// 1: 20
|
||||
#define SSP_DMAID_TX 0
|
||||
// 1: 2
|
||||
#define SSP_DMAID_RX 1
|
||||
// 1: 3
|
||||
#define SSP_DMACH LPC_GPDMACH0
|
||||
|
||||
#endif
|
||||
|
||||
1
src/ff.c
1
src/ff.c
@@ -2174,6 +2174,7 @@ FRESULT f_read (
|
||||
if (cc) { /* Read maximum contiguous sectors directly */
|
||||
if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
|
||||
cc = fp->fs->csize - csect;
|
||||
/* XXX OFFLOAD GOES HERE */
|
||||
if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
|
||||
ABORT(fp->fs, FR_DISK_ERR);
|
||||
#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
filetypes.c: directory scanning and file type detection
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
@@ -71,6 +70,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
|
||||
uint16_t numentries;
|
||||
uint32_t dirsize;
|
||||
uint8_t pass = 0;
|
||||
char buf[10];
|
||||
|
||||
dir_tgt = this_dir_tgt;
|
||||
if(depth==0) {
|
||||
@@ -198,10 +198,12 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
|
||||
- file name
|
||||
- file size */
|
||||
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
|
||||
sram_writebyte(len+1, db_tgt);
|
||||
sram_writeblock(path, db_tgt + sizeof(len), pathlen + 1);
|
||||
sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
|
||||
db_tgt += sizeof(len) + pathlen + sizeof(fno.fsize) + 1;
|
||||
snprintf(buf, sizeof(buf), " % 7ldk", fno.fsize/1024);
|
||||
sram_writeblock(buf, db_tgt, sizeof(buf)-1);
|
||||
sram_writebyte(len+1, db_tgt + sizeof(buf)-1);
|
||||
sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1);
|
||||
// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
|
||||
db_tgt += sizeof(len) + pathlen + sizeof(buf)-1 + 1;
|
||||
break;
|
||||
case TYPE_UNKNOWN:
|
||||
default:
|
||||
@@ -224,7 +226,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
|
||||
}
|
||||
} else uart_putc(0x30+res);
|
||||
}
|
||||
printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
|
||||
// printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
|
||||
sram_writelong(db_tgt, SRAM_DB_ADDR+4);
|
||||
sram_writelong(dir_end, SRAM_DB_ADDR+8);
|
||||
return crc;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
#include "timer.h"
|
||||
|
||||
void fpga_spi_init(void) {
|
||||
spi_init(SPI_SPEED_FPGA_FAST, SPI_FPGA);
|
||||
spi_init(SPI_SPEED_FPGA_FAST);
|
||||
}
|
||||
|
||||
void set_mcu_addr(uint32_t address) {
|
||||
|
||||
@@ -36,15 +36,15 @@
|
||||
#define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
|
||||
#define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
|
||||
|
||||
#define FPGA_TX_SYNC() spi_tx_sync(SPI_FPGA)
|
||||
#define FPGA_TX_BYTE(x) spi_tx_byte(x, SPI_FPGA)
|
||||
#define FPGA_RX_BYTE() spi_rx_byte(SPI_FPGA)
|
||||
#define FPGA_TXRX_BYTE(x) spi_txrx_byte(x, SPI_FPGA)
|
||||
#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y,SPI_FPGA)
|
||||
#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y,SPI_FPGA)
|
||||
#define FPGA_TX_SYNC() spi_tx_sync()
|
||||
#define FPGA_TX_BYTE(x) spi_tx_byte(x)
|
||||
#define FPGA_RX_BYTE() spi_rx_byte()
|
||||
#define FPGA_TXRX_BYTE(x) spi_txrx_byte(x)
|
||||
#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y)
|
||||
#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y)
|
||||
|
||||
#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST, SPI_FPGA)
|
||||
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW, SPI_FPGA)
|
||||
#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST)
|
||||
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW)
|
||||
|
||||
void fpga_spi_init(void);
|
||||
void fpga_spi_test(void);
|
||||
|
||||
24
src/main.c
24
src/main.c
@@ -10,7 +10,6 @@
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
#include "spi.h"
|
||||
#include "sdcard.h"
|
||||
#include "fileops.h"
|
||||
#include "fpga.h"
|
||||
#include "fpga_spi.h"
|
||||
@@ -23,6 +22,7 @@
|
||||
#include "tests.h"
|
||||
#include "cli.h"
|
||||
#include "sdnative.h"
|
||||
#include "crc.h"
|
||||
|
||||
#define EMC0TOGGLE (3<<4)
|
||||
#define MR0R (1<<1)
|
||||
@@ -54,15 +54,13 @@ int main(void) {
|
||||
timer_init();
|
||||
uart_init();
|
||||
fpga_spi_init();
|
||||
spi_preinit(SPI_FPGA);
|
||||
spi_preinit(SPI_SD);
|
||||
spi_preinit();
|
||||
/* do this last because the peripheral init()s change PCLK dividers */
|
||||
clock_init();
|
||||
|
||||
// sd_init();
|
||||
sdn_init();
|
||||
// while(1);
|
||||
|
||||
fpga_spi_init();
|
||||
delay_ms(10);
|
||||
printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
|
||||
@@ -105,6 +103,16 @@ restart:
|
||||
uint32_t mem_dir_id = sram_readlong(SRAM_DIRID);
|
||||
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
|
||||
|
||||
/* printf("savetest...");
|
||||
int i;
|
||||
uint16_t testcrc = 0;
|
||||
for(i=0; i<128; i++) {
|
||||
testcrc = crc_xmodem_update(testcrc, 0xff);
|
||||
}
|
||||
printf("testcrc = %04x\n", testcrc);
|
||||
save_sram((uint8_t*)"/pretty long filename here you know.bin", 0x400000, SRAM_DB_ADDR);
|
||||
printf("it's over!\n");
|
||||
while(1)cli_entrycheck(); */
|
||||
printf("mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id);
|
||||
mem_magic=0x12938712; /* always rescan card for now */
|
||||
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
|
||||
@@ -142,7 +150,6 @@ restart:
|
||||
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
|
||||
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
|
||||
}
|
||||
|
||||
/* load menu */
|
||||
uart_putc('(');
|
||||
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
|
||||
@@ -161,19 +168,23 @@ restart:
|
||||
snes_reset(0);
|
||||
|
||||
uint8_t cmd = 0;
|
||||
uint32_t filesize=0;
|
||||
printf("test sram\n");
|
||||
while(!sram_reliable());
|
||||
printf("ok\n");
|
||||
sram_hexdump(SRAM_DB_ADDR, 0x200);
|
||||
|
||||
while(!cmd) {
|
||||
cmd=menu_main_loop();
|
||||
printf("derp %d\n", cmd);
|
||||
sleep_ms(50);
|
||||
uart_putc('-');
|
||||
switch(cmd) {
|
||||
case SNES_CMD_LOADROM:
|
||||
get_selected_name(file_lfn);
|
||||
set_mcu_ovr(1);
|
||||
printf("Selected name: %s\n", file_lfn);
|
||||
load_rom(file_lfn, SRAM_ROM_ADDR);
|
||||
filesize = load_rom(file_lfn, SRAM_ROM_ADDR);
|
||||
if(romprops.ramsize_bytes) {
|
||||
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
|
||||
printf("SRM file: %s\n", file_lfn);
|
||||
@@ -181,6 +192,7 @@ sram_hexdump(SRAM_DB_ADDR, 0x200);
|
||||
} else {
|
||||
printf("No SRAM\n");
|
||||
}
|
||||
save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR);
|
||||
set_mcu_ovr(0);
|
||||
snes_reset(1);
|
||||
delay_ms(100);
|
||||
|
||||
335
src/sdnative.c
335
src/sdnative.c
@@ -120,7 +120,10 @@ uint8_t csd[17];
|
||||
uint8_t ccs=0;
|
||||
uint8_t rca1, rca2;
|
||||
|
||||
int during_blocktrans = 0;
|
||||
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
|
||||
enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT };
|
||||
|
||||
int during_blocktrans = TRANS_NONE;
|
||||
uint32_t last_block = 0;
|
||||
|
||||
/**
|
||||
@@ -161,18 +164,18 @@ static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
|
||||
|
||||
static inline void wiggle_slow_pos(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(5);
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
delay_us(5);
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_slow_neg(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(5);
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
delay_us(5);
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
@@ -191,6 +194,18 @@ static inline void wiggle_fast_neg(uint16_t times) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_neg1(void) {
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_pos1(void) {
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
send_command_slow
|
||||
@@ -272,10 +287,10 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
|
||||
*/
|
||||
int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
uint8_t datshift=8, cmdshift, i=6;
|
||||
int rsplen, dat=0, datcnt=512, j=0;
|
||||
static int state=0;
|
||||
int rsplen, dat=0, waitbusy=0, datcnt=512, j=0;
|
||||
static int state=CMD_RSP;
|
||||
// printf("send_command_fast: sending CMD:\n");
|
||||
wiggle_fast_pos(5);
|
||||
wiggle_fast_pos(9);
|
||||
// uart_trace(cmd, 0, 6);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 0:
|
||||
@@ -286,15 +301,18 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
case 10:
|
||||
rsplen = 17;
|
||||
break;
|
||||
case 12:
|
||||
rsplen = 6;
|
||||
waitbusy = 1;
|
||||
break;
|
||||
case 17:
|
||||
case 18:
|
||||
dat = 1;
|
||||
default:
|
||||
rsplen = 6;
|
||||
}
|
||||
|
||||
if(dat && (buf==NULL)) {
|
||||
printf("error: buf is null but data transfer expected.\n");
|
||||
printf("send_command_fast error: buf is null but data transfer expected.\n");
|
||||
return 0;
|
||||
}
|
||||
/* send command */
|
||||
@@ -311,7 +329,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
} else {
|
||||
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos(1);
|
||||
wiggle_fast_pos1();
|
||||
} while (cmdshift);
|
||||
cmd++;
|
||||
}
|
||||
@@ -323,7 +341,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
uint16_t timeout=65535;
|
||||
/* wait for responsebob */
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
// printf("timeout=%d\n", timeout);
|
||||
if(!timeout) {
|
||||
@@ -339,13 +357,13 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
// printf("data start\n");
|
||||
j=datcnt;
|
||||
state=1;
|
||||
state=CMD_RSPDAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmdshift--;
|
||||
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
} while (cmdshift);
|
||||
if(state==1)break;
|
||||
*rsp=cmddata;
|
||||
@@ -353,7 +371,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
rsp++;
|
||||
}
|
||||
|
||||
if(state==1) { /* process response+data */
|
||||
if(state==CMD_RSPDAT) { /* process response+data */
|
||||
int startbit=1;
|
||||
printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j);
|
||||
datshift=8;
|
||||
@@ -368,14 +386,15 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
i--;
|
||||
if(!i) {
|
||||
printf("response end\n");
|
||||
if(j) state=2; /* response over, remaining data */
|
||||
if(j) state=CMD_DAT; /* response over, remaining data */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!startbit) {
|
||||
datshift--;
|
||||
datdata |= (BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift;
|
||||
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*buf=datdata;
|
||||
@@ -386,42 +405,69 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
}
|
||||
}
|
||||
startbit=0;
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
}
|
||||
|
||||
if(dat && state!=2) { /* response ended before data */
|
||||
state=2;
|
||||
if(dat && state != CMD_DAT) { /* response ended before data */
|
||||
state=CMD_DAT;
|
||||
j=datcnt;
|
||||
datshift=8;
|
||||
// printf("response over, waiting for data...\n");
|
||||
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg(1); /* eat the start bit */
|
||||
wiggle_fast_neg1(); /* eat the start bit */
|
||||
}
|
||||
|
||||
if(state==2) { /* transfer rest of data */
|
||||
if(state==CMD_DAT) { /* transfer rest of data */
|
||||
// printf("remaining data: %d\n", j);
|
||||
while(1) {
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
if(datshift==8) {
|
||||
while(1) {
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
|
||||
wiggle_fast_neg1();
|
||||
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
wiggle_fast_neg(1);
|
||||
} else {
|
||||
|
||||
while(1) {
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* just eat the crcs for now */
|
||||
wiggle_fast_neg(17);
|
||||
state=3;
|
||||
if(dat) wiggle_fast_neg(17);
|
||||
|
||||
if(waitbusy) {
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
}
|
||||
state=CMD_RSP;
|
||||
}
|
||||
return rsplen;
|
||||
}
|
||||
@@ -436,18 +482,19 @@ void make_crc7(uint8_t* cmd) {
|
||||
cmd[5]=(cmd[5] << 1) | 1;
|
||||
}
|
||||
|
||||
void stream_datablock(uint8_t* buf) {
|
||||
uint8_t datshift=8;
|
||||
void stream_datablock(uint8_t *buf) {
|
||||
// uint8_t datshift=8;
|
||||
int j=512;
|
||||
uint8_t datdata=0;
|
||||
uint16_t timeout=65535;
|
||||
|
||||
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
|
||||
wiggle_fast_neg(1);
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg(1); /* eat the start bit */
|
||||
wiggle_fast_neg1(); /* eat the start bit */
|
||||
|
||||
while(1) {
|
||||
/*
|
||||
datshift-=4;
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
@@ -460,20 +507,164 @@ void stream_datablock(uint8_t* buf) {
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
wiggle_fast_neg(1);
|
||||
*/
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
|
||||
|((SD_DAT1REG->FIOPIN >> 13) & 0x6)
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
|
||||
|
||||
wiggle_fast_neg1();
|
||||
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
|
||||
/* eat the crc for now */
|
||||
wiggle_fast_neg(17);
|
||||
}
|
||||
|
||||
void read_block(uint32_t address, uint8_t* buf) {
|
||||
if(during_blocktrans && (last_block == address-1)) {
|
||||
void send_datablock(uint8_t *buf) {
|
||||
uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512;
|
||||
uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift;
|
||||
//uart_trace(buf, 0, 512);
|
||||
wiggle_fast_pos(1);
|
||||
// printf("send_datablock: wait for card\n");
|
||||
/* wait - card might be busy */
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg(1);
|
||||
printf(".");
|
||||
}
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1;
|
||||
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos(1); /* send start bit to card */
|
||||
crcshift=8;
|
||||
while(cnt--) {
|
||||
datshift=8;
|
||||
do {
|
||||
datshift-=4;
|
||||
if(((*buf)>>datshift) & 0x8) {
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x4) {
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x2){
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x1){
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos(1);
|
||||
} while (datshift);
|
||||
|
||||
crcshift-=2;
|
||||
dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift;
|
||||
dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift;
|
||||
dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift;
|
||||
dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift;
|
||||
if(!crcshift) {
|
||||
crc0 = crc_xmodem_update(crc0, dat0);
|
||||
crc1 = crc_xmodem_update(crc1, dat1);
|
||||
crc2 = crc_xmodem_update(crc2, dat2);
|
||||
crc3 = crc_xmodem_update(crc3, dat3);
|
||||
crcshift=8;
|
||||
dat0=0;
|
||||
dat1=0;
|
||||
dat2=0;
|
||||
dat3=0;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
// printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3);
|
||||
/* send crcs */
|
||||
datshift=16;
|
||||
do {
|
||||
datshift--;
|
||||
if((crc0 >> datshift)&1) {
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
if((crc1 >> datshift)&1) {
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
}
|
||||
if((crc2 >> datshift)&1) {
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
}
|
||||
if((crc3 >> datshift)&1) {
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos(1);
|
||||
} while(datshift);
|
||||
/* send end bit */
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos(1);
|
||||
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
|
||||
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
|
||||
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
|
||||
|
||||
wiggle_fast_neg(4);
|
||||
dat0=0;
|
||||
|
||||
datshift=3;
|
||||
do {
|
||||
datshift--;
|
||||
dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift);
|
||||
wiggle_fast_neg(1);
|
||||
} while (datshift);
|
||||
|
||||
if(dat0!=2) {
|
||||
printf("crc error! %02x\n", dat0);
|
||||
while(1);
|
||||
}
|
||||
wiggle_fast_neg(1);
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg(1);
|
||||
}
|
||||
}
|
||||
|
||||
void read_block(uint32_t address, uint8_t *buf) {
|
||||
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
|
||||
stream_datablock(buf);
|
||||
last_block=address;
|
||||
} else {
|
||||
if(during_blocktrans) {
|
||||
/* send STOP_TRANSMISSION */
|
||||
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
|
||||
cmd[0]=0x40+STOP_TRANSMISSION;
|
||||
cmd[1]=0;
|
||||
cmd[2]=0;
|
||||
@@ -493,11 +684,40 @@ void read_block(uint32_t address, uint8_t* buf) {
|
||||
send_command_fast(cmd, rsp, buf);
|
||||
// uart_trace(cmd, 0, 6);
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
during_blocktrans = 1;
|
||||
during_blocktrans = TRANS_READ;
|
||||
}
|
||||
// uart_trace(buf, 0, 512);
|
||||
}
|
||||
|
||||
void write_block(uint32_t address, uint8_t* buf) {
|
||||
if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) {
|
||||
send_datablock(buf);
|
||||
last_block=address;
|
||||
} else {
|
||||
if(during_blocktrans) {
|
||||
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
|
||||
cmd[0]=0x40+STOP_TRANSMISSION;
|
||||
cmd[1]=0;
|
||||
cmd[2]=0;
|
||||
cmd[3]=0;
|
||||
cmd[4]=0;
|
||||
cmd[5]=0x61;
|
||||
send_command_fast(cmd, rsp, NULL);
|
||||
}
|
||||
last_block=address;
|
||||
if(!ccs) address <<= 9;
|
||||
cmd[0]=0x40+WRITE_MULTIPLE_BLOCK;
|
||||
cmd[1]=address>>24;
|
||||
cmd[2]=address>>16;
|
||||
cmd[3]=address>>8;
|
||||
cmd[4]=address;
|
||||
make_crc7(cmd);
|
||||
send_command_fast(cmd, rsp, NULL); /* only send cmd & get response */
|
||||
send_datablock(buf);
|
||||
during_blocktrans = TRANS_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Public functions
|
||||
//
|
||||
@@ -520,15 +740,14 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
uint8_t cmd[6]={0,0,0,0,0,0}; /* command */
|
||||
uint8_t rsp[17]; /* space for response */
|
||||
int rsplen;
|
||||
uint8_t hcs=0, data;
|
||||
uint8_t hcs=0;
|
||||
if(drv>=MAX_CARDS)
|
||||
return STA_NOINIT|STA_NODISK;
|
||||
|
||||
data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
|
||||
/* if the card is sending data from before a reset we try to deselect it
|
||||
prior to initialization */
|
||||
for(rsplen=0; rsplen<1042; rsplen++) {
|
||||
if((data != BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
for(rsplen=0; rsplen<2042; rsplen++) {
|
||||
if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
|
||||
printf("card seems to be sending data, attempting deselect\n");
|
||||
cmd[0]=0x40+7;
|
||||
cmd[1]=0;
|
||||
@@ -542,7 +761,6 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
printf("CMD7 deselect no response! D:\n");
|
||||
}
|
||||
}
|
||||
data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
cmd[0]=0x40+GO_IDLE_STATE;
|
||||
@@ -638,6 +856,7 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
cmd[4]=0;
|
||||
make_crc7(cmd);
|
||||
|
||||
/* record CSD for getinfo */
|
||||
if((rsplen=send_command_slow(cmd, csd))) {
|
||||
// printf("CMD9 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
@@ -652,6 +871,7 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
cmd[4]=0;
|
||||
make_crc7(cmd);
|
||||
|
||||
/* select the card */
|
||||
if((rsplen=send_command_slow(cmd, rsp))) {
|
||||
// printf("CMD7 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
@@ -667,6 +887,7 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
cmd[4]=0;
|
||||
make_crc7(cmd);
|
||||
|
||||
/* get card status */
|
||||
if((rsplen=send_command_fast(cmd, rsp, NULL))) {
|
||||
// printf("CMD13 response:\n");
|
||||
// uart_trace(rsp, 0, rsplen);
|
||||
@@ -674,6 +895,7 @@ DRESULT sdn_initialize(BYTE drv) {
|
||||
printf("CMD13 no response!\n");
|
||||
}
|
||||
|
||||
/* set bus width */
|
||||
cmd[0]=0x40+55;
|
||||
cmd[1]=rca1;
|
||||
cmd[2]=rca2;
|
||||
@@ -776,8 +998,21 @@ DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
|
||||
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
|
||||
|
||||
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
|
||||
return RES_OK;
|
||||
uint8_t sec;
|
||||
uint8_t *buf = (uint8_t*)buffer;
|
||||
if(drv >= MAX_CARDS) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if (sdn_status(drv) & STA_NODISK)
|
||||
return RES_NOTRDY;
|
||||
|
||||
for(sec=0; sec<count; sec++) {
|
||||
write_block(sector+sec, buf);
|
||||
buf+=512;
|
||||
}
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write")));
|
||||
|
||||
/* Detect changes of SD card 0 */
|
||||
|
||||
@@ -135,5 +135,5 @@ uint8_t menu_main_loop() {
|
||||
void get_selected_name(uint8_t* fn) {
|
||||
uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
|
||||
printf("fd addr=%lx\n", addr);
|
||||
sram_readblock(fn, addr+1+SRAM_MENU_ADDR, 256);
|
||||
sram_readblock(fn, addr+10+SRAM_MENU_ADDR, 256);
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ stat_getstring++;
|
||||
/* is directory link, name offset 6 */
|
||||
sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20);
|
||||
} else {
|
||||
/* is file link, name offset 65 */
|
||||
sram_readblock(ptr, addr+1+SRAM_MENU_ADDR, 20);
|
||||
/* is file link, name offset 10 */
|
||||
sram_readblock(ptr, addr+10+SRAM_MENU_ADDR, 20);
|
||||
}
|
||||
ptr[20]=0;
|
||||
}
|
||||
|
||||
167
src/spi.c
167
src/spi.c
@@ -36,174 +36,134 @@
|
||||
#define SSP_RFF 3 // Receive FIFO full
|
||||
#define SSP_BSY 4 // Busy
|
||||
|
||||
typedef struct {
|
||||
LPC_SSP_TypeDef *SSP_REGS;
|
||||
LPC_GPDMACH_TypeDef *SSP_DMACH;
|
||||
uint32_t *SSP_PCLKREG;
|
||||
int SSP_PCLKBIT;
|
||||
int SSP_DMAID_TX;
|
||||
int SSP_DMAID_RX;
|
||||
} ssp_props;
|
||||
|
||||
|
||||
static ssp_props SSP_SEL[2] = {
|
||||
{ LPC_SSP0, LPC_GPDMACH0, (uint32_t*)&(LPC_SC->PCLKSEL1), 10, 0, 1 }, /* SSP0 */
|
||||
{ LPC_SSP1, LPC_GPDMACH1, (uint32_t*)&(LPC_SC->PCLKSEL0), 20, 2, 3 } /* SSP1 */
|
||||
};
|
||||
|
||||
void spi_preinit(int device) {
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
void spi_preinit() {
|
||||
|
||||
/* Set clock prescaler to 1:1 */
|
||||
BITBAND(*(ssp->SSP_PCLKREG), ssp->SSP_PCLKBIT) = 1;
|
||||
BITBAND(LPC_SC->SSP_PCLKREG, SSP_PCLKBIT) = 1;
|
||||
}
|
||||
|
||||
void spi_init(spi_speed_t speed, int device) {
|
||||
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
void spi_init(spi_speed_t speed) {
|
||||
|
||||
/* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */
|
||||
ssp->SSP_REGS->CR0 = (8-1);
|
||||
SSP_REGS->CR0 = (8-1);
|
||||
|
||||
/* set clock prescaler */
|
||||
if (speed == SPI_SPEED_FAST) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
|
||||
} else if (speed == SPI_SPEED_SLOW) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
|
||||
} else if (speed == SPI_SPEED_FPGA_FAST) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
|
||||
} else {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
|
||||
}
|
||||
|
||||
/* Enable SSP */
|
||||
ssp->SSP_REGS->CR1 = BV(1);
|
||||
SSP_REGS->CR1 = BV(1);
|
||||
|
||||
/* Enable DMA controller, little-endian mode */
|
||||
BITBAND(LPC_SC->PCONP, 29) = 1;
|
||||
LPC_GPDMA->DMACConfig = 1;
|
||||
}
|
||||
|
||||
void spi_tx_sync(int device) {
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
void spi_tx_sync() {
|
||||
/* Wait until TX fifo is flushed */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
|
||||
}
|
||||
|
||||
void spi_tx_byte(uint8_t data, int device) {
|
||||
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
void spi_tx_byte(uint8_t data) {
|
||||
/* Wait until TX fifo can accept data */
|
||||
while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ;
|
||||
while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ;
|
||||
|
||||
/* Send byte */
|
||||
ssp->SSP_REGS->DR = data;
|
||||
SSP_REGS->DR = data;
|
||||
}
|
||||
|
||||
uint8_t spi_txrx_byte(uint8_t data, int device) {
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
uint8_t spi_txrx_byte(uint8_t data) {
|
||||
/* Wait until SSP is not busy */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
|
||||
|
||||
/* Clear RX fifo */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
|
||||
(void) ssp->SSP_REGS->DR;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_RNE))
|
||||
(void) SSP_REGS->DR;
|
||||
|
||||
/* Transmit a single dummy byte */
|
||||
ssp->SSP_REGS->DR = data;
|
||||
SSP_REGS->DR = data;
|
||||
|
||||
/* Wait until answer has been received */
|
||||
while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
|
||||
while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ;
|
||||
|
||||
return ssp->SSP_REGS->DR;
|
||||
return SSP_REGS->DR;
|
||||
}
|
||||
|
||||
uint8_t spi_rx_byte(int device) {
|
||||
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
uint8_t spi_rx_byte() {
|
||||
/* Wait until SSP is not busy */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
|
||||
|
||||
/* Clear RX fifo */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
|
||||
(void) ssp->SSP_REGS->DR;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_RNE))
|
||||
(void) SSP_REGS->DR;
|
||||
|
||||
/* Transmit a single dummy byte */
|
||||
ssp->SSP_REGS->DR = 0xff;
|
||||
SSP_REGS->DR = 0xff;
|
||||
|
||||
/* Wait until answer has been received */
|
||||
while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
|
||||
while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ;
|
||||
|
||||
return ssp->SSP_REGS->DR;
|
||||
return SSP_REGS->DR;
|
||||
}
|
||||
|
||||
void spi_tx_block(const void *ptr, unsigned int length, int device) {
|
||||
void spi_tx_block(const void *ptr, unsigned int length) {
|
||||
const uint8_t *data = (const uint8_t *)ptr;
|
||||
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
while (length--) {
|
||||
/* Wait until TX fifo can accept data */
|
||||
while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ;
|
||||
while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ;
|
||||
|
||||
ssp->SSP_REGS->DR = *data++;
|
||||
SSP_REGS->DR = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
void spi_rx_block(void *ptr, unsigned int length, int device) {
|
||||
void spi_rx_block(void *ptr, unsigned int length) {
|
||||
uint8_t *data = (uint8_t *)ptr;
|
||||
unsigned int txlen = length;
|
||||
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
/* Wait until SSP is not busy */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
|
||||
|
||||
/* Clear RX fifo */
|
||||
while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
|
||||
(void) ssp->SSP_REGS->DR;
|
||||
while (BITBAND(SSP_REGS->SR, SSP_RNE))
|
||||
(void) SSP_REGS->DR;
|
||||
|
||||
if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) {
|
||||
/* Odd length or unaligned buffer */
|
||||
while (length > 0) {
|
||||
/* Wait until TX or RX FIFO are ready */
|
||||
while (txlen > 0 && !BITBAND(ssp->SSP_REGS->SR, SSP_TNF) &&
|
||||
!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
|
||||
while (txlen > 0 && !BITBAND(SSP_REGS->SR, SSP_TNF) &&
|
||||
!BITBAND(SSP_REGS->SR, SSP_RNE)) ;
|
||||
|
||||
/* Try to receive data */
|
||||
while (length > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) {
|
||||
*data++ = ssp->SSP_REGS->DR;
|
||||
while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) {
|
||||
*data++ = SSP_REGS->DR;
|
||||
length--;
|
||||
}
|
||||
|
||||
/* Send dummy data until TX full or RX ready */
|
||||
while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF) && !BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) {
|
||||
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) {
|
||||
txlen--;
|
||||
ssp->SSP_REGS->DR = 0xff;
|
||||
SSP_REGS->DR = 0xff;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Clear interrupt flags of DMA channels 0 */
|
||||
LPC_GPDMA->DMACIntTCClear = BV(device);
|
||||
LPC_GPDMA->DMACIntErrClr = BV(device);
|
||||
LPC_GPDMA->DMACIntTCClear = BV(0);
|
||||
LPC_GPDMA->DMACIntErrClr = BV(0);
|
||||
|
||||
/* Set up RX DMA channel */
|
||||
ssp->SSP_DMACH->DMACCSrcAddr = (uint32_t)&ssp->SSP_REGS->DR;
|
||||
ssp->SSP_DMACH->DMACCDestAddr = (uint32_t)ptr;
|
||||
ssp->SSP_DMACH->DMACCLLI = 0; // no linked list
|
||||
ssp->SSP_DMACH->DMACCControl = length
|
||||
SSP_DMACH->DMACCSrcAddr = (uint32_t)&SSP_REGS->DR;
|
||||
SSP_DMACH->DMACCDestAddr = (uint32_t)ptr;
|
||||
SSP_DMACH->DMACCLLI = 0; // no linked list
|
||||
SSP_DMACH->DMACCControl = length
|
||||
| (0 << 12) // source burst size 1 (FIXME: Check if larger possible/useful)
|
||||
| (0 << 15) // destination burst size 1
|
||||
| (0 << 18) // source transfer width 1 byte
|
||||
@@ -211,52 +171,49 @@ void spi_rx_block(void *ptr, unsigned int length, int device) {
|
||||
| (0 << 26) // source address not incremented
|
||||
| (1 << 27) // destination address incremented
|
||||
;
|
||||
ssp->SSP_DMACH->DMACCConfig = 1 // enable channel
|
||||
| (ssp->SSP_DMAID_RX << 1) // data source SSP RX
|
||||
SSP_DMACH->DMACCConfig = 1 // enable channel
|
||||
| (SSP_DMAID_RX << 1) // data source SSP RX
|
||||
| (2 << 11) // transfer from peripheral to memory
|
||||
;
|
||||
|
||||
/* Enable RX FIFO DMA */
|
||||
ssp->SSP_REGS->DMACR = 1;
|
||||
SSP_REGS->DMACR = 1;
|
||||
|
||||
/* Write <length> bytes into TX FIFO */
|
||||
// FIXME: Any value in doing this using DMA too?
|
||||
while (txlen > 0) {
|
||||
while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) {
|
||||
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) {
|
||||
txlen--;
|
||||
ssp->SSP_REGS->DR = 0xff;
|
||||
SSP_REGS->DR = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until DMA channel disables itself */
|
||||
while (ssp->SSP_DMACH->DMACCConfig & 1) ;
|
||||
while (SSP_DMACH->DMACCConfig & 1) ;
|
||||
|
||||
/* Disable RX FIFO DMA */
|
||||
ssp->SSP_REGS->DMACR = 0;
|
||||
SSP_REGS->DMACR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void spi_set_speed(spi_speed_t speed, int device) {
|
||||
/* select interface */
|
||||
ssp_props *ssp = &(SSP_SEL[device]);
|
||||
|
||||
void spi_set_speed(spi_speed_t speed) {
|
||||
/* Wait until TX fifo is empty */
|
||||
while (!BITBAND(ssp->SSP_REGS->SR, 0)) ;
|
||||
while (!BITBAND(SSP_REGS->SR, 0)) ;
|
||||
|
||||
/* Disable SSP (FIXME: Is this required?) */
|
||||
ssp->SSP_REGS->CR1 = 0;
|
||||
SSP_REGS->CR1 = 0;
|
||||
|
||||
/* Change clock divisor */
|
||||
if (speed == SPI_SPEED_FAST) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
|
||||
} else if (speed == SPI_SPEED_SLOW) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
|
||||
} else if (speed == SPI_SPEED_FPGA_FAST) {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
|
||||
} else {
|
||||
ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
|
||||
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
|
||||
}
|
||||
|
||||
/* Enable SSP */
|
||||
ssp->SSP_REGS->CR1 = BV(1);
|
||||
SSP_REGS->CR1 = BV(1);
|
||||
}
|
||||
|
||||
18
src/spi.h
18
src/spi.h
@@ -33,30 +33,30 @@
|
||||
typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FPGA_SLOW } spi_speed_t;
|
||||
|
||||
/* Pre-Initialize SPI interface (PCLK divider before PLL setup) */
|
||||
void spi_preinit(int device);
|
||||
void spi_preinit(void);
|
||||
|
||||
/* Initialize SPI interface */
|
||||
void spi_init(spi_speed_t speed, int device);
|
||||
void spi_init(spi_speed_t speed);
|
||||
|
||||
/* Transmit a single byte */
|
||||
void spi_tx_byte(uint8_t data, int device);
|
||||
void spi_tx_byte(uint8_t data);
|
||||
|
||||
/* Transmit a single byte and return received data */
|
||||
uint8_t spi_txrx_byte(uint8_t data, int device);
|
||||
uint8_t spi_txrx_byte(uint8_t data);
|
||||
|
||||
/* Transmit a data block */
|
||||
void spi_tx_block(const void *data, unsigned int length, int device);
|
||||
void spi_tx_block(const void *data, unsigned int length);
|
||||
|
||||
/* Receive a single byte */
|
||||
uint8_t spi_rx_byte(int device);
|
||||
uint8_t spi_rx_byte(void);
|
||||
|
||||
/* Receive a data block */
|
||||
void spi_rx_block(void *data, unsigned int length, int device);
|
||||
void spi_rx_block(void *data, unsigned int length);
|
||||
|
||||
/* Switch speed of SPI interface */
|
||||
void spi_set_speed(spi_speed_t speed, int device);
|
||||
void spi_set_speed(spi_speed_t speed);
|
||||
|
||||
/* wait for SPI TX FIFO to become empty */
|
||||
void spi_tx_sync(int device);
|
||||
void spi_tx_sync(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//#ifdef CONFIG_UART_DEBUG
|
||||
@@ -28,6 +29,7 @@ void uart_puthex(uint8_t num);
|
||||
void uart_trace(void *ptr, uint16_t start, uint16_t len);
|
||||
void uart_flush(void);
|
||||
int printf(const char *fmt, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
#define uart_putcrlf() uart_putc('\n')
|
||||
|
||||
#else
|
||||
|
||||
@@ -20,7 +20,7 @@ void xmodem_rxfile(FIL* fil) {
|
||||
FRESULT res;
|
||||
uart_flush();
|
||||
do {
|
||||
sleep_ms(10000);
|
||||
delay_ms(10000);
|
||||
uart_putc(ASC_NAK);
|
||||
} while (uart_getc() != ASC_SOH);
|
||||
do {
|
||||
|
||||
Reference in New Issue
Block a user