STM32工作笔记0083---UCOSIII中断和时间管理

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

STM32工作笔记0083---UCOSIII中断和时间管理_第1张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第2张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第3张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第4张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第5张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第6张图片

去看看代码:

STM32工作笔记0083---UCOSIII中断和时间管理_第7张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第8张图片

这个就是串口的中断服务函数.

然后

STM32工作笔记0083---UCOSIII中断和时间管理_第9张图片

可以看到这里有个判断

#if SYSTEM_SUPPORT_OS

  OSIntEnter()

#endif

如果使用了UCOS操作系统,这里就

调用  OSIntEnter() 这函数开始.

 

STM32工作笔记0083---UCOSIII中断和时间管理_第10张图片

然后调用了OSIntEnter,以后,中间部分就写,操作系统的中断服务函数,

然后,写完以后

最后再调用

OsIntExit()这个函数,

所以,可以看到这个跟咱们自己写操作系统的,中断服务函数基本没有区别

只是添加了OsIntEnter和OsIntExit这两个函数,把中断服务内容,放到了

这两个函数中间了.

STM32工作笔记0083---UCOSIII中断和时间管理_第11张图片

可以去看看

STM32工作笔记0083---UCOSIII中断和时间管理_第12张图片

os没有运行就退出,如果os运行,进入下一步

这里这个OSIntNestingCtr这个是嵌套的深度,最多是250级.

STM32工作笔记0083---UCOSIII中断和时间管理_第13张图片

这里这个,这个8u的最大值是255

STM32工作笔记0083---UCOSIII中断和时间管理_第14张图片

OSIntNestingCtr>250的时候,说明中断嵌套,超过了UCOSIII系统所允许的中断嵌套数.

就返回.最后OSIntNestingCtr++ ,这个+1就表示发生了一次中断.

注意,这里因为,中断服务函数:

OSIntEnter开始的时候,OSIntNestingCtr这个会++

然后执行完了OSIntExit 中,这个OSIntNestingCtr又会--,所以

只要是不要有超过250个,中断函数,同时运行,那么这个OSIntNestingCtr,就不会超过

250,也就是说中断在UCOSIII中,要求不能太多了,超过250个就不行了

但是STM32咱们知道一共中断是100多个..

不会超过这个数.

STM32工作笔记0083---UCOSIII中断和时间管理_第15张图片

然后再去看看OSIntExit这个函数

STM32工作笔记0083---UCOSIII中断和时间管理_第16张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第17张图片

这个函数比较长了

STM32工作笔记0083---UCOSIII中断和时间管理_第18张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第19张图片

看看这个CPU_INT_DIS这个变量是,关闭全局中断

STM32工作笔记0083---UCOSIII中断和时间管理_第20张图片

然后可以看到下面如果OSIntNestingCtr这个变量=0,也就是说当前,没有发生中断的时候

这个时候,这个OSIntExit这个函数就不能执行这里就return了.

STM32工作笔记0083---UCOSIII中断和时间管理_第21张图片

然后再OSIntNestingCtr去减1,

减去1 以后这里再判断,如果减去以后,这OSIntNestingCtr还是大于0的说明,还有其他的中断服务函数,

所以这个时候,这个OSIntExit,还有一个功能就是如果这个中断服务函数执行完了以后,同时

还有其他中断服务函数在执行的话,那么就要去执行其他的中断服务函数.

 

当这个不大于0的时候,就说明所有的中断服务函数,都已经执行完了,就可以退出了.

STM32工作笔记0083---UCOSIII中断和时间管理_第22张图片

然后判断任务有没有加锁,有加锁的话,也就是不能不执行其他任务,

所以这里就需要返回了.

STM32工作笔记0083---UCOSIII中断和时间管理_第23张图片

接下来,再去获取到当前,已经就绪的,最高优先级的任务

找到接下来的这个优先级最高的就绪任务以后,接下来就要做

任务切换

STM32工作笔记0083---UCOSIII中断和时间管理_第24张图片

然后OSTaskCtxSwCtr++ 这个变量来完成

任务切换次数的记录.

STM32工作笔记0083---UCOSIII中断和时间管理_第25张图片

这个是中断级任务调度器.

STM32工作笔记0083---UCOSIII中断和时间管理_第26张图片

所以这里咱们知道OSIntExit这函数,退出中断的是,去调用了

中断级的任务切换函数,来切换下一个,最高优先级就绪任务.

STM32工作笔记0083---UCOSIII中断和时间管理_第27张图片

再来看一下这个临界段代码保护,比如,有些设备的初始化等,就不能被打断,那么这个时候

就需要进行,临界段代码保护,临界段代码保护有两个方法,一是,设置OS_CFG_ISR_POST_DEFERRED_EN是0,

这个时候用关闭中断的方式来保护代码,也就是系统不执行中断了,只走这段代码,走完以后再做其他的,这个方法

有个坏处就是,关闭中断以后,系统的滴答定时器会停止运行,像串口收数据也会收到影响.

第二个是:OS_CFG_ISR_POST_DEFERRED_EN是1,这样的话,可以通过

给调度器加锁的方式来保护临界段代码,这样的话,会好很多.

STM32工作笔记0083---UCOSIII中断和时间管理_第28张图片

去看看代码:

STM32工作笔记0083---UCOSIII中断和时间管理_第29张图片

可以看到这里,下面是创建任务的过程,这里创建任务的过程是不应该被打断的,

所以这里,可以看到添加

OS_CRITICAL_ENTER这个函数了.

STM32工作笔记0083---UCOSIII中断和时间管理_第30张图片

然后任务创建完以后,又退出了临界区

OS_CRITICAL_EXIT();

其实这里

OSTaskCreate(...)

这个函数的内部,其实也自己去调用了,临界区保护

STM32工作笔记0083---UCOSIII中断和时间管理_第31张图片

进去这个函数去看看

STM32工作笔记0083---UCOSIII中断和时间管理_第32张图片

可以看到,在关键的地方,总有

OS_CRITICAL_ENTER()

这种地方,用来进行临界区保护.

 

但是习惯,咱们在做任务创建的前后都加个任务保护

STM32工作笔记0083---UCOSIII中断和时间管理_第33张图片

这里还要注意一点,就是

当我们想要使用临界段保护代码的时候,一定要

CPU_SR_ALLOC()使用这个函数,先调用一下这个.

去看看这个

STM32工作笔记0083---UCOSIII中断和时间管理_第34张图片

可以看到这个也是一个宏,

他指向了一个CPU_SR这个变量.

STM32工作笔记0083---UCOSIII中断和时间管理_第35张图片

假如这里我们把这变量注释掉,那么一编译就报错了

报错说:缺少cpu_sr这个变量

STM32工作笔记0083---UCOSIII中断和时间管理_第36张图片

所以,当使用临界区保护代码的时候,一定要调用

CPU_SR_ALLOC()这个函数.

然后再看看

STM32工作笔记0083---UCOSIII中断和时间管理_第37张图片

这个函数.

STM32工作笔记0083---UCOSIII中断和时间管理_第38张图片

可以看到这部分都是条件编译.

STM32工作笔记0083---UCOSIII中断和时间管理_第39张图片

这类可以看到

这里

OS_CFG_ISR_POST_DEFERRED_EN>0的时候

也就是,前面咱们说的,OS_CFG_ISR_POST_DEFERRED_EN是1的时候,是采用加锁的方法来

进行,保护临界区代码的.

STM32工作笔记0083---UCOSIII中断和时间管理_第40张图片.

去看看这个代码

OS_CFG_ISR_POST_DEFERRED_EN是1,也就是系统默认的是通过加锁的方式来保护临界区代码

然后再继续看上面的条件宏定义部分:

STM32工作笔记0083---UCOSIII中断和时间管理_第41张图片

先看这个

OS_CRITICAL_ENTER() 这个是进入临界区代码的时候,要调用这个宏定义

STM32工作笔记0083---UCOSIII中断和时间管理_第42张图片

OS_CRITICAL_EXIT()这个是退出临界区保护代码的时候,要调用的这个宏定义

STM32工作笔记0083---UCOSIII中断和时间管理_第43张图片

这个是OS_CRITICAL_EXIT_NO_SCHED()这个是另一个退出,临界区代码的方式

STM32工作笔记0083---UCOSIII中断和时间管理_第44张图片

先去看这个

OS_CRITICAL_ENTER

可以看到先去调用了一下这个宏定义,然后

下面

OSSchedLockNestingCtr++ 这个是说,给任务调度器加锁,这样的话,

就不会产生任务调度了

然后:

STM32工作笔记0083---UCOSIII中断和时间管理_第45张图片

这里退出的时候

OSSchedLockNestingCtr--任务调度器又去--了

把锁释放掉.

STM32工作笔记0083---UCOSIII中断和时间管理_第46张图片

然后可以看到,释放任务调度器以后,释放锁以后,如果还有其他任务的话,

还进行了,这里的任务切换.

STM32工作笔记0083---UCOSIII中断和时间管理_第47张图片

这里如果调用的是这个的话,可以看到结束临界区代码保护的时候,就没有任务切换

OS_CRITICAL_EXIT_NO_SCHED()

然后这里退出临界代码区,一般用:OS_CRITICAL_ENTER();这个

STM32工作笔记0083---UCOSIII中断和时间管理_第48张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第49张图片

然后再去看看,这里

OS_CFG_ISR_POST_DEFERRED_EN这个宏定义如果是0的时候,那么,

也就是说使用关闭中断的方式来实现,临界区代码的保护

这里咱们可以根据需要把这个OS_CFG_ISR_POST_DEFERRED_EN改成0

一般都是不需要改的

STM32工作笔记0083---UCOSIII中断和时间管理_第50张图片

可以看到OS_CFG_ISR_POST_DEFERRED_EN=0的时候走的宏定义的else

STM32工作笔记0083---UCOSIII中断和时间管理_第51张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第52张图片

可以看到这里面:
这个是通过这个CPU_SR_Save(),保存现场,也就关闭所有中断,来实现的.

STM32工作笔记0083---UCOSIII中断和时间管理_第53张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第54张图片

当然也可以看到,这种关闭中断的方式,保护临界区代码,恢复的时候,

也是通过CPU_SR_Restore()这种方式,也就是使能所有的中断,恢复所有的中断来实现的.

STM32工作笔记0083---UCOSIII中断和时间管理_第55张图片

这个就是说的临界区代码保护

然后:

STM32工作笔记0083---UCOSIII中断和时间管理_第56张图片

 

STM32工作笔记0083---UCOSIII中断和时间管理_第57张图片

注意这里的延时函数,是能触发系统任务切换就可以,不一定就是

延时函数.

STM32工作笔记0083---UCOSIII中断和时间管理_第58张图片

去看看这两个函数具体怎么用

STM32工作笔记0083---UCOSIII中断和时间管理_第59张图片

先看看这个OSTimeDly这个函数

STM32工作笔记0083---UCOSIII中断和时间管理_第60张图片

这里,可以看到,这个延时不是,延时多少秒,之类的,这个是延时的时间片数,比如

一个时间片是5ms,你延时2个就是10ms

STM32工作笔记0083---UCOSIII中断和时间管理_第61张图片

可以看看他的参数,第一个OS_TICK是,要延时的时间片数,

第二个:OS_OPT是要选择的模式,比如有前面说的相对模式,

周期模式,绝对模式等.

然后后面是错误代码

去看看这个

OS_OPT这个模式的文档:

STM32工作笔记0083---UCOSIII中断和时间管理_第62张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第63张图片

因为下面这个

STM32工作笔记0083---UCOSIII中断和时间管理_第64张图片

这个OSTimeDlyHMSM()只有相对模式,所以上面OSTimeDly()用的时候

一般也是定为相对模式.

STM32工作笔记0083---UCOSIII中断和时间管理_第65张图片

这个OSTimeDlyHMSM()函数的几个参数可以看看

有,小时,分钟,秒,毫秒,选项,还有错误码

然后再看一下时间的什么的范围:

STM32工作笔记0083---UCOSIII中断和时间管理_第66张图片

STM32工作笔记0083---UCOSIII中断和时间管理_第67张图片

然后这里的

OSTimeDlyResume()取消延时而进入就绪状态

然后

OSTimeGet还是可以用的,可以用来获取任务的运行时间,因为OSInit的时候,会把OSTickCtr设置为0

,每运行一个时钟节拍那么就会+1.,所以这里用OSTickCtr * 每个节拍的毫秒就是,这个任务执行所需要的的时间

STM32工作笔记0083---UCOSIII中断和时间管理_第68张图片

 

比如任务开始的时候,记录一下时钟节拍数是A,任务结束的时候记录一下时钟节拍数是B

那么B-A 然后 *5(一个时钟节拍是5ms) 就是,这个任务所花费的时间.

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(硬件嵌入式)