硬汉嵌入式论坛

 找回密码
 立即注册
查看: 322|回复: 17
收起左侧

[STM32H7] STM32H7 U盘记录数据会打断GUI刷屏异常问题

[复制链接]

59

主题

674

回帖

856

积分

金牌会员

积分
856
发表于 2025-8-1 08:59:42 | 显示全部楼层 |阅读模式
STM32H7 U盘记录数据打断GUI刷屏现象,导致GUI会卡顿1S左右。
应用是这样的设计的,SPI DMA接收数据100ms进入一次中断然后通知读数据任务进行数据拷贝这个优先级最高,这个数据也用于GUI显示和U盘记录的数据写成csv格式。U盘记录数据要求最高也是100ms记录一次数据即1s钟会记录10次,同时也记录时间由RTC提供。如果不开数据记录GUI刷屏都是正常的,开了U盘数据记录就时不时卡顿一下。U盘记录数据任务优先级高于GUI刷屏,如果调整优先级GUI高于U盘,这样U盘记录数据时间就对不上了。任务优先级如下排序

1、SPI中断->拷贝数据,最高任务。
2、IIC任务,读取RTC同时保存参数用,
3、U盘记录数据。
4、GUI刷屏任务。
这样U盘记录数据就是正常的1S记录10个数据,如果3和4互换一下,GUI是不卡顿,但是U盘记录数据就不正常了,U盘的数据每次写入大概2K数据,写一次用时大概3ms左右,怀疑是写U盘的时候打断了GUI,用的是STUSB+Fatfs。开始怀疑是显示和U盘数据共享问题,改成两组数据,一组用于显示,一组数据用于U盘存储,也没有解决问题。
现在不知道啥解决这个问题,特来发帖请教一下。

回复

使用道具 举报

5

主题

269

回帖

284

积分

高级会员

积分
284
发表于 2025-8-1 09:42:00 | 显示全部楼层
有可能u盘任务和ui任务的用户代码里有死等待的地方
也有可能是u盘的小数据写入速度不够快,把单次写入数据量扩大看看会不会好些,比如单次写32K或64K这样


比如这是某个u盘的读写速度,可以看到在单次写入量4KB及以下时速度是非常慢的,你可以用ATTODiskBenchmark测下u盘的实际写入速度

QQ20250801-093754.png

回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-1 09:49:28 | 显示全部楼层
DX3906 发表于 2025-8-1 09:42
有可能u盘任务和ui任务的用户代码里有死等待的地方
也有可能是u盘的小数据写入速度不够快,把单次写入数据 ...

我也发现这个问题,用了几个U盘,出现卡顿的几率又有所不同,毕竟新的U盘就非常好,旧的U盘这个插入电脑就提示修复的就很容易出现卡顿,但是还是要想解决这个问题,做产品不能跟用户说U盘有问题啊。
回复

使用道具 举报

5

主题

269

回帖

284

积分

高级会员

积分
284
发表于 2025-8-1 14:26:39 | 显示全部楼层
ou513 发表于 2025-8-1 09:49
我也发现这个问题,用了几个U盘,出现卡顿的几率又有所不同,毕竟新的U盘就非常好,旧的U盘这个插入电脑 ...

那可以试试把单次写入量搞大些
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-8-1 14:43:58 | 显示全部楼层
ou513 发表于 2025-8-1 09:49
我也发现这个问题,用了几个U盘,出现卡顿的几率又有所不同,毕竟新的U盘就非常好,旧的U盘这个插入电脑 ...

有个办法不知道满足需求不,U盘写入后,GUI刷新数据从U盘读取出来刷新,这样是不是就互不影响了。
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-1 15:33:15 | 显示全部楼层
eric2013 发表于 2025-8-1 14:43
有个办法不知道满足需求不,U盘写入后,GUI刷新数据从U盘读取出来刷新,这样是不是就互不影响了。

不行,数据存储是外挂U盘的,然后存储的数据内容也是可以随意设定的,1-255个数据内容。就是现在想确认的问题是不是就因为存储任务打断了GUI写数据到U盘里导致的卡顿。我已尝试了存储数据任务正常跑屏蔽fwrite写操作就不会卡顿了,推测应该就是写操作导致了GUI卡顿的现象。
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-1 15:36:31 | 显示全部楼层
本帖最后由 ou513 于 2025-8-1 15:38 编辑
DX3906 发表于 2025-8-1 14:26
那可以试试把单次写入量搞大些

我觉得不是单次写入数据量的问题,应该就是写数据导致的,GUI被打断了因为GUI优先级最低,就需要等到下一次高优先级的任务运行完成后因为还有其他的高优先级任务,GUI任务才得到运行从而跳出了卡顿现象重新刷新数据。尝试写入少量数据几个字节也会出现但是概率会低一些。
回复

使用道具 举报

0

主题

40

回帖

40

积分

新手上路

积分
40
发表于 2025-8-1 18:09:30 | 显示全部楼层
比较容易,U盘数据的时候,实现多缓冲,比如一次记录10个数据后,在GUI空闲的时候,其他空闲的时候,写入一条,依次类推。
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-1 23:06:21 | 显示全部楼层
a13421364618 发表于 2025-8-1 18:09
比较容易,U盘数据的时候,实现多缓冲,比如一次记录10个数据后,在GUI空闲的时候,其他空闲的时候,写入一 ...

这个不太理什么时候确定GUI空闲呢,U盘数据是也是由spi读数据任务通知的,设计是接收到一个新的数据就通知U盘记录数据,这个spi是从设备被动接收数据,数据频率就是100ms发过来一次。我也在想先保存要存储的数据到缓存中,然后再写入U盘,就你说的GUI空闲这个什么把握?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-8-2 09:22:23 | 显示全部楼层
ou513 发表于 2025-8-1 23:06
这个不太理什么时候确定GUI空闲呢,U盘数据是也是由spi读数据任务通知的,设计是接收到一个新的数据就通 ...

这种的话,直接把U盘存储数据和GUI放在一个任务里面。如果是emWin处理这个比较简单。之前完毕GUI_Exec就可以处理U盘,你的是100ms一次,正常可以处理的过来。处理不过来就考虑弄个FIFO,这样可以一次将之前未及时写入的处理了。

回复

使用道具 举报

7

主题

158

回帖

179

积分

初级会员

积分
179
发表于 2025-8-2 10:53:24 | 显示全部楼层
做过类似的50MS纪录一次,写数据用缓存
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-2 13:45:22 | 显示全部楼层
eric2013 发表于 2025-8-2 09:22
这种的话,直接把U盘存储数据和GUI放在一个任务里面。如果是emWin处理这个比较简单。之前完毕GUI_Exec就 ...

这个我也有考虑过,但是具体还不知道啥做,就GUI任务现在就如下代码,就是处理队列消息。U盘数据记录也是要消息通知保存的,


        while (1)
        {               
               
                status = osMessageQueueGet(ToGUIQueueHandle, &MSG, 0, 10);
               
               if (status == osOK)
                {
                        if (MSG.hWin != 0 && (MSG.MsgId == WM_DSP_FEFRESH || MSG.MsgId == WM_REFRESH_LANGUAGE
                                || MSG.MsgId == DSP_FACTORY_INIT || MSG.MsgId == WM_FACTORY_INIT))
                        {
                                WM_SendMessageNoPara(MSG.hWin, MSG.MsgId);
                       }


                    /*是不是在这里处理U盘数据*/
                        else if (MSG.hWin==U盘消息)   
                   {
                      保存数据操作。
                   }
             }                               
          GUI_Delay(10);
          /* 还是在这里操作,这里就是GUI_Exec执行后可以操作?*/


        }

回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-2 13:48:01 | 显示全部楼层
mygod 发表于 2025-8-2 10:53
做过类似的50MS纪录一次,写数据用缓存

缓存应该也是解决了不最终的问题,只能说机率小些,U盘操作总是还会打断GUI的。硬汉的方案正在考虑调试看看效果
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-8-3 10:52:36 | 显示全部楼层
ou513 发表于 2025-8-2 13:45
这个我也有考虑过,但是具体还不知道啥做,就GUI任务现在就如下代码,就是处理队列消息。U盘数据记录也是 ...

也可以考虑直接通过osMessageQueueGet(ToGUIQueueHandle, &MSG, 0, 10);接收消息
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-4 07:54:57 | 显示全部楼层
eric2013 发表于 2025-8-3 10:52
也可以考虑直接通过osMessageQueueGet(ToGUIQueueHandle, &MSG, 0, 10);接收消息

上班准备调试看看效果
回复

使用道具 举报

5

主题

269

回帖

284

积分

高级会员

积分
284
发表于 2025-8-4 14:11:15 | 显示全部楼层
ou513 发表于 2025-8-1 15:36
我觉得不是单次写入数据量的问题,应该就是写数据导致的,GUI被打断了因为GUI优先级最低,就需要等到下一 ...

只写几个字节也会出现,那感觉可能是fwrite消耗时间太长了,我觉得你可以用示波器或者逻辑分析仪测一下fwirte的执行时间,ui任务人能感觉到卡顿至少是10ms以上的卡顿了
回复

使用道具 举报

5

主题

269

回帖

284

积分

高级会员

积分
284
发表于 2025-8-4 14:14:15 | 显示全部楼层
ou513 发表于 2025-8-2 13:45
这个我也有考虑过,但是具体还不知道啥做,就GUI任务现在就如下代码,就是处理队列消息。U盘数据记录也是 ...

这部分逻辑可以优化下,osMessageQueueGet最后一个参数填0或者1,最长等待1ms获取消息,获取不到就赶紧退出来
这部分现在是先等10ms获取消息,然后GUI_Delay刷新并延时10ms,最坏情况下,ui需要间隔20ms才能刷新一次
回复

使用道具 举报

59

主题

674

回帖

856

积分

金牌会员

积分
856
 楼主| 发表于 2025-8-4 14:17:03 | 显示全部楼层
DX3906 发表于 2025-8-4 14:14
这部分逻辑可以优化下,osMessageQueueGet最后一个参数填0或者1,最长等待1ms获取消息,获取不到就赶紧退 ...

好,着手调试一下看看效果,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 06:12 , Processed in 0.049651 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表