我在ZedBoard上,我正在尝试在SD卡上写字。 我正在开发一个嵌入式系统,我没有任何操作系统,我正在运行裸机。
我可以从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);
知道我做错了吗?
答案 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_write
和 f_sync
。