mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
Added support for multiple SD cards
The MMCFS implementation can now handle more than one MMC card. To use this feature, define these macros in platform_conf.h: PLATFORM_MMC_NUM_CARDS - the total number of cards MMCFS_CS_PORT_ARRAY - array of CS ports MMCFS_CS_PIN_ARRAY - array of CS pins MMCFS_SPI_NUM_ARRAY - array of SPI port numbers For example: defines a system with 2 MMC cards. The first one uses SPI0 and has its CS on PG0. The second one also uses SPI0 (this is perfectly possible) but has its CS on PC5. This was the configuration used to test this feature on a EK-LM3S8962 board.
This commit is contained in:
parent
d05a3ae0e9
commit
ea6e38f26e
284
src/elua_mmc.c
284
src/elua_mmc.c
@ -9,6 +9,13 @@
|
|||||||
#if defined( BUILD_MMCFS ) && !defined( ELUA_SIMULATOR )
|
#if defined( BUILD_MMCFS ) && !defined( ELUA_SIMULATOR )
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "diskio.h"
|
#include "diskio.h"
|
||||||
|
#include "mmcfs.h"
|
||||||
|
|
||||||
|
#ifndef PLATFORM_MMC_NUM_CARDS
|
||||||
|
#define NUM_CARDS 1
|
||||||
|
#else
|
||||||
|
#define NUM_CARDS PLATFORM_MMC_NUM_CARDS
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
/* Definitions for MMC/SDC command */
|
||||||
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
||||||
@ -27,22 +34,32 @@
|
|||||||
#define CMD55 (0x40+55) /* APP_CMD */
|
#define CMD55 (0x40+55) /* APP_CMD */
|
||||||
#define CMD58 (0x40+58) /* READ_OCR */
|
#define CMD58 (0x40+58) /* READ_OCR */
|
||||||
|
|
||||||
#ifndef MMCFS_SPI_NUM
|
#if !defined( MMCFS_SPI_NUM ) && !defined( MMCFS_SPI_NUM_ARRAY )
|
||||||
#error "MMC not supported on this board"
|
#error "MMC not supported on this board"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined( MMCFS_CS_PORT )
|
||||||
|
const u8 mmcfs_cs_ports[ NUM_CARDS ] = { MMCFS_CS_PORT };
|
||||||
|
static const u8 mmcfs_cs_pins[ NUM_CARDS ] = { MMCFS_CS_PIN };
|
||||||
|
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = { MMCFS_SPI_NUM };
|
||||||
|
#elif defined( MMCFS_CS_PORT_ARRAY )
|
||||||
|
const u8 mmcfs_cs_ports[ NUM_CARDS ] = MMCFS_CS_PORT_ARRAY;
|
||||||
|
static const u8 mmcfs_cs_pins[ NUM_CARDS ] = MMCFS_CS_PIN_ARRAY;
|
||||||
|
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = MMCFS_SPI_NUM_ARRAY;
|
||||||
|
#endif
|
||||||
|
|
||||||
// asserts the CS pin to the card
|
// asserts the CS pin to the card
|
||||||
static
|
static
|
||||||
void SELECT (void)
|
void SELECT (BYTE id)
|
||||||
{
|
{
|
||||||
platform_pio_op( MMCFS_CS_PORT , ( ( u32 ) 1 << MMCFS_CS_PIN ), PLATFORM_IO_PIN_CLEAR );
|
platform_pio_op( mmcfs_cs_ports[ id ] , ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_CLEAR );
|
||||||
}
|
}
|
||||||
|
|
||||||
// de-asserts the CS pin to the card
|
// de-asserts the CS pin to the card
|
||||||
static
|
static
|
||||||
void DESELECT (void)
|
void DESELECT (BYTE id)
|
||||||
{
|
{
|
||||||
platform_pio_op( MMCFS_CS_PORT, ( ( u32 ) 1 << MMCFS_CS_PIN ), PLATFORM_IO_PIN_SET );
|
platform_pio_op( mmcfs_cs_ports[ id ], ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_SET );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -52,20 +69,13 @@ void DESELECT (void)
|
|||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static volatile
|
static volatile DSTATUS Stat[ NUM_CARDS ]; /* Disk status */
|
||||||
DSTATUS Stat = STA_NOINIT; /* Disk status */
|
|
||||||
|
|
||||||
static volatile timer_data_type Timer1 = 0;
|
static BYTE TriesLeft[ NUM_CARDS ];
|
||||||
static volatile timer_data_type Timer2 = 0;
|
|
||||||
|
|
||||||
static
|
static BYTE CardType[ NUM_CARDS ]; /* b0:MMC, b1:SDC, b2:Block addressing */
|
||||||
BYTE TriesLeft = 2;
|
|
||||||
|
|
||||||
static
|
static BYTE PowerFlag[ NUM_CARDS ]; /* indicates if "power" is on */
|
||||||
BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE PowerFlag = 0; /* indicates if "power" is on */
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@ -74,9 +84,9 @@ BYTE PowerFlag = 0; /* indicates if "power" is on */
|
|||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void xmit_spi (BYTE dat)
|
void xmit_spi (BYTE id, BYTE dat)
|
||||||
{
|
{
|
||||||
platform_spi_send_recv( MMCFS_SPI_NUM, dat );
|
platform_spi_send_recv( mmcfs_spi_nums[ id ], dat );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,20 +95,20 @@ void xmit_spi (BYTE dat)
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
BYTE rcvr_spi (void)
|
BYTE rcvr_spi (BYTE id)
|
||||||
{
|
{
|
||||||
DWORD rcvdat;
|
DWORD rcvdat;
|
||||||
|
|
||||||
rcvdat = platform_spi_send_recv( MMCFS_SPI_NUM, 0xFF );
|
rcvdat = platform_spi_send_recv( mmcfs_spi_nums[ id ], 0xFF );
|
||||||
|
|
||||||
return ( BYTE )rcvdat;
|
return ( BYTE )rcvdat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void rcvr_spi_m (BYTE *dst)
|
void rcvr_spi_m (BYTE id, BYTE *dst)
|
||||||
{
|
{
|
||||||
*dst = rcvr_spi();
|
*dst = rcvr_spi( id );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@ -106,14 +116,15 @@ void rcvr_spi_m (BYTE *dst)
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
BYTE wait_ready (void)
|
BYTE wait_ready (BYTE id)
|
||||||
{
|
{
|
||||||
BYTE res;
|
BYTE res;
|
||||||
|
timer_data_type Timer2;
|
||||||
|
|
||||||
Timer2 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
Timer2 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||||
rcvr_spi();
|
rcvr_spi( id );
|
||||||
do
|
do
|
||||||
res = rcvr_spi(); /* Wait for ready in timeout of 500ms. */
|
res = rcvr_spi( id ); /* Wait for ready in timeout of 500ms. */
|
||||||
while ( ( res != 0xFF ) && ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer2 ) < 500000 ) );
|
while ( ( res != 0xFF ) && ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer2 ) < 500000 ) );
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -124,16 +135,16 @@ BYTE wait_ready (void)
|
|||||||
/* required after card power up to get it into SPI mode */
|
/* required after card power up to get it into SPI mode */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
static
|
static
|
||||||
void send_initial_clock_train(void)
|
void send_initial_clock_train(BYTE id)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
/* Ensure CS is held high. */
|
/* Ensure CS is held high. */
|
||||||
DESELECT();
|
DESELECT(id);
|
||||||
|
|
||||||
/* Send 10 bytes over the SSI. This causes the clock to wiggle the */
|
/* Send 10 bytes over the SSI. This causes the clock to wiggle the */
|
||||||
/* required number of times. */
|
/* required number of times. */
|
||||||
for(i = 0 ; i < 10 ; i++)
|
for(i = 0 ; i < 10 ; i++)
|
||||||
rcvr_spi();
|
rcvr_spi(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@ -143,7 +154,7 @@ void send_initial_clock_train(void)
|
|||||||
/* is nothing to do in these functions and chk_power always returns 1. */
|
/* is nothing to do in these functions and chk_power always returns 1. */
|
||||||
|
|
||||||
static
|
static
|
||||||
void power_on (void)
|
void power_on (BYTE id)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This doesn't really turn the power on, but initializes the
|
* This doesn't really turn the power on, but initializes the
|
||||||
@ -151,23 +162,23 @@ void power_on (void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Setup CS pin & deselect
|
// Setup CS pin & deselect
|
||||||
platform_pio_op( MMCFS_CS_PORT, ( ( u32 ) 1 << MMCFS_CS_PIN ), PLATFORM_IO_PIN_DIR_OUTPUT );
|
platform_pio_op( mmcfs_cs_ports[ id ], ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_DIR_OUTPUT );
|
||||||
//platform_pio_op( MMCFS_CS_PORT, ( ( u32 ) 1 << MMCFS_CS_PIN ), PLATFORM_IO_PIN_PULLUP );
|
//platform_pio_op( MMCFS_CS_PORT, ( ( u32 ) 1 << MMCFS_CS_PIN ), PLATFORM_IO_PIN_PULLUP );
|
||||||
DESELECT();
|
DESELECT( id );
|
||||||
|
|
||||||
// Setup SPI
|
// Setup SPI
|
||||||
platform_spi_setup( MMCFS_SPI_NUM, PLATFORM_SPI_MASTER, 400000, 0, 0, 8 );
|
platform_spi_setup( mmcfs_spi_nums[ id ], PLATFORM_SPI_MASTER, 400000, 0, 0, 8 );
|
||||||
|
|
||||||
/* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
|
/* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
|
||||||
/* to be able to accept a native command. */
|
/* to be able to accept a native command. */
|
||||||
send_initial_clock_train();
|
send_initial_clock_train(id);
|
||||||
|
|
||||||
PowerFlag = 1;
|
PowerFlag[id] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the SSI speed to the max setting
|
// set the SSI speed to the max setting
|
||||||
static
|
static
|
||||||
void set_max_speed(void)
|
void set_max_speed(BYTE id)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
@ -177,48 +188,49 @@ void set_max_speed(void)
|
|||||||
i = 12500000;
|
i = 12500000;
|
||||||
|
|
||||||
/* Configure the SPI port */
|
/* Configure the SPI port */
|
||||||
platform_spi_setup( MMCFS_SPI_NUM, PLATFORM_SPI_MASTER, i, 0, 0, 8 );
|
platform_spi_setup( mmcfs_spi_nums[ id ], PLATFORM_SPI_MASTER, i, 0, 0, 8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void power_off (void)
|
void power_off (BYTE id)
|
||||||
{
|
{
|
||||||
PowerFlag = 0;
|
PowerFlag[ id ] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int chk_power(void) /* Socket power state: 0=off, 1=on */
|
int chk_power(BYTE id) /* Socket power state: 0=off, 1=on */
|
||||||
{
|
{
|
||||||
return PowerFlag;
|
return PowerFlag[ id ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Receive a data packet from MMC */
|
/* Receive a data packet from MMC */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
BOOL rcvr_datablock (
|
BOOL rcvr_datablock (
|
||||||
|
BYTE id, /* Disk ID */
|
||||||
BYTE *buff, /* Data buffer to store received data */
|
BYTE *buff, /* Data buffer to store received data */
|
||||||
UINT btr /* Byte count (must be even number) */
|
UINT btr /* Byte count (must be even number) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BYTE token;
|
BYTE token;
|
||||||
|
timer_data_type Timer1;
|
||||||
|
|
||||||
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||||
do { /* Wait for data packet in timeout of 100ms */
|
do { /* Wait for data packet in timeout of 100ms */
|
||||||
token = rcvr_spi();
|
token = rcvr_spi(id);
|
||||||
} while ( ( token == 0xFF ) &&
|
} while ( ( token == 0xFF ) &&
|
||||||
platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 100000 );
|
platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 100000 );
|
||||||
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
|
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
|
||||||
|
|
||||||
do { /* Receive the data block into buffer */
|
do { /* Receive the data block into buffer */
|
||||||
rcvr_spi_m(buff++);
|
rcvr_spi_m(id, buff++);
|
||||||
rcvr_spi_m(buff++);
|
rcvr_spi_m(id, buff++);
|
||||||
} while (btr -= 2);
|
} while (btr -= 2);
|
||||||
rcvr_spi(); /* Discard CRC */
|
rcvr_spi(id); /* Discard CRC */
|
||||||
rcvr_spi();
|
rcvr_spi(id);
|
||||||
|
|
||||||
return TRUE; /* Return with success */
|
return TRUE; /* Return with success */
|
||||||
}
|
}
|
||||||
@ -232,6 +244,7 @@ BOOL rcvr_datablock (
|
|||||||
#if _READONLY == 0
|
#if _READONLY == 0
|
||||||
static
|
static
|
||||||
BOOL xmit_datablock (
|
BOOL xmit_datablock (
|
||||||
|
BYTE id, /* Disk ID */
|
||||||
const BYTE *buff, /* 512 byte data block to be transmitted */
|
const BYTE *buff, /* 512 byte data block to be transmitted */
|
||||||
BYTE token /* Data/Stop token */
|
BYTE token /* Data/Stop token */
|
||||||
)
|
)
|
||||||
@ -239,18 +252,18 @@ BOOL xmit_datablock (
|
|||||||
BYTE resp, wc;
|
BYTE resp, wc;
|
||||||
|
|
||||||
|
|
||||||
if (wait_ready() != 0xFF) return FALSE;
|
if (wait_ready(id) != 0xFF) return FALSE;
|
||||||
|
|
||||||
xmit_spi(token); /* Xmit data token */
|
xmit_spi(id,token); /* Xmit data token */
|
||||||
if (token != 0xFD) { /* Is data token */
|
if (token != 0xFD) { /* Is data token */
|
||||||
wc = 0;
|
wc = 0;
|
||||||
do { /* Xmit the 512 byte data block to MMC */
|
do { /* Xmit the 512 byte data block to MMC */
|
||||||
xmit_spi(*buff++);
|
xmit_spi(id,*buff++);
|
||||||
xmit_spi(*buff++);
|
xmit_spi(id,*buff++);
|
||||||
} while (--wc);
|
} while (--wc);
|
||||||
xmit_spi(0xFF); /* CRC (Dummy) */
|
xmit_spi(id,0xFF); /* CRC (Dummy) */
|
||||||
xmit_spi(0xFF);
|
xmit_spi(id,0xFF);
|
||||||
resp = rcvr_spi(); /* Reveive data response */
|
resp = rcvr_spi(id); /* Reveive data response */
|
||||||
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
|
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -267,6 +280,7 @@ BOOL xmit_datablock (
|
|||||||
|
|
||||||
static
|
static
|
||||||
BYTE send_cmd (
|
BYTE send_cmd (
|
||||||
|
BYTE id, /* Disk ID */
|
||||||
BYTE cmd, /* Command byte */
|
BYTE cmd, /* Command byte */
|
||||||
DWORD arg /* Argument */
|
DWORD arg /* Argument */
|
||||||
)
|
)
|
||||||
@ -274,24 +288,24 @@ BYTE send_cmd (
|
|||||||
BYTE n, res;
|
BYTE n, res;
|
||||||
|
|
||||||
|
|
||||||
if (wait_ready() != 0xFF) return 0xFF;
|
if (wait_ready(id) != 0xFF) return 0xFF;
|
||||||
|
|
||||||
/* Send command packet */
|
/* Send command packet */
|
||||||
xmit_spi(cmd); /* Command */
|
xmit_spi(id,cmd); /* Command */
|
||||||
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
|
xmit_spi(id,(BYTE)(arg >> 24)); /* Argument[31..24] */
|
||||||
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
|
xmit_spi(id,(BYTE)(arg >> 16)); /* Argument[23..16] */
|
||||||
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
|
xmit_spi(id,(BYTE)(arg >> 8)); /* Argument[15..8] */
|
||||||
xmit_spi((BYTE)arg); /* Argument[7..0] */
|
xmit_spi(id,(BYTE)arg); /* Argument[7..0] */
|
||||||
n = 0;
|
n = 0;
|
||||||
if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
|
if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
|
||||||
if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
|
if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
|
||||||
xmit_spi(n);
|
xmit_spi(id,n);
|
||||||
|
|
||||||
/* Receive command response */
|
/* Receive command response */
|
||||||
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
|
if (cmd == CMD12) rcvr_spi(id); /* Skip a stuff byte when stop reading */
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
||||||
do
|
do
|
||||||
res = rcvr_spi();
|
res = rcvr_spi(id);
|
||||||
while ((res & 0x80) && --n);
|
while ((res & 0x80) && --n);
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
return res; /* Return with the response value */
|
||||||
@ -305,6 +319,16 @@ BYTE send_cmd (
|
|||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void elua_mmc_init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < NUM_CARDS; i ++ )
|
||||||
|
{
|
||||||
|
Stat[ i ] = STA_NOINIT;
|
||||||
|
TriesLeft[ i ] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Initialize Disk Drive */
|
/* Initialize Disk Drive */
|
||||||
@ -315,62 +339,61 @@ DSTATUS disk_initialize (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
BYTE n, ty, ocr[4];
|
BYTE n, ty, ocr[4];
|
||||||
|
timer_data_type Timer1;
|
||||||
|
|
||||||
|
if (Stat[drv] & STA_NODISK) return Stat[drv]; /* No card in the socket */
|
||||||
if (drv) return STA_NOINIT; /* Supports only single drive */
|
|
||||||
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
power_on(); /* Force socket power on */
|
power_on(drv); /* Force socket power on */
|
||||||
|
|
||||||
SELECT(); /* CS = L */
|
SELECT(drv); /* CS = L */
|
||||||
ty = 0;
|
ty = 0;
|
||||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
if (send_cmd(drv,CMD0, 0) == 1) { /* Enter Idle state */
|
||||||
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
|
if (send_cmd(drv,CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
|
||||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(drv);
|
||||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
||||||
do {
|
do {
|
||||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
|
if (send_cmd(drv,CMD55, 0) <= 1 && send_cmd(drv,CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
|
||||||
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
||||||
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 )
|
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 )
|
||||||
&& send_cmd(CMD58, 0) == 0) { /* Check CCS bit (it seems pointless to check the timer here*/
|
&& send_cmd(drv,CMD58, 0) == 0) { /* Check CCS bit (it seems pointless to check the timer here*/
|
||||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(drv);
|
||||||
ty = (ocr[0] & 0x40) ? 6 : 2;
|
ty = (ocr[0] & 0x40) ? 6 : 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { /* SDC Ver1 or MMC */
|
} else { /* SDC Ver1 or MMC */
|
||||||
ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
|
ty = (send_cmd(drv,CMD55, 0) <= 1 && send_cmd(drv,CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
|
||||||
do {
|
do {
|
||||||
if (ty == 2) {
|
if (ty == 2) {
|
||||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
|
if (send_cmd(drv,CMD55, 0) <= 1 && send_cmd(drv,CMD41, 0) == 0) break; /* ACMD41 */
|
||||||
} else {
|
} else {
|
||||||
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
|
if (send_cmd(drv,CMD1, 0) == 0) break; /* CMD1 */
|
||||||
}
|
}
|
||||||
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
||||||
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) >= 1000000 )
|
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) >= 1000000 )
|
||||||
|| send_cmd(CMD16, 512) != 0 ) /* Select R/W block length */
|
|| send_cmd(drv,CMD16, 512) != 0 ) /* Select R/W block length */
|
||||||
ty = 0;
|
ty = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CardType = ty;
|
CardType[drv] = ty;
|
||||||
DESELECT(); /* CS = H */
|
DESELECT(drv); /* CS = H */
|
||||||
rcvr_spi(); /* Idle (Release DO) */
|
rcvr_spi(drv); /* Idle (Release DO) */
|
||||||
|
|
||||||
if (TriesLeft)
|
if (TriesLeft[drv])
|
||||||
TriesLeft--;
|
TriesLeft[drv]--;
|
||||||
|
|
||||||
if (ty) { /* Initialization succeded */
|
if (ty) { /* Initialization succeded */
|
||||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
Stat[drv] &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
||||||
set_max_speed();
|
set_max_speed(drv);
|
||||||
} else { /* Initialization failed */
|
} else { /* Initialization failed */
|
||||||
power_off();
|
power_off(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
} while( TriesLeft > 0 && ty == 0 );
|
} while( TriesLeft[drv] > 0 && ty == 0 );
|
||||||
|
|
||||||
return Stat;
|
return Stat[drv];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -383,8 +406,7 @@ DSTATUS disk_status (
|
|||||||
BYTE drv /* Physical drive nmuber (0) */
|
BYTE drv /* Physical drive nmuber (0) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (drv) return STA_NOINIT; /* Supports only single drive */
|
return Stat[drv];
|
||||||
return Stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -400,30 +422,30 @@ DRESULT disk_read (
|
|||||||
BYTE count /* Sector count (1..255) */
|
BYTE count /* Sector count (1..255) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (drv || !count) return RES_PARERR;
|
if (!count) return RES_PARERR;
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
if (Stat[drv] & STA_NOINIT) return RES_NOTRDY;
|
||||||
|
|
||||||
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
|
if (!(CardType[drv] & 4)) sector *= 512; /* Convert to byte address if needed */
|
||||||
|
|
||||||
SELECT(); /* CS = L */
|
SELECT(drv); /* CS = L */
|
||||||
|
|
||||||
if (count == 1) { /* Single block read */
|
if (count == 1) { /* Single block read */
|
||||||
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
|
if ((send_cmd(drv,CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
|
||||||
&& rcvr_datablock(buff, 512))
|
&& rcvr_datablock(drv,buff, 512))
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
else { /* Multiple block read */
|
else { /* Multiple block read */
|
||||||
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
|
if (send_cmd(drv,CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
|
||||||
do {
|
do {
|
||||||
if (!rcvr_datablock(buff, 512)) break;
|
if (!rcvr_datablock(drv,buff, 512)) break;
|
||||||
buff += 512;
|
buff += 512;
|
||||||
} while (--count);
|
} while (--count);
|
||||||
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
|
send_cmd(drv,CMD12, 0); /* STOP_TRANSMISSION */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DESELECT(); /* CS = H */
|
DESELECT(drv); /* CS = H */
|
||||||
rcvr_spi(); /* Idle (Release DO) */
|
rcvr_spi(drv); /* Idle (Release DO) */
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
return count ? RES_ERROR : RES_OK;
|
||||||
}
|
}
|
||||||
@ -442,35 +464,35 @@ DRESULT disk_write (
|
|||||||
BYTE count /* Sector count (1..255) */
|
BYTE count /* Sector count (1..255) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (drv || !count) return RES_PARERR;
|
if (!count) return RES_PARERR;
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
if (Stat[drv] & STA_NOINIT) return RES_NOTRDY;
|
||||||
if (Stat & STA_PROTECT) return RES_WRPRT;
|
if (Stat[drv] & STA_PROTECT) return RES_WRPRT;
|
||||||
|
|
||||||
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
|
if (!(CardType[drv] & 4)) sector *= 512; /* Convert to byte address if needed */
|
||||||
|
|
||||||
SELECT(); /* CS = L */
|
SELECT(drv); /* CS = L */
|
||||||
|
|
||||||
if (count == 1) { /* Single block write */
|
if (count == 1) { /* Single block write */
|
||||||
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
|
if ((send_cmd(drv, CMD24, sector) == 0) /* WRITE_BLOCK */
|
||||||
&& xmit_datablock(buff, 0xFE))
|
&& xmit_datablock(drv, buff, 0xFE))
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
else { /* Multiple block write */
|
else { /* Multiple block write */
|
||||||
if (CardType & 2) {
|
if (CardType[drv] & 2) {
|
||||||
send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
|
send_cmd(drv, CMD55, 0); send_cmd(drv, CMD23, count); /* ACMD23 */
|
||||||
}
|
}
|
||||||
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
|
if (send_cmd(drv, CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
|
||||||
do {
|
do {
|
||||||
if (!xmit_datablock(buff, 0xFC)) break;
|
if (!xmit_datablock(drv, buff, 0xFC)) break;
|
||||||
buff += 512;
|
buff += 512;
|
||||||
} while (--count);
|
} while (--count);
|
||||||
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
|
if (!xmit_datablock(drv, 0, 0xFD)) /* STOP_TRAN token */
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DESELECT(); /* CS = H */
|
DESELECT(drv); /* CS = H */
|
||||||
rcvr_spi(); /* Idle (Release DO) */
|
rcvr_spi(drv); /* Idle (Release DO) */
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
return count ? RES_ERROR : RES_OK;
|
||||||
}
|
}
|
||||||
@ -493,23 +515,21 @@ DRESULT disk_ioctl (
|
|||||||
WORD csize;
|
WORD csize;
|
||||||
|
|
||||||
|
|
||||||
if (drv) return RES_PARERR;
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
res = RES_ERROR;
|
||||||
|
|
||||||
if (ctrl == CTRL_POWER) {
|
if (ctrl == CTRL_POWER) {
|
||||||
switch (*ptr) {
|
switch (*ptr) {
|
||||||
case 0: /* Sub control code == 0 (POWER_OFF) */
|
case 0: /* Sub control code == 0 (POWER_OFF) */
|
||||||
if (chk_power())
|
if (chk_power(drv))
|
||||||
power_off(); /* Power off */
|
power_off(drv); /* Power off */
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
case 1: /* Sub control code == 1 (POWER_ON) */
|
case 1: /* Sub control code == 1 (POWER_ON) */
|
||||||
power_on(); /* Power on */
|
power_on(drv); /* Power on */
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
case 2: /* Sub control code == 2 (POWER_GET) */
|
case 2: /* Sub control code == 2 (POWER_GET) */
|
||||||
*(ptr+1) = (BYTE)chk_power();
|
*(ptr+1) = (BYTE)chk_power(drv);
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
@ -517,13 +537,13 @@ DRESULT disk_ioctl (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
if (Stat[drv] & STA_NOINIT) return RES_NOTRDY;
|
||||||
|
|
||||||
SELECT(); /* CS = L */
|
SELECT(drv); /* CS = L */
|
||||||
|
|
||||||
switch (ctrl) {
|
switch (ctrl) {
|
||||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
||||||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
|
if ((send_cmd(drv,CMD9, 0) == 0) && rcvr_datablock(drv,csd, 16)) {
|
||||||
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
|
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
|
||||||
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
|
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
|
||||||
*(DWORD*)buff = (DWORD)csize << 10;
|
*(DWORD*)buff = (DWORD)csize << 10;
|
||||||
@ -542,26 +562,26 @@ DRESULT disk_ioctl (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_SYNC : /* Make sure that data has been written */
|
case CTRL_SYNC : /* Make sure that data has been written */
|
||||||
if (wait_ready() == 0xFF)
|
if (wait_ready(drv) == 0xFF)
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
|
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
|
||||||
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
|
if (send_cmd(drv,CMD9, 0) == 0 /* READ_CSD */
|
||||||
&& rcvr_datablock(ptr, 16))
|
&& rcvr_datablock(drv, ptr, 16))
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
|
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
|
||||||
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
|
if (send_cmd(drv, CMD10, 0) == 0 /* READ_CID */
|
||||||
&& rcvr_datablock(ptr, 16))
|
&& rcvr_datablock(drv, ptr, 16))
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
|
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
|
||||||
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
|
if (send_cmd(drv, CMD58, 0) == 0) { /* READ_OCR */
|
||||||
for (n = 0; n < 4; n++)
|
for (n = 0; n < 4; n++)
|
||||||
*ptr++ = rcvr_spi();
|
*ptr++ = rcvr_spi(drv);
|
||||||
res = RES_OK;
|
res = RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,8 +594,8 @@ DRESULT disk_ioctl (
|
|||||||
res = RES_PARERR;
|
res = RES_PARERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
DESELECT(); /* CS = H */
|
DESELECT(drv); /* CS = H */
|
||||||
rcvr_spi(); /* Idle (Release DO) */
|
rcvr_spi(drv); /* Idle (Release DO) */
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -120,7 +120,11 @@
|
|||||||
/ Physical Drive Configurations
|
/ Physical Drive Configurations
|
||||||
/----------------------------------------------------------------------------*/
|
/----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef PLATFORM_MMC_NUM_CARDS
|
||||||
#define _DRIVES 1
|
#define _DRIVES 1
|
||||||
|
#else
|
||||||
|
#define _DRIVES PLATFORM_MMC_NUM_CARDS
|
||||||
|
#endif
|
||||||
/* Number of volumes (logical drives) to be used. */
|
/* Number of volumes (logical drives) to be used. */
|
||||||
|
|
||||||
|
|
||||||
|
65
src/mmcfs.c
65
src/mmcfs.c
@ -20,8 +20,16 @@
|
|||||||
static FIL mmcfs_fd_table[ MMCFS_MAX_FDS ];
|
static FIL mmcfs_fd_table[ MMCFS_MAX_FDS ];
|
||||||
static int mmcfs_num_fd;
|
static int mmcfs_num_fd;
|
||||||
|
|
||||||
|
extern void elua_mmc_init();
|
||||||
|
|
||||||
|
#ifndef PLATFORM_MMC_NUM_CARDS
|
||||||
|
#define NUM_CARDS 1
|
||||||
|
#else
|
||||||
|
#define NUM_CARDS PLATFORM_MMC_NUM_CARDS
|
||||||
|
#endif
|
||||||
|
|
||||||
// Data structures used by FatFs
|
// Data structures used by FatFs
|
||||||
static FATFS mmc_fs;
|
static FATFS mmc_fs[ NUM_CARDS ];
|
||||||
static FIL mmc_fileObject;
|
static FIL mmc_fileObject;
|
||||||
//static DIR mmc_dir;
|
//static DIR mmc_dir;
|
||||||
//static FILINFO mmc_fileInfo;
|
//static FILINFO mmc_fileInfo;
|
||||||
@ -31,9 +39,6 @@ typedef struct
|
|||||||
struct dm_dirent *pdm;
|
struct dm_dirent *pdm;
|
||||||
} MMCFS_DIRENT_DATA;
|
} MMCFS_DIRENT_DATA;
|
||||||
|
|
||||||
#define PATH_BUF_SIZE 40
|
|
||||||
static char mmc_pathBuf[PATH_BUF_SIZE];
|
|
||||||
|
|
||||||
static int mmcfs_find_empty_fd( void )
|
static int mmcfs_find_empty_fd( void )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -48,6 +53,8 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int mmc_mode;
|
int mmc_mode;
|
||||||
|
char *mmc_pathBuf;
|
||||||
|
int drv_num = *( int* )pdata;
|
||||||
|
|
||||||
if (mmcfs_num_fd == MMCFS_MAX_FDS)
|
if (mmcfs_num_fd == MMCFS_MAX_FDS)
|
||||||
{
|
{
|
||||||
@ -56,10 +63,15 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default to top directory if none given
|
// Default to top directory if none given
|
||||||
mmc_pathBuf[0] = 0;
|
|
||||||
if (strchr(path, '/') == NULL)
|
if (strchr(path, '/') == NULL)
|
||||||
strcat(mmc_pathBuf, "/");
|
asprintf( &mmc_pathBuf, "%d:/%s", drv_num, path );
|
||||||
strcat(mmc_pathBuf, path);
|
else
|
||||||
|
asprintf( &mmc_pathBuf, "%d:%s", drv_num, path );
|
||||||
|
if( mmc_pathBuf == NULL )
|
||||||
|
{
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Scrub binary flag, if defined
|
// Scrub binary flag, if defined
|
||||||
#ifdef O_BINARY
|
#ifdef O_BINARY
|
||||||
@ -70,6 +82,7 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
if ((flags & O_ACCMODE) != O_RDONLY)
|
if ((flags & O_ACCMODE) != O_RDONLY)
|
||||||
{
|
{
|
||||||
r->_errno = EROFS;
|
r->_errno = EROFS;
|
||||||
|
free( mmc_pathBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mmc_mode = FA_OPEN_EXISTING & FA_READ;
|
mmc_mode = FA_OPEN_EXISTING & FA_READ;
|
||||||
@ -86,6 +99,7 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
|
free( mmc_pathBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +112,7 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
|
free( mmc_pathBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif // _FS_READONLY
|
#endif // _FS_READONLY
|
||||||
@ -106,6 +121,7 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
if (f_open(&mmc_fileObject, mmc_pathBuf, mmc_mode) != FR_OK)
|
if (f_open(&mmc_fileObject, mmc_pathBuf, mmc_mode) != FR_OK)
|
||||||
{
|
{
|
||||||
r->_errno = ENOENT;
|
r->_errno = ENOENT;
|
||||||
|
free( mmc_pathBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +130,7 @@ static int mmcfs_open_r( struct _reent *r, const char *path, int flags, int mode
|
|||||||
fd = mmcfs_find_empty_fd();
|
fd = mmcfs_find_empty_fd();
|
||||||
memcpy(mmcfs_fd_table + fd, &mmc_fileObject, sizeof(FIL));
|
memcpy(mmcfs_fd_table + fd, &mmc_fileObject, sizeof(FIL));
|
||||||
mmcfs_num_fd ++;
|
mmcfs_num_fd ++;
|
||||||
|
free( mmc_pathBuf );
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +213,8 @@ static void* mmcfs_opendir_r( struct _reent *r, const char* dname, void *pdata )
|
|||||||
{
|
{
|
||||||
void* res = NULL;
|
void* res = NULL;
|
||||||
MMCFS_DIRENT_DATA *pd = ( MMCFS_DIRENT_DATA* )malloc( sizeof( MMCFS_DIRENT_DATA ) );
|
MMCFS_DIRENT_DATA *pd = ( MMCFS_DIRENT_DATA* )malloc( sizeof( MMCFS_DIRENT_DATA ) );
|
||||||
|
int drv_num = *( int* )pdata;
|
||||||
|
char *pname = NULL;
|
||||||
|
|
||||||
if( !pd )
|
if( !pd )
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -205,9 +224,10 @@ static void* mmcfs_opendir_r( struct _reent *r, const char* dname, void *pdata )
|
|||||||
if( ( pd->pdm = ( struct dm_dirent* )malloc( sizeof( struct dm_dirent ) ) ) == NULL )
|
if( ( pd->pdm = ( struct dm_dirent* )malloc( sizeof( struct dm_dirent ) ) ) == NULL )
|
||||||
goto out;
|
goto out;
|
||||||
if( !dname || strlen( dname ) == 0 )
|
if( !dname || strlen( dname ) == 0 )
|
||||||
res = f_opendir( pd->dir, "/" ) != FR_OK ? NULL : pd;
|
asprintf( &pname, "%d:/", drv_num );
|
||||||
else
|
else
|
||||||
res = f_opendir( pd->dir, dname ) != FR_OK ? NULL : pd;
|
asprintf( &pname, "%d:%s", drv_num, dname );
|
||||||
|
res = f_opendir( pd->dir, pname ) != FR_OK ? NULL : pd;
|
||||||
out:
|
out:
|
||||||
if( res == NULL )
|
if( res == NULL )
|
||||||
{
|
{
|
||||||
@ -217,6 +237,8 @@ out:
|
|||||||
free( pd->pdm );
|
free( pd->pdm );
|
||||||
free( pd );
|
free( pd );
|
||||||
}
|
}
|
||||||
|
if( pname )
|
||||||
|
free( pname );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,10 +314,29 @@ static const DM_DEVICE mmcfs_device =
|
|||||||
|
|
||||||
int mmcfs_init()
|
int mmcfs_init()
|
||||||
{
|
{
|
||||||
// Mount the MMC file system using logical disk 0
|
elua_mmc_init();
|
||||||
if ( f_mount( 0, &mmc_fs ) != FR_OK )
|
#if NUM_CARDS == 1
|
||||||
|
static int cid = 0;
|
||||||
|
// A single MMCFS
|
||||||
|
if ( f_mount( 0, mmc_fs ) != FR_OK )
|
||||||
return DM_ERR_INIT;
|
return DM_ERR_INIT;
|
||||||
return dm_register( "/mmc", NULL, &mmcfs_device );
|
return dm_register( "/mmc", &cid, &mmcfs_device );
|
||||||
|
#else // #if NUM_CARDS == 1
|
||||||
|
int i;
|
||||||
|
static char names[ NUM_CARDS ][ 6 ];
|
||||||
|
static int ids[ NUM_CARDS ];
|
||||||
|
|
||||||
|
// [TODO] add more error checking!
|
||||||
|
for( i = 0; i < NUM_CARDS; i ++ )
|
||||||
|
if( f_mount( i, mmc_fs + i ) == FR_OK )
|
||||||
|
{
|
||||||
|
printf( "MOUNTED %d\n", i );
|
||||||
|
ids[ i ] = i;
|
||||||
|
sprintf( names[ i ], "/mmc%d", i );
|
||||||
|
dm_register( names[ i ], ids + i, &mmcfs_device );
|
||||||
|
}
|
||||||
|
return DM_OK;
|
||||||
|
#endif // #if NUM_CARDS == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // #ifdef BUILD_MMCFS
|
#else // #ifdef BUILD_MMCFS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user