2

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

我可以从 SD 卡上正常读取,它们没问题。

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

  • f_write 返回 FR_OK
  • bw(写入的字节数)变量是正确的
  • 文件已创建(当我从 PC 读取 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);

知道我做错了什么吗?

4

6 回答 6

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") );
}
于 2016-05-08T21:13:26.960 回答
2

您可以只刷新缓冲区(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 */
于 2016-06-01T12:11:09.817 回答
1

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

  • 所有功能都成功。

  • 我能够删除和创建文件(所以我不在只读状态)。

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

每次我在重新启动后读取文件时,它都是空的。

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

修复:我需要按 256 字节的块写入数据才能将数据实际写入 SD。256 字节是我 SD 卡中一页的大小,所以这很有意义。

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

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

512 -> 512

480 -> 256

255 -> 0

256 -> 256

希望它可以帮助某人:)

于 2017-04-21T12:20:38.623 回答
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);
                }
            }
于 2020-04-04T21:47:08.983 回答
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 卡上的文件,无论如何希望可以节省两天的调试时间!

于 2016-12-14T23:31:50.160 回答
0

这是来自 Nordic NRF52 devkit,但我的症状正是您的症状,因为我的每一个f_write呼叫都发生在中断或北欧事件通知中,我猜这是不允许的。

我的解决方法:我创建了一个WriteFromInterrupt()从中断和回调中调用的函数,它将写入放入队列中,然后从我的 main() 循环中进行了另一个调用,最终通过调用f_writeand来清空队列f_sync

于 2021-07-15T13:43:37.647 回答