FatFS f_write无效

时间:2016-03-26 21:30:16

标签: c embedded sd-card bare-metal fatfs

我在ZedBoard上,我正在尝试在SD卡上写字。 我正在开发一个嵌入式系统,我没有任何操作系统,我正在运行裸机。

我可以从SD卡上读得很好,他们没问题。

但是当我试图阅读时,我有一些奇怪的行为:

  • f_write返回FR_OK
  • bw(写入的字节)变量是正确的
  • 创建文件(当我从电脑上读取SD卡时可以看到它)

但是当我读取文件时,它是空的。

这是我的代码:

void WriteFile(char const* fileName, char* buffer, size_t size)
{
    FIL file;
    FATFS fs;
    UINT bw;
    FRESULT fr;

    f_mount(&fs, "", 0);
    f_open(&file, fileName, FA_WRITE | FA_CREATE_ALWAYS);
    fr = f_write(&file, buffer, size, &bw);
    if (size != bw || fr != FR_OK)
        PRINT(("Error in writing !\n"));
    f_close(&file);
    f_mount(NULL, "", 0);
}

我称之为这样的方法:

 WriteFile("Hello.txt", "Hello World !", 13);

知道我做错了吗?

6 个答案:

答案 0 :(得分:2)

我找到了一个解决我问题的小黑客:
基本上它没有在SD卡上写入,因为缓冲区尚未满(在XILINX的低级API中)。
所以我做的很简单:我写一次数据。虽然文件的大小不等于或大于写入的数据的大小,但我写0(按块32)
另外,另一件重要的事情是:你写的数据必须是32字节对齐! 这是我的(工作)代码:

size_t SizeOfFile(char const *path)
{
    FILE *fp = fopen(path, "r");
    fseek(fp, 0, SEEK_END);
    size_t fsize = (size_t) ftell(fp);
    fclose(fp);
    return fsize;
}

void WriteFile( char const* fileName, char* buffer, size_t size )
{
    size_t allignement = ( size + 32 - 1 ) & ~ ( 32 - 1 );  // We must allign by 32
    char* Buffer_logger = pleb_malloc( allignement );
    pleb_memset( Buffer_logger, 0, allignement );
    pleb_memcpy( Buffer_logger, buffer, size );

    unsigned int BytesWr;
    size_t accum = 0;
    result = f_open( &file, fileName, FA_CREATE_ALWAYS | FA_WRITE | FA_READ );
    if ( result != 0 )
    {
        return;
    }

    sprintf( Buffer_logger, "%s", buffer );

    while ( SizeOfFile( fileName ) == 0 )
    {
        // Open log for writing
        result = f_open( &file, fileName, FA_WRITE );
        if ( result != 0 )
        {
            return;
        }

        // Point to the EOF
        result = f_lseek( &file, accum );
        if ( result != 0 )
        {
            return;
        }

        // Write to log
        result = f_write( &file, (const void*) Buffer_logger, size, &BytesWr );
        if ( result != 0 )
        {
            return;
        }

        accum += accum + strlen( Buffer_logger );

        //Close file.
        result = f_close( &file );
        if ( result != 0 )
        {
            return;
        }

        pleb_memset( Buffer_logger, 0, allignement );

        size = 32;
        pleb_memset( Buffer_logger, 0, size );
    }
    pleb_free( Buffer_logger );
    PRINT( ("Data written to log Successfully\r\n") );
}

答案 1 :(得分:0)

您只需刷新缓冲区(f_sync):

        FRESULT result;
        FATFS fs;
        FIL file;

        const char string[] = "Hallo world\0";
        uint16_t written = 0;
        FILINFO fno;

        /* Open or create a log file and ready to append */
        printf("mount:%d",f_mount(&fs, "", 1));
        printf("open: %d", f_open(&file, "log.txt", FA_WRITE  | FA_OPEN_ALWAYS ));
        printf("stat: %d", f_stat("log3.txt", &fno));
        printf("write: %d wr: %d", f_write(&file, string, 11, &written), written);
        printf("flush: %d", f_sync(&file));
        printf("close: %d", f_close(&file)); /* close performs sync before close */

答案 2 :(得分:0)

我有同样的问题,fatfs创建了该文件,但不会向其写入任何数据。没有由fatfs函数产生的错误所以我被困了2天然后我发现如果我在i / o层发送512字节块后放置一个断点,在我的代码中它的函数send_datablock(buff,0xFE) ))它会工作。

我发现在写入数据块后,SD需要时间将该块实际写入内部闪存,请参阅

http://elm-chan.org/docs/mmc/mmc_e.html

在单个块下写入忙碌时段DO行,您必须等待此时段结束才能发送任何其他命令(即另一个CMD24单个块写入),否则SD会丢弃最后一个CMD24因此您丢失了数据发送。

我在send_datablock函数的末尾添加了一个等待循环,如下所示

    /* if not accepted, return with error */
    if((data & 0x1F) != 0x05)
    {
        return 0;
    }
    else
    {
        /* wait for SD to finish writing data */
        tmr = 5000;
        do
        {
            data = get_response(SDEXIChannel);
            if(data != 0x00)
            {
                break;
            }
            udelay(100);
            tmr--;
        } while(0 != tmr);

        /* did we time out ? if so return with error */
        if(tmr == 0)
        {
            return 0;
        }

这似乎解决了我的问题,我现在可以写入SD卡上的文件,无论如何希望能节省两天的调试!

答案 3 :(得分:0)

我尝试使用Xilinx SoC(如ZedBoard)在SD上写入时遇到了同样的问题。我无法在SD卡上写入数据,即使:

  • 所有功能都成功。

  • 我能够删除并创建文件(所以我不是只读的)。

  • 当我回读我在卡片上写的内容时(f_lseek返回0和f_read)我读了正确的数据。

每次重启后我都会读取文件,它是空的。

我尝试过以前的解决方案,但没有一个有效。 史蒂夫的回答让我走上正轨。

FIX:我需要写入256字节的块才能将我的数据实际写入SD。 256字节是我SD卡中页面的大小,所以它会产生很多感觉。

如果写入不是256的倍数,则不会写入所有数据。 例如:

Bytes使用f_write写的 - >字节实际写入文件

512 - > 512

480 - > 256

255 - > 0

256 - > 256

希望它可以帮助某人:)

答案 4 :(得分:0)

我知道这是一篇旧文章,但是如果有人遇到此问题,我可以通过添加f_sync(&myFile);

来解决
            char myData[] = "Hello from STM32";
            if(f_write(&myFile, myData, strlen(myData), &myBytes) == FR_OK)
            {
                if(f_sync(&myFile) == FR_OK){
                    HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
                    HAL_Delay(500);
                    HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
                }
            }

答案 5 :(得分:0)

这是来自 Nordic NRF52 devkit,但我确实遇到了您的症状,因为我的每个 f_write 调用都发生在中断或北欧事件通知内,我猜这是不允许的。

我的修复:我创建了一个 WriteFromInterrupt() 函数以从中断和回调中调用,该函数将写入放入队列中,然后从我的 main() 循环中进行另一个调用,最终调用清空队列f_writef_sync