找回密码
 立即注册
查看: 415|回复: 8

STC单片机 uC/OS-II核心技术(9):不使用任何中断的uC/OS-II移植版

[复制链接]

该用户从未签到

63

主题

660

回帖

1万

积分

荣誉版主

积分
10806
发表于 2023-10-4 20:51:38 | 显示全部楼层 |阅读模式
本帖最后由 杨为民 于 2024-3-31 10:57 编辑

一、梦想照亮现实
(1)有个人说:“我有一个梦”,然后那个梦就实现了。有个网友有个理想:
Fig_01_理想.jpg
对于单片机应用中断是最重要的实时响应技术手段。我理解他理想的RTOS系统是:
如果一个硬件中断的条件成立,就应该让该中断立刻发生,实现实时响应。
具体地说,对于STC32G单片机,理想的RTOS系统在任何时候都不应该关闭总中断(EA=0),哪怕关闭的极短的时间也不行,因为这个极短的关闭总中断的时间就成了限制RTOS系统的实时响应时间的上限。
(2)根据前文介绍的中断外任务切换方法,笔者认为V1.20版本的“挑战者x51 uC/OS-II移植版”已经实现了这个理想。
二、不使用任何中断的uC/OS-II移植版

(3)在前文范例的基础上,笔者删去了挑战者x51 V1.10版本中的与中断有关的程序,形成了V1.20版本,形成了本文的范例。下图是V1.10版本未删除的移植选项:
Fig_02_未删除.jpg
下图是V1.20版本已删除所有与中断有关的部分的移植选项:
Fig_03_无中断.jpg
(4)首先删除了所有的临界区保护方法,第52行和第53行定义临界区保护方法为空。根据uC/OS-II的设计,所有uC/OS-II的程序均不会对任何中断进行操作。
(5)其次删除原型中有关“PendSv”的全部程序,将中断里任务切换函数“OSIntCtxSw()”指定为空。根据uC/OS-II的设计,所有uC/OS-II的程序均不会依赖任何中断。

(6)最后在本文范例中删除前文范例中与定时器中断有关的全部程序,比如下面的初始化程序:
Fig_04_无ISR.jpg
以及定时器中断ISR。这样本文范例是在没有任何中断的情况下运行的单片机RTOS范例。
这证明V1.20版本的挑战者x51 uC/OS-II与中断无关,用户可以像裸机程序一样自由地使用任何硬件中断,对这些硬件中断事件V1.20版本的响应是“零延时”的。
三、uC/OS-II中断外任务切换使用方法
(7)本文范例的实时任务的优先级从高到低为任务A、任务B、任务C。范例的主任务是任务B,范例演示了将任务控制权切换到比自己优先级高或者低的任务的方法。

(8)下图是本文范例的主函数:
Fig_05_main.jpg
从中可以看到已经没有任何关于中断的程序了。

(9)下图是任务B中进行任务切换部分的程序:
Fig_06_TASKB.jpg
其中第167行是将任务切换到任务A去的语句。由于任务A的优先级2比任务B的优先级3高,因此,第167行语句一执行,首先就会将任务B挂起在该程序行处,然后就去将任务控制权切换到任务A去执行。
如果一个任务要将任务控制权切换到优先级比自己高的任务时,只需要用“OSTaskResume”语句唤醒高优先级任务即可。

(10)下图是任务A的程序:
Fig_07_TASKA.jpg
本文范例开始运行后,由于任务A优先级最高,它首先运行,然后在第98行处挂起自己,等待被唤醒。然后范例将控制权交给任务B去执行。
当任务A被任务B唤醒后,任务A的程序将从第98行的函数返回,顺序执行任务程序,直到再次在第98行处挂起自己,等待被唤醒。然后范例将控制权返回给任务B去恢复执行。
如果一个任务要将任务控制权返回到优先级比自己低的任务时,只需要用“OSTaskSuspend”语句挂起自己即可。
(11)前面任务B的第149行程序唤醒任务C(对于只有三个任务,这一行是多余的),使得任务C处于就绪状态。但由于任务B的优先级比高于任务C,任务C不会立即执行。当第150行程序挂起任务B时,任务的控制权才交给任务C去执行。
如果一个任务要将任务控制权切换到优先级比自己低的任务时,不但需要用“OSTaskResume”语句唤醒低优先级任务,而且还需要用“OSTaskSuspend”语句挂起自己。

(12)下图是本文范例运行效果的逻辑分析仪截屏:
Fig_08_运行效果.jpg
其中通道2是任务B信号,通道3是任务切换信号,通道4是任务A信号,通道5是任务C信号。
从中可以看出,无需借助任何中断,也不会干预任何中断,V1.20版本的挑战者x51 uC/OS-II移植版可以正常运行,实现单片机RTOS系统的按优先级进行任务切换功能。
附件:本文范例源程序
挑战者x51_03A_无中断RTOS.rar (443.99 KB, 下载次数: 25)


回复 送花

使用道具 举报

该用户从未签到

20

主题

547

回帖

1817

积分

荣誉版主

积分
1817
发表于 2023-10-6 12:13:11 | 显示全部楼层
今天送杨老师一个礼物 <STC32G - FreeRTOS 中断切换任务版本>

这个版本去年年底就做了, 因为没有实际项目要用到, 当时只是浅尝即止了.
这个版本和官网上发的版本主要改动是用中断切换任务.基本功能已经做好了, 但文档还有些乱, 需要整理一下. 做的时候只是为了看一下运行结果,很多地方也还需要优化.
官网上那个FreeRTOS的版本中有个缺陷是, 如果在中断里激活了一个高优先级任务, 不能即时任务切换, 需要等到时钟滴塔到了以后再统一进行切换.
现在这个版本没有这个缺陷, 但是可靠性还得进一步验证.

去年年底我发现官网上这个FreeRTOS版本的缺点后就发贴提出过, 但很遗憾, 到现在官网上的范例代码仍没有改变, 还是老样子.

我希望杨老师接收这个礼物, 并将其发杨光大, 本人认为这是一个重大的改进, 毕竟名字叫做RTOS, 官网的例子不能实时切换任务, 那还能叫实时OS吗

范例中, 打开了任务运行时间统计功能, 串口0 printf 输出结果, 运行截图如下:

运行结果

运行结果


此代码需要注意的是, 运行时间统计功能需要很大的任务栈, 故范示中使用了heap_4.c , 好像 FreeRTOS 原码有个用大内存的地方原码也改过, 具体记不清了, 用的时候注意一下就可以了


代码:
STC32G - FreeRTOS(中断切换任务).rar (23.35 MB, 下载次数: 35)




点评

非常感谢您的分享,ucos2移植版已在项目的stc32g8K64上运行  发表于 2023-10-6 17:50
玩家版最显著的一个特征就是“猴子掰包谷”,产品版最必要的一个特征就是终身维护。  详情 回复 发表于 2023-10-6 13:21
回复 支持 反对 送花

使用道具 举报

该用户从未签到

63

主题

660

回帖

1万

积分

荣誉版主

积分
10806
 楼主| 发表于 2023-10-6 13:21:25 | 显示全部楼层
tzz1983 发表于 2023-10-6 12:13
今天送杨老师一个礼物

这个版本去年年底就做了, 因为没有实际项目要用到, 当时只是浅尝即止了.

玩家版最显著的一个特征就是“猴子掰包谷”,产品版最必要的一个特征就是终身维护。

点评

谢谢你, 让我对人性的理解有更深的层次  发表于 2023-10-6 13:54
即便我没有义务维护,我也是代码贡献者,你呢?专业找茬?还找不到?  发表于 2023-10-6 13:32
你不要就算了,没必要损我一下吧, 我没有义务维护  发表于 2023-10-6 13:30
回复 支持 反对 送花

使用道具 举报

该用户从未签到

20

主题

547

回帖

1817

积分

荣誉版主

积分
1817
发表于 2023-10-7 13:31:41 | 显示全部楼层
本帖最后由 tzz1983 于 2023-10-7 13:37 编辑

谈点别的话题, 其实UCOSII中, 不管是代码切换任务还是中断切换任务, 模式1直接开关中断都是可用的,虽然我现在没有支持, 熊仔也没支持, 但确实是可以用的.
只要满足几个条件:
1. 除进出临界段时, 短暂的关掉中断外, 其它时候都要保持中断打开.
2.调用OS应用前, 须保证EA=1, 否则会出现调用结束后EA意外的被打开了.
3.所有代码中, 不能显式或隐式的出现临界段嵌套.
如果能满足这三个条件, 是可以用模式1的
有没有发现, 这三个条件, 其实我们都不用刻意去做, 实际上大多数情况下本来就自动满足条件了.
但最终我还是不建议用模式1, 因为它有条件, 而模式3没有这些限制. 有更好的方法当然要用更好的办法了.

"除进出临界段时, 短暂的关掉中断外, 其它时候都要保持中断打开" 这点对模式3仍然有效.

结论: 中断的应用对OS来说实在是太重要了, 可以想象一下, 没有中断的OS是什么样子, 太可怕了. 没有中断, OS将失去魂, 和单体大循环没什么区别.
像杨老师这个例子, 其实也包括熊仔那个例子(熊仔是在演关中断切换任务,算特殊也可以),
在没有中断了情况下, 在各个任务中跳来跳去, 阻塞也不行用, CPU独占, 这和没有OS有什么区别吗, 虽然能做到, 显示个简单波形, 跳来跳去等, 但没有什么意义.


熊仔和CosyOS  曾经讨论 Arm内核没有像JBC这样的指令, 只能分两步保存并关中断如下:
mrs r0, primask
cpsid i

这样为何不会出现问题?  其实不会出问题, 和我刚才说的模式1差不多的道理.
现在有亿分之1的机会, 刚好在读完primask时发生了中断, 但是, 有没有想过, primask的值不会变的, 即便是在别的地方有临界段代码,  因为配对使用的原因->它的值也不会变, 除非你故意在某个地方把总中断给关了, 不再打开, 否则就不会出错.
但是你非要把总中断给关了并且不再打开, 那出问题的就不尽尽是进临界区的这两条指令是否可靠的问题了, 整个OS都将瘫痪,没有灵魂!















回复 支持 反对 送花

使用道具 举报

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2024-5-8 14:39 , Processed in 0.062588 second(s), 45 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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