firmware: adjustments for Mk.II Rev.C; enable timesetting from SNES menu
This commit is contained in:
@@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes_bootldr
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c crc.c
|
||||
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc16.c crc32.c sdnative.c fileops.c iap.c printf.c
|
||||
|
||||
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
|
||||
|
||||
@@ -67,7 +67,7 @@ SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sd
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC = startup.S
|
||||
ASRC = startup.S crc.S
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
// #define DEBUG_IRQ
|
||||
// #define DEBUG_MSU1
|
||||
|
||||
//#define DEBUG_BL
|
||||
#ifdef DEBUG_BL
|
||||
#define DBG_BL
|
||||
#ifdef DEBUG_UART
|
||||
#define DBG_UART
|
||||
#else
|
||||
#define DBG_BL while(0)
|
||||
#define DBG_UART while(0)
|
||||
#endif
|
||||
|
||||
#define DBG_BL while(0)
|
||||
|
||||
#define FW_START (0x00002000L)
|
||||
#define FLASH_SECTORS (17)
|
||||
|
||||
|
||||
#define VER "0.0.1(NSFW)"
|
||||
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
|
||||
|
||||
@@ -29,10 +30,10 @@
|
||||
|
||||
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
|
||||
|
||||
#define SD_DT_REG LPC_GPIO2
|
||||
#define SD_DT_BIT 3
|
||||
#define SD_WP_REG LPC_GPIO2
|
||||
#define SD_WP_BIT 4
|
||||
#define SD_DT_REG LPC_GPIO0
|
||||
#define SD_DT_BIT 8
|
||||
#define SD_WP_REG LPC_GPIO0
|
||||
#define SD_WP_BIT 6
|
||||
|
||||
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
|
||||
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
|
||||
@@ -40,16 +41,16 @@
|
||||
#define CONFIG_SD_BLOCKTRANSFER 1
|
||||
#define CONFIG_SD_AUTO_RETRIES 10
|
||||
// #define SD_CHANGE_VECT
|
||||
// #define CONFIG_SD_DATACRC 1
|
||||
#define CONFIG_SD_DATACRC 1
|
||||
|
||||
#define CONFIG_UART_NUM 3
|
||||
// #define CONFIG_CPU_FREQUENCY 90315789
|
||||
#define CONFIG_CPU_FREQUENCY (92000000L)
|
||||
//#define CONFIG_CPU_FREQUENCY 46000000
|
||||
#define CONFIG_UART_PCLKDIV 1
|
||||
#define CONFIG_UART_TX_BUF_SHIFT 1
|
||||
#define CONFIG_UART_TX_BUF_SHIFT 8
|
||||
#define CONFIG_UART_BAUDRATE 921600
|
||||
#define CONFIG_UART_DEADLOCKABLE
|
||||
//#define CONFIG_UART_DEADLOCKABLE
|
||||
|
||||
#define SSP_CLK_DIVISOR_FAST 2
|
||||
#define SSP_CLK_DIVISOR_SLOW 250
|
||||
@@ -58,20 +59,19 @@
|
||||
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
|
||||
|
||||
#define SNES_RESET_REG LPC_GPIO1
|
||||
#define SNES_RESET_BIT 29
|
||||
/* XXX Rev.B: 1.26 */
|
||||
#define SNES_CIC_D0_REG LPC_GPIO1
|
||||
#define SNES_CIC_D0_BIT 26
|
||||
/* XXX Rev.B: 0.1 */
|
||||
#define SNES_CIC_D1_REG LPC_GPIO1
|
||||
#define SNES_CIC_D1_BIT 25
|
||||
/* XXX Rev.B: 0.0 */
|
||||
#define SNES_CIC_STATUS_REG LPC_GPIO0
|
||||
#define SNES_CIC_STATUS_BIT 1
|
||||
/* XXX Rev.B: 1.29 */
|
||||
#define SNES_CIC_PAIR_REG LPC_GPIO0
|
||||
#define SNES_CIC_PAIR_BIT 0
|
||||
/* XXX Rev.B: 1.25 */
|
||||
#define SNES_RESET_BIT 26
|
||||
|
||||
#define SNES_CIC_D0_REG LPC_GPIO0
|
||||
#define SNES_CIC_D0_BIT 1
|
||||
|
||||
#define SNES_CIC_D1_REG LPC_GPIO0
|
||||
#define SNES_CIC_D1_BIT 0
|
||||
|
||||
#define SNES_CIC_STATUS_REG LPC_GPIO1
|
||||
#define SNES_CIC_STATUS_BIT 29
|
||||
|
||||
#define SNES_CIC_PAIR_REG LPC_GPIO1
|
||||
#define SNES_CIC_PAIR_BIT 25
|
||||
|
||||
#define QSORT_MAXELEM 1024
|
||||
|
||||
@@ -88,20 +88,18 @@
|
||||
|
||||
#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_DAT0REG LPC_GPIO2
|
||||
#define SD_DAT1REG LPC_GPIO2
|
||||
#define SD_DAT2REG LPC_GPIO2
|
||||
#define SD_DAT3REG LPC_GPIO2
|
||||
|
||||
#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_DAT0PIN (0)
|
||||
#define SD_DAT1PIN (1)
|
||||
#define SD_DAT2PIN (2)
|
||||
#define SD_DAT3PIN (3)
|
||||
|
||||
#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
|
||||
|((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
|
||||
#define SD_DAT (LPC_GPIO2->FIOPIN & 0xf)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,22 +26,6 @@ loop:
|
||||
uxtb r0, r0 // clear top bits of result
|
||||
bx lr // return
|
||||
|
||||
|
||||
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
|
||||
.global crc_xmodem_block
|
||||
.thumb_func
|
||||
crc_xmodem_block:
|
||||
adr r12, crc_table // load address of crc table
|
||||
blockloop:
|
||||
ldrb.w r3, [r1], #1 // read data byte
|
||||
eor r3, r3, r0, lsr #8 // EOR data byte
|
||||
ldrh r3, [r12, r3, lsl #1] // load value from CRC table
|
||||
eor r0, r3, r0, lsl #8 // update CRC
|
||||
uxth r0, r0 // clear top bits of result
|
||||
subs r2, r2, #1 // decrement length
|
||||
bne blockloop // loop while length > 0
|
||||
bx lr // return
|
||||
|
||||
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
|
||||
.global crc_xmodem_update
|
||||
.thumb_func
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
DBG_BL printf("HFSR: %lx\n", SCB->HFSR);
|
||||
uart_putc('H');
|
||||
DBG_UART uart_putc('H');
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -2183,7 +2183,7 @@ FRESULT f_read (
|
||||
mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
|
||||
#else
|
||||
if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){
|
||||
mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); uart_putc('Y');}
|
||||
mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); }
|
||||
#endif
|
||||
#endif
|
||||
rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
|
||||
|
||||
@@ -127,9 +127,9 @@ FLASH_RES flash_file(uint8_t *filename) {
|
||||
DBG_BL printf("firmware image found. file size: %ld\n", file_handle.fsize);
|
||||
DBG_BL printf("reading header...\n");
|
||||
f_read(&file_handle, &file_header, 32, &bytes_read);
|
||||
print_header(&file_header);
|
||||
DBG_BL print_header(&file_header);
|
||||
if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
|
||||
uart_putc('F');
|
||||
DBG_UART uart_putc('F');
|
||||
f_read(&file_handle, file_buf, 0xe0, &bytes_read);
|
||||
for(;;) {
|
||||
bytes_read = file_read();
|
||||
@@ -171,7 +171,7 @@ FLASH_RES flash_file(uint8_t *filename) {
|
||||
current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1))
|
||||
: (flash_addr >> 12);
|
||||
DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
|
||||
uart_putc('.');
|
||||
DBG_UART uart_putc('.');
|
||||
toggle_rdy_led();
|
||||
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
|
||||
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
|
||||
@@ -185,11 +185,11 @@ FLASH_RES flash_file(uint8_t *filename) {
|
||||
}
|
||||
if(total_read != file_header.size) {
|
||||
DBG_BL printf("wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size);
|
||||
uart_putc('X');
|
||||
DBG_UART uart_putc('X');
|
||||
return ERR_FILECHK;
|
||||
}
|
||||
} else {
|
||||
uart_putc('n');
|
||||
DBG_UART uart_putc('n');
|
||||
DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
|
||||
}
|
||||
return ERR_OK;
|
||||
|
||||
@@ -9,18 +9,27 @@ int led_rdyledstate = 0;
|
||||
int led_readledstate = 0;
|
||||
int led_writeledstate = 0;
|
||||
|
||||
/* LED connections (Rev.C)
|
||||
|
||||
LED color IO PWM
|
||||
---------------------------
|
||||
ready green P2.4 PWM1[5]
|
||||
read yellow P2.5 PWM1[6]
|
||||
write red P1.23 PWM1[4]
|
||||
*/
|
||||
|
||||
void rdyled(unsigned int state) {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
|
||||
BITBAND(LPC_GPIO2->FIODIR, 4) = state;
|
||||
led_rdyledstate = state;
|
||||
}
|
||||
|
||||
void readled(unsigned int state) {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
|
||||
BITBAND(LPC_GPIO2->FIODIR, 5) = state;
|
||||
led_readledstate = state;
|
||||
}
|
||||
|
||||
void writeled(unsigned int state) {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
|
||||
BITBAND(LPC_GPIO1->FIODIR, 23) = state;
|
||||
led_writeledstate = state;
|
||||
}
|
||||
|
||||
@@ -36,7 +45,7 @@ void led_clkout32(uint32_t val) {
|
||||
}
|
||||
|
||||
void toggle_rdy_led() {
|
||||
rdyled(!led_rdyledstate);
|
||||
rdyled(~led_rdyledstate);
|
||||
}
|
||||
|
||||
void toggle_read_led() {
|
||||
@@ -49,21 +58,28 @@ void toggle_write_led() {
|
||||
|
||||
void led_panic() {
|
||||
while(1) {
|
||||
LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
|
||||
LPC_GPIO2->FIODIR |= BV(4) | BV(5);
|
||||
LPC_GPIO1->FIODIR |= BV(23);
|
||||
delay_ms(350);
|
||||
LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
|
||||
LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
|
||||
LPC_GPIO1->FIODIR &= ~BV(23);
|
||||
delay_ms(350);
|
||||
}
|
||||
}
|
||||
|
||||
void led_std() {
|
||||
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
|
||||
|
||||
BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
|
||||
|
||||
BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
|
||||
|
||||
BITBAND(LPC_PWM1->PCR, 12) = 0;
|
||||
BITBAND(LPC_PWM1->PCR, 13) = 0;
|
||||
BITBAND(LPC_PWM1->PCR, 14) = 0;
|
||||
}
|
||||
|
||||
void led_init() {
|
||||
|
||||
@@ -10,7 +10,7 @@ ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x03000
|
||||
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x02000
|
||||
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
|
||||
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ int main(void) {
|
||||
clock_disconnect();
|
||||
power_init();
|
||||
timer_init();
|
||||
uart_init();
|
||||
DBG_UART uart_init();
|
||||
led_init();
|
||||
readled(0);
|
||||
rdyled(0);
|
||||
|
||||
@@ -66,12 +66,13 @@
|
||||
#define CARD_SDHC (1<<1)
|
||||
|
||||
/*
|
||||
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
|
||||
Rev.A Rev.C
|
||||
1 DAT3/SS P0.6 P2.3
|
||||
2 CMD/DI P0.9 P0.9
|
||||
5 Clock P0.7 P0.7
|
||||
7 DAT0/DO P0.8 P2.0
|
||||
8 DAT1/IRQ P1.14 P2.1
|
||||
9 DAT2/NC P1.15 P2.2
|
||||
*/
|
||||
|
||||
/* SD init procedure
|
||||
@@ -195,6 +196,42 @@ static inline void wiggle_fast_pos1(void) {
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
|
||||
int get_and_check_datacrc(uint8_t *buf) {
|
||||
uint16_t crc0=0, crc1=0, crc2=0, crc3=0;
|
||||
uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0;
|
||||
uint8_t d0=0, d1=0, d2=0, d3=0;
|
||||
uint8_t datdata;
|
||||
uint16_t datcnt;
|
||||
/* get crcs from card */
|
||||
for (datcnt=0; datcnt < 16; datcnt++) {
|
||||
datdata = SD_DAT;
|
||||
wiggle_fast_neg1();
|
||||
sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001);
|
||||
sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001);
|
||||
sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001);
|
||||
sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001);
|
||||
}
|
||||
wiggle_fast_neg1();
|
||||
/* calc crcs from data */
|
||||
for (datcnt=0; datcnt < 512; datcnt++) {
|
||||
d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ;
|
||||
d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ;
|
||||
d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ;
|
||||
d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ;
|
||||
if((datcnt % 4) == 3) {
|
||||
crc0 = crc_xmodem_update(crc0, d0);
|
||||
crc1 = crc_xmodem_update(crc1, d1);
|
||||
crc2 = crc_xmodem_update(crc2, d2);
|
||||
crc3 = crc_xmodem_update(crc3, d3);
|
||||
}
|
||||
}
|
||||
if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) {
|
||||
DBG_SD printf("CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void wait_busy(void) {
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg1();
|
||||
@@ -446,8 +483,16 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
}
|
||||
}
|
||||
}
|
||||
/* just eat the crcs for now */
|
||||
if(dat) wiggle_fast_neg(17);
|
||||
if(dat) {
|
||||
#ifdef CONFIG_SD_DATACRC
|
||||
if(get_and_check_datacrc(buf-512)) {
|
||||
return CRC_ERROR;
|
||||
}
|
||||
#else
|
||||
/* eat the crcs */
|
||||
wiggle_fast_neg(17);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(waitbusy) {
|
||||
DBG_SD printf("waitbusy after send_cmd\n");
|
||||
@@ -515,7 +560,7 @@ int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* r
|
||||
return cmd_fast(cmd, param, crc, dat, rsp);
|
||||
}
|
||||
|
||||
void stream_datablock(uint8_t *buf) {
|
||||
int stream_datablock(uint8_t *buf) {
|
||||
// uint8_t datshift=8;
|
||||
int j=512;
|
||||
uint8_t datdata=0;
|
||||
@@ -537,8 +582,13 @@ void stream_datablock(uint8_t *buf) {
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
/* eat the crc for now */
|
||||
#ifdef CONFIG_SD_DATACRC
|
||||
return get_and_check_datacrc(buf-512);
|
||||
#else
|
||||
/* eat the crcs */
|
||||
wiggle_fast_neg(17);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void send_datablock(uint8_t *buf) {
|
||||
@@ -667,7 +717,17 @@ void send_datablock(uint8_t *buf) {
|
||||
void read_block(uint32_t address, uint8_t *buf) {
|
||||
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
|
||||
//uart_putc('r');
|
||||
#ifdef CONFIG_SD_DATACRC
|
||||
int cmd_res;
|
||||
if((cmd_res = stream_datablock(buf)) == CRC_ERROR) {
|
||||
while(cmd_res == CRC_ERROR) {
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
stream_datablock(buf);
|
||||
#endif
|
||||
last_block=address;
|
||||
} else {
|
||||
if(during_blocktrans) {
|
||||
@@ -680,7 +740,14 @@ void read_block(uint32_t address, uint8_t *buf) {
|
||||
if(!ccs) {
|
||||
address <<= 9;
|
||||
}
|
||||
#ifdef CONFIG_SD_DATACRC
|
||||
while(1) {
|
||||
if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break;
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
};
|
||||
#else
|
||||
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
|
||||
#endif
|
||||
during_blocktrans = TRANS_READ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
#define CRC_ERROR (0xf000)
|
||||
|
||||
/* These functions are weak-aliased to disk_... */
|
||||
void sdn_init(void);
|
||||
DSTATUS sdn_status(BYTE drv);
|
||||
|
||||
Reference in New Issue
Block a user