高优先级的线程播放音频,低优先级的线程负责按键和显示,当按键和显示条件越加越多,而实际上都没有执行,也会影响高优先级的调用时间片。中间多加几个sleep也没用。不理解这个是什么原理,高手帮忙解释下
代码贴出来有点乱,大概整理下逻辑。
线程进来后。死循环,先检测是否有按键按下,如果有,休眠180ms给其他线程(且作为防抖)。
接着根据不同的操作查看是否需要更新显示。如果需要,则更新显示后休眠20ms
循环一直执行
出问题的时候打印线程
thread pri status sp stack size max used left tick error
BtStack 19 ready 0x0000006c 0x00005000 13% 0x00000033 -01
Usart_Read 19 ready 0x00000064 0x00001000 35% 0x00000064 000
Usart_Write 19 ready 0x00000074 0x00001000 04% 0x00000010 -02
Keypad 22 ready 0x00000060 0x00000800 16% 0x00000005 -02
tshell 24 suspend 0x00000070 0x00001000 02% 0x00000007 000
sys_work 23 suspend 0x00000048 0x00000800 03% 0x0000000a 000
ulog_async 30 suspend 0x0000005c 0x00000400 08% 0x00000014 000
tidle 31 ready 0x00000054 0x00000100 32% 0x00000017 000
按键处理逻辑,其中按键和显示线程优先级是21,音频接收和播放线程优先级都是19,下方有一个#if 1, 如果改成#if 0 ,播放时序就必定被打乱。实际上,AudioBox(display.ui.mode) 一直都是LCD_UI_MODE_COMMON,没有按键时不会进去其他模式,但是表现是播放时序明显变慢。
实测就是低等级的判断逻辑或者线程数多了,就会影响高等级的处理时序,证明线程调度还不是很智能,我把msh线程删了就可以工作了
1 线程调度本来就不是智能,是规则,优先级和时间片;
2 看一下你的CPU是不是够用;
3 看一下你的低优先级任务里是不是关中断、锁任务调度了;
4 看一下你的中断是不是占用过长时间;
@winfeng
感谢回复。
困扰了我快一周,最终验证测试,是因为代码空间超出了一定大小,可以执行,但是效率变得非常低。估计GD32的code area 超出之后512K就需要做重新寻址。
我验证方式是,低等级线程(按键处理)在一定的条件后直接退出。此时高等级的线程(音频接收和播放)调度依旧会受影响。当删除掉一点其他代码,就又正常了。所以是和代码大小有关,和线程调度应该没有关系
调查到这里就有点尴尬了。本身我是做蓝牙协议栈的。压缩得很辛苦才勉强够用。
各位大侠有什么好的建议吗?
下方粗体的是编译最终大小的信息。
Build started: Project: project
* Using Compiler ‘V5.06 update 6 (build 750)’, folder: ‘C:\Keil_v5\ARM\ARMCC\Bin’
Build target ‘rt-thread_gd32f4xx’
compiling key_pad.c…
applications\key_pad.c(765): warning: #111-D: statement is unreachable
rt_kprintf(“exit KeyPad Procress\n”);
applications\key_pad.c(359): warning: #177-D: function “ProcessKeyWithEditMode” was declared but never referenced
static void ProcessKeyWithEditMode(uint32_t keystate)
applications\key_pad.c: 2 warnings, 0 errors
linking…
Program Size: Code=345404 RO-data=115684 RW-data=1372 ZI-data=139068
FromELF: creating hex file…
“.\build\rtthread-gd32f4xx.axf” - 0 Error(s), 2 Warning(s).
Build Time Elapsed: 00:00:06
Load “C:\workspace\EsMcuStack_gd32450vit6\build\rtthread-gd32f4xx.axf”
Set JLink Project File to “C:\workspace\EsMcuStack_gd32450vit6\JLinkSettings.ini”
**
看 gd 的芯片手册,关于 flash 容量大小,看过了会有些莫名的被骗的感觉,宣称的大小不是一般意义的大小。跟乡镇银行推销理财产品一样一样的。
@Clark
还能这样?是不是类似那种整块儿cache
@出出啊
是的,他有两个区域,一个代码区域,一个存储区域。
然后我自虐用他来做蓝牙音频。当然,放弃掉蓝牙电话协议,只是音频,应该也是够。
做完这波再说吧,还好是预研,不是直接上产品,要不周期不知道要拉长多久。
GD的坑不止这个,还有DMA,还有各种寄存器不清不楚
@winfeng
我理解的是代码区域是映射表可以操作的地方,至于IC的内核怎么设计我就不了解了。
个人觉得应该覆盖整个Flash应该也不麻烦,可能会损失性能吧。
应该不是Cahche的概念,因为RAM只保留当前运行的函数和全局变量。运行结束之后就释放了。
看起来更像是内核管理Flash区域就只有512K,多出的也可以放代码,但是要重新做一遍寻址。这样就会额外消耗运算时间。
表现现象就是,多加点代码(即使当前不运行),也会导致音频处理线程效率变低。