FATFS multiple drives

Go To Last Post
31 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have version 7e and it's supposed to support multiple drives, but i don't know how to do it. If i call

disk_intialize(param.);

this function checks if param > 0 and if so, exits. SO how would i use 2 or more cards if param. is always 0 ? I don't see ANYTHING in ANY of the functions that allow selecting 1 of multiple cards, say i do an f_read(), how's it determined which card to read from ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

this function checks if param > 0 and if so, exits

Clearly this is a bit of "future planning" on Chan's part and is not implemented yet. The "state" of a file system is, in theory, fully encapsulated in the FATFS structure so that the code should be able to keep two or more contexts but you'd need to audit Chan's entire code and see if you can find any places where there is non-reentrancy and also that no assumptions are made about drive number.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So then this example from his site is just fluff. I was afraid of that. Thanks.

void main (void)
{
    FATFS fs[2];         /* Work area (file system object) for logical drives */
    FIL fsrc, fdst;      /* file objects */
    BYTE buffer[4096];   /* file copy buffer */
    FRESULT res;         /* FatFs function common result code */
    UINT br, bw;         /* File read/write count */


    /* Register work area for logical drives */
    f_mount(0, &fs[0]);
    f_mount(1, &fs[1]);

    /* Open source file on the drive 1 */
    res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
    if (res) die(res);

    /* Create destination file on the drive 0 */
    res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
    if (res) die(res);

    /* Copy source to destination */
    for (;;) {
        res = f_read(&fsrc, buffer, sizeof(buffer), &br);    /* Read a chunk of src file */
        if (res || br == 0) break; /* error or eof */
        res = f_write(&fdst, buffer, br, &bw);               /* Write it to the dst file */
        if (res || bw < br) break; /* error or disk full */
    }

    /* Close open files */
    f_close(&fsrc);
    f_close(&fdst);

    /* Unregister work area prior to discard it */
    f_mount(0, NULL);
    f_mount(1, NULL);
}

Edit: I just found this in his "filename" page --

Quote:
Correspondence between logical and physical drives

The FatFs module has work areas that called file system object for each volume (logical drive). In default, the logical drive is bound to the physical drive that has same drive number, and the first partition is mounted. When _MULTI_PARTITION == 1 is specified in configuration option, each individual logical drive can be bound to any physical drive/partition. In this case, a drive number resolution table must be defined as follows:

Example: Logical drive 0-2 are assigned to three pri-partitions on the physical drive 0 (fixed disk)
Logical drive 3 is assigned to physical drive 1 (removable disk)

const PARTITION Drives[] = {
{0, 0}, /* Logical drive 0 ==> Physical drive 0, 1st partition */
{0, 1}, /* Logical drive 1 ==> Physical drive 0, 2nd partition */
{0, 2}, /* Logical drive 2 ==> Physical drive 0, 3rd partition */
{1, 0} /* Logical drive 3 ==> Physical drive 1 */
};

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, did you build the full FATFS, or a Tiny or Pico version?

Note that your original excerpt of the disk_initialize() rejection I find in mmc.c . That is a different "layer" of that system than fopen() etc. Are all the drivers besides MMC/SD coded the same way?

[Beyond that I can't help, as I've only done Tiny with single-file.]

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Quote:

Note that your original excerpt of the disk_initialize() rejection I find in mmc.c .

The issue here is that this is to do with FatFs support on differing systems. If you download ffsample.zip and look in the avr sub-dir you find disk_initialize() in ata.c (ATA IDE), cfc.c (CompactFlash Card), cfmm.c (CFC and MM combined) and mmc.c (SD/MMC). If you look at each you see:

ata.c

	if (drv) return STA_NOINIT;		/* Supports only single drive */

cfc.c

	if (drv) return STA_NOINIT;				/* Supports only single drive */

cfmm.c (uses the function parm to pick CFC or MMC)

	switch (drv) {
	case CFC :
		return CF_disk_initialize();
	case MMC :
		return MM_disk_initialize();
	}

mmc.c

	if (drv) return STA_NOINIT;			/* Supports only single drive */

HOWEVER now look at win32/diskio.c:

	if (drv >= 10) {
		sta = STA_NOINIT;
	} else {
		get_status(&Stat[drv]);
		sta = Stat[drv].status;
	}

It supports TEN drives! That's where the parameter to disk_initialize() really gets exercised.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
So, did you build the full FATFS, or a Tiny or Pico version?
Full FatFS. Well, maybe when I find enough time I'll try to update his avr/mmc code according to the win32/mmc model( thanks for pointin' this out Cliff ).

I'm working on a contract that uses 2 SD cards:

MCU ---> ssd1926 ( jpeg codec )-->SD mode card
|
|--> SPI mode card

I'm now thinking that I can use the FATFS based filesystem ( it's modified ), that's pointing to SD mode card( via '1926) thru MCU parallel I/F and just duplicate relevant file functions. Rename those and make them point to SPI I/F ! I'll have to also account for all globals used by these ( sigh ). It should work, i guess. :lol:

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you need to access both cards at once? If not then initialise/mount card 1 and do file functions then unmount, switch your lowest level mmc.c functions to operate on the other card then initialise/mount that one.

However I suspect you maybe want to copy from one card to the other and have both "open" at the same time?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Do you need to access both cards at once?

Quote:
However I suspect you maybe want to copy from one card to the other and have both "open" at the same time?
Yep, to both.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quick update Clawson. The codec chip has a 256KB buffer
so after f_opening() the file on SD mode card, I see now that i can do a DMA SD_card --> '1926 buffer, f_close(), turn off the SD_card, then just do indirect 8 bit // port read of the buffer and f_write() out to SPI_Card. Love this codec chip !!

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to use 2 physical drives with fatfs one as
SD card ans other is USB .
I tries to mount with f_mount and then trying for f_open ..but it is not working

Can somebody tell me how to use 2 physical drives with fatfs?

Thanks in advance.

Poonam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tested with each of the physical drives?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for reply.

yes..i have tested with each drive independently.

and it worked fine..but when i am trying to do with 2 drives its no working.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show the smallest test program that demonstrates it not working. (Often in reducing to such a test program you'll find the fault anyway ;-))

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

actually is it possible to use SD card and USB at the same time with fatfs???

I am trying like below lines.

1st mounting 2 drives with 0 and 1 and then trying to open which is failing.

(f_mount(0, &fs[0]) == FR_OK)
(f_mount(1, &fs[1]) == FR_OK)

and then trying to open using f_open but it is failing..

should i maintain 2 diffrent file structure for 2 drives.
I am totally confused.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 is talking about some version 7e..may i know what is that version?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have not done anything with Fat FS for a long time now, but in version 7 by head it was not possible to mount 2 drives without changing the FATfs code.

I do also not recall anybody here having tried that before.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I doubt the example of f_open() in the user manual:

http://elm-chan.org/fsw/ff/en/op...

would have used 2 drives if it were not supported (I assume Chan actually tested that!).

However you usually provide one level of disk_initialize(), disk_read(), disk_write(). Not sure how you tell it to do SD/MMC on one and USB on another? Presumably it's the fact that drive_initialize() takes a "disk number" parameter? But within it's going to have to have something like "if drive==0 then init_SD else init_USB" etc. Similarly disk_read and disk_write take a drive number so must be re-directed appropriately too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the reply.

I am doing as follows inside disk_init:
DSTATUS disk_initialize(BYTE drv)
{
char buff[10];
printf("Drive is getting intialized\n");
if (drv)
return STA_NOINIT;

switch(drv){
/* For SD*/
case '0':
sdio_init(0, 0);
printf("SDIO intialization successfully\n");
if (!sdio_card_detect())
{
return STA_NODISK;
}
sdio_power_on();
printf("SDIO power on is done successfully\n");
if (sdio_acquire())
{
disk_inited = 1;
return STA_OK;
}
sdio_read_blocks(buff,0,0);
break;
/*For USB*/
case'1':
if(1)
{
disk_inited = 1;
return STA_OK;
}
break;

default:
return STA_NODISK;
}
}

this is my disk init function where i am differentiating for sdio and usb
but still its not working .

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And do disk_read() and disk_write() have similar switches?

(Also are you sure you want to switch on ASCII '0'/'1' rather than binary 0/1? Though I suppose it doesn't matter as long as you are consistent).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes disk_read and disk_write is also having similar switches as follows
DRESULT disk_read(
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buf, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count) /* Sector count (1..128) */
{
int stat = disk_status(drv);

bytes_transferred = 0;
if (stat != STA_OK && stat != STA_PROTECT)
return RES_ERROR;
if (count == 0)
return RES_PARERR;

switch(drv){
/* For SD*/
case SD_DRIVE:
bytes_transferred = sdio_read_blocks(buf, sector, sector + count - 1);
if (bytes_transferred != count * MMC_SECTOR_SIZE)
return RES_ERROR;
break;
/*For USB*/
case USB_DRIVE:
//bytes_transferred = MS_Host_ReadDeviceBlocks(&FlashDisk_MS_Interface, 0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer);
if (USB_HostState != HOST_STATE_Configured)
{
return RES_NOTRDY;
}
else if (MS_Host_ReadDeviceBlocks(&FlashDisk_MS_Interface, 0, sector, count, 512, buf))
//else if (MS_Host_ReadDeviceBlocks(&FlashDisk_MS_Interface, 0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer))
{
MS_Host_ResetMSInterface(&FlashDisk_MS_Interface);
return RES_ERROR;
}
break;
}
return RES_OK;
}

DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buf, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count) /* Sector count (1..128) */
{
int stat = disk_status(drv);

bytes_transferred = 0;
if (stat != STA_OK)
return RES_ERROR;

switch(drv){
/* For SD*/
case SD_DRIVE:
if (count == 0)
return RES_PARERR;
bytes_transferred = sdio_write_blocks((BYTE *)buf, sector, sector + count - 1);
if (bytes_transferred != count * MMC_SECTOR_SIZE)
return RES_ERROR;
/*For USB*/
case USB_DRIVE:
if (USB_HostState != HOST_STATE_Configured)
{
return RES_NOTRDY;
}
else if (MS_Host_WriteDeviceBlocks(&FlashDisk_MS_Interface, 0, sector, count, 512, buf))
{
MS_Host_ResetMSInterface(&FlashDisk_MS_Interface);
return RES_ERROR;
}
break;
}
return RES_OK;
}

i changed that switch case name into macro and using that one..i have to check whther it will work or not

thanks
Poonam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I have tried like below by giving
#define SD_DRIVE 1
#define USB_DRIVE 0

/* SD_USB at a time*/
f_mount(USB_DRIVE, &fs[0]);
f_mount(SD_DRIVE, &fs[1]);
rc = f_open(&fsrc, "0:Aizyc.txt", FA_OPEN_EXISTING | FA_READ);
rm = f_open(&fdst, "1:Aizyc_sd.txt", FA_CREATE_ALWAYS | FA_WRITE);
/* Close open files */
f_close(&fsrc);
f_close(&fdst);
/* Unregister work area prior to discard it */
f_mount(SD_DRIVE, NULL);
f_mount(USB_DRIVE, NULL);

/* end of SD_USB at a time*/

but rc is returning FR_OK and rm is returning FR_NO_FILESYSTEM

means it worked for drive 0..please help me

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But hold on a minute. You have:

#define SD_DRIVE 1
#define USB_DRIVE 0 

But in disk_initialize() you have:

/* For SD*/
case '0': 
...
/*For USB*/
case'1': 

Ever watched Sesame Street? Ever heard the phrase "one of these things is not like the other one"?

I said '0'/'1' seemed like an odd choice but would be OK iof you were consistent. However you do not appear to be consistent.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

no i changed my disk_int routine also like wise
DSTATUS disk_initialize(BYTE drv)
{
char buff[10];
printf("Drive is getting intialized\n");
if (drv)
return STA_NOINIT;

switch(drv){
/* For SD*/
case SD_DRIVE:
sdio_init(0, 0);
printf("SDIO intialization successfully\n");
if (!sdio_card_detect())
{
return STA_NODISK;
}
sdio_power_on();
printf("SDIO power on is done successfully\n");
if (sdio_acquire())
{
disk_inited = 1;
return STA_OK;
}
sdio_read_blocks(buff,0,0);
break;
/*For USB*/
case USB_DRIVE:
if(1)
{
disk_inited = 1;
return STA_OK;
}
break;

default:
return STA_NODISK;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to print the fatfs *fs structure variables for SD and USB after f_mount but the variables for USB is holding some values as it is drive 0 and variables for SD are all Zeros [0].

/*structure i tried to print */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect;
} fatfs

plz let me know whether we should write different structure for both drive or any help will be appreciated..

Thanks
Poonam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there some reason you are not able to debug this yourself? Why not step into the code that fills the fatfs structure and find out what's happening in the SD case.

(BTW you obviously need separate structures for each file system - it wasn't clear from your post if you were maybe trying to share one?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Besides from what clawson mentioned, there’s this;

DSTATUS disk_initialize(BYTE drv)
{
char buff[10];
printf("Drive is getting intialized\n");
if (drv)
return STA_NOINIT;
…

A value anything but zero for the parameter drv, will exit the function with STA_NOINIT.
The compiler will probably never compile the code starting with ‘case USB_DRIVE’, because it will never switch to that. Didn’t the compiler warn for that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes i am sharing the same below fatfs structure for both SD and USB...

typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect;
} fatfs

we are mounting both drives with fatfs then y we need seperate file structure.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

USB_DRIVE is macro defined as 0...so compilier dint give any error for that...

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
USB_DRIVE is macro defined as 0...so compilier dint give any error for that...

But that's not the one that would have the problem. You used:

#define SD_DRIVE 1
#define USB_DRIVE 0 

then:

DSTATUS disk_initialize(BYTE drv)
{
  char buff[10];
  printf("Drive is getting intialized\n");
  if (drv)
    return STA_NOINIT;

so when you use:

disk_initialize(SD_DRIVE);

that's going to immediately return STA_NOINIT without having initialized anything - it never makes it as far as the switch()/case:

One thing this highlights is that when any of these functions return a status/error code you should test it. Don't just use:

disk_initialize(SD_DRIVE);

but:

result = disk_initialize(SD_DRIVE);
if (result != 0) {
  abort("something is seriously wrong");
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

poonam_arnav wrote:
USB_DRIVE is macro defined as 0...so compilier dint give any error for that...

Thanks


Yeah, well ‘in general’ when using the switch statement we start with the lowest value(0 for example), and go up from there, but it’s not necessary to do it that way, the switch statement will branch to the first ‘true’ case expression it encounters, or will go down to the ‘default’ if exist, or quit the switch if no expression is true.

If what clawson explained still does not ring a bell, then I suggest you to buy the K&R bible, and read some basic ‘C’ programming verses.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

disk int for SD and uSB is working fine
disk_initialize(USB_DRIVE);
disk_initialize(SD_DRIVE);

while doing f_open for both drives it creating problem