完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
最近开发log存储器,移植FATFS文件系统,四路串口通道接收数据后存储在SD卡内。在调试中设置串口波特率为256000bps,每10ms发送250个字节,四路通道同时工作,MCU主频为120MHz,使用一张CLASS4 8G卡和一张CLASS10 16G卡进行测试。在测试中使用8G卡速度上不来导致数据丢失,为了提高SD卡兼容性与稳定性,竭力挖掘SD性能,提高写入速度。
开发环境 主控MCU : STM32F205RE SD硬件接口 : SDIO SD卡 : 金士顿16G(CLASS10)、金士顿8G(CLASS4) FATFS版本 : R0.11 软件开发库 : HAL库 SD底层驱动 1、SD驱动配置为4线数据总线可提高速度,在SD卡初始化后调用库函数HAL_SD_ConfigWideBusOperation()可配置4线数据总线。 2、配置SD读写为DMA中断方式,关于SD中断与DMA中断哪个优先级高的问题,网上众说纷纭。但发现在HAL库中stm32f2xx_hal_sd.c 原文注释:Configure the SDIO and DMA interrupt priorities using functions HAL_NVIC_SetPriority();DMA priority is superior to SDIO priority.(不加翻译,免得暴露英文水平) 提高FATFS利用效率 1、对于高频操作文件,可以上电直接打开文件f_open,之后除非读写失败之外不再关闭文件f_close,使用f_sync代替f_close写入SD卡。同时为了防止断电丢失大量数据的情况,可以在f_write之后加f_sync。 f_open(); while (1) { if (get_data()) { f_write(); f_sync(); } } f_close; 2、加入队列配合FATFS文件系统写数据,底层串口接收到的数据放入队列中,应用层去队列中拿数据写入SD卡。对于数据吞吐量比较大的可以设置大一些队列,我设置了队列数据节点为1k字节,开了100个队列。队列数据节点越大,写入的块数据就越大,写SD卡速度就越快。 测试数据块大小对写入速度的影响 测试方法: 测试方法: #define DATA_SIZE 512 //数据块大小 #define DATA_CYCLE (8192 * 2) uint8_t buffer[DATA_SIZE]; void test_sd_rate(void) { int i; f_open(); //调用计时 for (i = 0; i < DATA_CYCLE; i++) { f_write(, buffer, DATA_SIZE, ); } f_sync(); //统计计时 } 核心代码 #define FILE_CLOSE 0x00 #define FILE_OPEN 0x01 #define SD_FULL_MEM 0x01 #define SD_NOT_FULL_MEM 0x00 #define SD_LIMIT_MEMORY_MB 10 static const char *files[4] = { "CHANNEL2.TXT", "CHANNEL3.TXT", "CHANNEL4.TXT", "CHANNEL6.TXT" }; static uint8_t files_status[4] = { FILE_CLOSE, FILE_CLOSE, FILE_CLOSE, FILE_CLOSE }; uint32_t byteswriten; FATFS SDFatFS; char SDPath[4]; FIL fileobj[4]; QNODE data; /* 队列数据节点 */ FRESULT open_append(FIL* fp, const char* path) { FRESULT fr; fr = f_open(fp, path, FA_WRITE | FA_OPEN_ALWAYS); if (fr == FR_OK) { fr = f_lseek(fp, f_size(fp)); if (fr != FR_OK) { f_close(fp); } } return fr; } /* 查询SD卡内存容量 */ static uint8_t query_sd_memory(void) { int ret; DWORD file_nclst; uint32_t free_mbs; FATFS *fs = &SDFatfs; ret = f_getfree(SDPath, &file_nclst, &fs); if (ret != FR_OK) { printf("f_getfree = %d n", ret); } free_mbs = file_nclst * (f->csize) / 2 / 1024; if (free_mbs <= SD_LIMIT_MEMORY_MB) return SD_FULL_MEM; return SD_NOT_FULL_MEM; } void fatfs_link_driver_init(void) { if (FATFS_LinkDriver(&SD_Driver, SDPath) == 0) { if (f_mount(&SDFatfs, SDPath, 0) != FR_OK) { printf("SD卡挂载文件系统失败!n"); } } } void log_task(void) { int ret; static uint8_t sd_memory_status = SD_NOT_FULL_MEM ; if (false == queue_remove(&g_queue, &data)) return; if (BSP_SD_IsDetected() == SD_NOT_PRESENT || g_system_restart) return; if (sd_memory_status == SD_FULL_MEM ) return; if (files_status[data.channel] == FILE_CLOSE) { open_append(&fileobj[data.channel], files[data.channel]); files_status[data.channel] = FILE_OPEN; } sd_memory_status = query_sd_memory(); ret = f_write(&fileobj[data.channel], data.data, data.len, &byteswritten); if (ret != FR_OK || byteswritten != data.len) { f_close(&fileobj[data.channel]); files_status[data.channel] = FILE_CLOSE; } ret = f_sync(&fileobj[data.channel]); if (ret != FR_OK) { f_close(&fileobj[data.channel]); files_status[data.channel] = FILE_CLOSE; } } 总结 经过以上一些处理,可以提高SD卡读写速度,除了优化SD底层驱动外,对于写失败或关闭文件失败的情况并没有很好的应对方案。如果您有更好的建议,欢迎留言。 |
|
|
|
只有小组成员才能发言,加入小组>>
3323 浏览 9 评论
3000 浏览 16 评论
3498 浏览 1 评论
9073 浏览 16 评论
4093 浏览 18 评论
1192浏览 3评论
613浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
603浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2341浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1899浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-29 13:45 , Processed in 1.090961 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号