EmbeddedRelated.com
Forums

pf_open() returning FR_NO_FILE inspite of an existing file on microSD card

Started by kunalb 8 years ago14 replieslatest reply 8 years ago1398 views

I am trying to connect microSD card (transcend 2GB) to MSP430F67791 controller via SPI interface (USCI_B1).

I am using petit Fatfs library (latest R0.03) for this. (http://elm-chan.org/fsw/ff/00index_p.html)

In main(), I am calling the petit-FatFs functions in this order:

fileStatus = pf_mount(&fs);                  // FRESULT fileStatus;
fileStatus = pf_open(fileName);           // const char fileName[15] = "test.txt";
                                          // I even tried pf_open("test.txt")
 //In pffconf.h : #define _USE_LCC 1 /* Allow lower case characters for path name */
fileStatus = pf_write("Hello world!\r\n", 14, &bytesWritten);
fileStatus = pf_write(0, 0, &bytesWritten);

pf_mount() returns FR_OK but pf_open() is returning FR_NO_FILE, and this is the problem I'm facing. I made sure that the file exists and it exists in the root directory. From my computer, I formatted the card as FAT32 and created test.txt on it. I even tried writing a character in it from my computer so that the file size is non-zero.

The FR_NO_FILE status is returned by dir_find():

pf_open() -> follow_path() -> dir_find()

I had to write only 4 low-level SPI functions for the petit FatFs library to work on my MSP430.

void init_spi (void)
{
P4DIR |= BIT5 | BIT6;                                  // MOSI, CLK as o/p
P4DIR &= ~BIT4;                                         // MISO as i/p
P4SEL0 |= BIT4 | BIT5 |BIT6;                     // SPI
UCB1CTLW0 |= UCSWRST;                              // reset state
UCB1CTLW0 |= UCMST | UCSYNC | UCCKPL | UCMSB;                 // 3-pin, 8-bit SPI master
                                                                                                        // Clock polarity high, MSB
UCB1CTLW0 |= UCSSEL_2;                             // SMCLK
UCB1BRW = 84;                                                // SMCLK/84 = 200kHz
UCB1CTLW0 &= ~UCSWRST;                         // SPI on
}
void xmit_spi (BYTE d)
{
while (!(UCB1IFG & UCTXIFG)) ;                // USCI_B1 TX buffer ready?
UCB1TXBUF = d; // Transmit character
}
BYTE rcv_spi (void)
{
char recd_byte;
rcv_spi_count++;
xmit_spi(0xFF);
while (!(UCB1IFG & UCRXIFG));                    //USCI_B1 RX buffer filled ?
recd_byte = UCB1RXBUF;
return recd_byte; 
}
void dly_100us (void)
{
// MCLK= 16 MHz, 1 NOP = 0.06us, if microSec=1 then delay= (0.06*16) * 1 = 0.96us (approx 1 us)
unsigned int microSec= 100;
unsigned long int i;
for ( i= 16*microSec ; i > 0 ; i--)
{
_NOP();
}
}
#define SELECT() P4OUT &= ~BIT3                 // CS = L. P4.3 is configured as o/p
#define DESELECT() P4OUT |= BIT3               // CS = H

Can anyone help to let me know if I'm missing something or if the microSD card & SPI specs that I'm working with are ok ? Thanks

[ - ]
Reply by jorickNovember 3, 2016

On the Petit FAT File System page (http://elm-chan.org/fsw/ff/pf/appnote.html) I see: "_FS_FAT16 is 1. _FS_FAT12_FS_FAT32 and _USE_LCC are 0."  Since you're using FAT32, did you set _FS_FAT16 to 0 and _FS_FAT32 to 1?

[ - ]
Reply by kunalbNovember 3, 2016

yes, the flags are set correctly

[ - ]
Reply by stephanebNovember 3, 2016

As you can see, copying a question from stack overflow doesn't yield good results with the editor.  May I ask you to edit your post and fix this?  I can do it for you if you are unsure as to how to proceed.

[ - ]
Reply by Tim WescottNovember 3, 2016

Unless you've enabled long file names, you need to use "old DOS" names: meaning an 8.3 format where the characters used are limited to capital letters, numbers, and a few things like underscores (you'll have to look up for any more).  So:

THIS.TXT  is OK

my-cool-file.txt  is not

BOB_009.000  is OK

BOB_009.0000  is not.

Dunno what else to suggest -- I've scratched the surface of that code, but it's for a hobby project, and so I've been stalled at the verge of putting it on the debugger and seeing if it works with real hardware.

[ - ]
Reply by kunalbNovember 3, 2016

Thank you

[ - ]
Reply by kunalbNovember 3, 2016
I used FatFs instead of petit FatFs and wrote same corresponding low level SPI functions for FatFs and did not see the problem. Currently I'm trying to use f_sync() after couple of f_write() but getting FR_DISK_ERR returned. But f_close() works fine. For every FatFs function call I have a timeout of 10 attempts. My application is data logger and so I ideally do not want to close the file everytime after few f_write(). Does any one know of particular reasons why f_sync() would return error but f_close() works fine ?
[ - ]
Reply by jorickNovember 3, 2016

If FatFs worked and petit FatFs didn't, that may point to a bug of some sort in petit FatFs.  Can you use FatFs instead?  It has a small footprint as well, if space is an issue.

[ - ]
Reply by kunalbNovember 3, 2016

yes,I am using FatFs for my application but as described above, I'm struggling with f_sync() returning FR_DISK_ERR but f_close() working ok.

[ - ]
Reply by jorickNovember 3, 2016

I'm looking at the FatFs source code and f_close calls f_sync prior to actually closing the file.  So I can't see why it isn't working.  Could you post a code snippet?

[ - ]
Reply by kunalbNovember 3, 2016

My main() looks like this:

f_mount_timeout=10;
do        {        fMountStatus = f_mount (&myFs, "0:", 1);        }        
while(f_mount_timeout-- && fMountStatus);

f_open_timeout=10;
do        {        fOpenStatus = f_open(&fileObject, fileName, FA_OPEN_APPEND | FA_WRITE | FA_READ); }       
while(f_open_timeout-- && fOpenStatus);

f_write_timeout = 10;        
do        {        fWriteStatus = f_write(&fileObject, content, (stringSize-1), &bytesWritten);  }        
while(f_write_timeout-- && fWriteStatus);

f_sync_timeout=20;        
do        {        fsyncStatus = f_sync(&fileObject);        }        
while(f_sync_timeout-- && fSyncStatus);

All file functions except f_sync() return OK. f_sync() returns DISK_ERR. If I use f_close() instead of f_sync(), then f_close() returns OK after 2 attempts. I think using f_sync() for my data logger application is better than f_close() because after every f_close() I have to mount & open.

[ - ]
Reply by jorickNovember 3, 2016

I've looked over your code as well as the FatFs source code and I can't find anything that stands out.  So most likely there's a bug somewhere in the code you wrote that implements diskio.c, since DISK_ERR (or FR_DISK_ERR) comes from there.  My guess is that it's in the disk_write function.

[ - ]
Reply by kunalbNovember 3, 2016

Hi, i found that f_sync was not working because of a different problem and f_close was working ok because I tested my firmware under different SD card conditions. The real problem is that my file size is getting restricted to the Allocation Unit Size that is set during formatting of SD card as FAT32. The max Allocation Unit Size that can be set to an 8GB SDHC card is 64KB. I am not able to write into the file after it grows to 64KB. Is there something to be done once the file size reaches Allocation Unit Size of the SD card ?

[ - ]
Reply by kunalbNovember 3, 2016

My file function calls are same as above, except that now I'm calling f_write() 100 times before f_sync() and f_close(). So my code is as follows in a continuous loop :


f_mount_timeout=10;
do        {        fMountStatus = f_mount (&myFs, "0:", 1);        }        
while(f_mount_timeout-- && fMountStatus);

f_open_timeout=10;
do        {        fOpenStatus = f_open(&fileObject, fileName, FA_OPEN_APPEND | FA_WRITE | FA_READ); }       
while(f_open_timeout-- && fOpenStatus);

while(f_write_count < 100)  // f_write_count initialized to 0      
{
f_write_timeout = 10;        
do        {        fWriteStatus = f_write(&fileObject, content, (stringSize-1), &bytesWritten);  }        
while(f_write_timeout-- && fWriteStatus);
f_write_count++;

}
f_sync_timeout=20;        
do        {        fsyncStatus = f_sync(&fileObject);        }        
while(f_sync_timeout-- && fSyncStatus);

f_close_timeout=20;        
do        {        fcloseStatus = f_close(&fileObject);        }        
while(f_close_timeout-- && fcloseStatus);


I was hoping that after the file size reaches 64KB, f_close() & then f_mount() would take care of increasing the file size because I observed that after a reset to the system, it could write beyond 64KB. But I do not wish to reset my system for that. Is there any straight forward way to handle this situation ?

My file is a .csv file that I create on SD card before connecting it to MSP430 controller.

[ - ]
Reply by kunalbNovember 3, 2016

I thought creating a new thread for this new problem would be better. So it is posted here: https://www.embeddedrelated.com/thread/1257/