STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)

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

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第1张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第2张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第3张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第4张图片

这个信号量就类似于锁,给代码,或共享资源,比如输入输出寄存器等加锁,保证同一个时间

只能有一个函数去操作对应的值,然后现在基本用来做任务同步

是什么意思呢?

比如数据的接收就需要同步,因为不同步有可能数据就会乱

比如这里,通过中断进行数据接收,放到ISR寄存器,然后有个任务task1,去发送数据,那么

这里的这个中断和这个task1就需要同步,才能保证数据接收正确.

然后再比如:

key按键是一个任务,然后led亮是一个任务,

那么key按键和led亮需要保持同步也就是,按下key,led就要亮,要保证这个顺序.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第5张图片

这里再说一下这个信号量,

这个信号量可以理解为就是一个变量,

比如这里有3个任务,A,C,D,那么

如果有个变量作为信号量,比如变量b,只有当变量b是大于0的时候,其他的A,C,D任务才能

进行使用资源,当b减少到0的时候,那么CD就只能等待,当再变量b再恢复到

0以上的时候,CD就又可以使用这个资源.

 

那么pend是等待信号量可用,或者是请求信号量,post是发送信号量,或者叫释放信号量.

比如这个时候有个信号量是5,那么如果一直pend,一直请求的话,如果这个信号量减少到0,那么

C,D就没办法使用了.就会停止运行.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第6张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第7张图片

去看看代码

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第8张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第9张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第10张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第11张图片

看看这个信号量的种类,一种是二进制的,也就是只能一个任务使用的资源,比如

打印机,还有是计数形的,某个资源可同时被几个任务使用,比如缓存池,有10个缓存块,

那么同时最多可支持10个任务来使用内存池,就可以计数到10,把这个信号量设置为10就可以了.,

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第12张图片

去看看代码:

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第13张图片

首先

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第14张图片

这OSSemCreate这个是,创建一个信号量.

要创建一个信号量,首先要定义一个信号量.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第15张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第16张图片

然后看一下,这里OS_SEM是信号量,

CPU_CHAR P_PNAME这是信号量的名字

cnt是信号量,可以计数,这个计数的初始值

p_err这个是信号量的错误代码

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第17张图片

去看看这个信号量.

 STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第18张图片

这里,主要看这个

OS_SEM_CTR Ctr这个值,这个就是,信号量的值,大于0的时候资源可以用,为0就要等待.

这个值可以读取,一会去看看

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第19张图片

这个OSSemDel是删除信号量,

第一个p_sem是信号量,第二个是选项opt,第三个是错误码

选项都是有什么呢

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第20张图片

可以看到这里:

OS_OPT_DEL_NO_PEND这个意思是,如果有很多任务还在使用这个信号量,就等待任务使用信号量结束以后

再去删除这个信号量

然后

OS_OPT_DEL_ALWAYS这个意思是不管还有没有其他任务在使用这个信号量,直接删除.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第21张图片

再看看这个

OSSemPend这个()函数是等待信号量函数.

第一个参数是要等待的信号量,

第二个参数是timeout,超时

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第22张图片

可以看到这里是时钟tick,时间片,如果5ms是一个时钟周期,那么设置为2,就是10ms

如果这里设置了,比如2,就等待10ms,就超时了,超时以后就可以去执行其他任务去了.

如果这里timeout设置成了0,那么意思就是,一直去请求信号量,也就是一直去等待信号量了.

 

一直等待,就会造成任务不继续执行了,所以这里timeout这个要注意.

第三个参数是opt

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第23张图片

OS_OPT_PEND_BLOCKING这个的意思就是,如果请求信号量,

这里请求不到,就会程序阻塞在这里.

OS_OPT_PEND_NON_BLOCKING这个是,如果请求不到信号量就直接返回了不等了.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第24张图片

这里在看看p_ts

这个是个时间戳,就是返回一个请求到信号量的时刻.

最后一个参数是请求的错误码

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第25张图片

这个OSSemPendAbort这个是,取消等待

第一个参数是操作的哪个信号量

第二个参数是,选项.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第26张图片

这个OS_OPT_PEND_ABORT_L这个是仅仅,取消优先级最高的任务的等待.

OS_OPT_PEND_ABORT_ALL这个是,取消所有的等待任务

OS_OPT_POST_NO_SCHED这个是,禁止在本函数内进行任务调度操作.

第3个参数就是错误码

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第27张图片

OSSemPost()这个是发送信号量的函数,

这个第一个参数是发送哪个信号量.

第二个是OS_OPT是一个选项去看看

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第28张图片

这里OS_OPT_POST_1这个是,像正在等待信号量的所有任务中,优先级最高是任务去发送信号量

OS_OPT_POST_ALL这个是,向所有的任务去发送信号量.

OS_OPT_POST_NO_SCHED这个是禁止本函数内进行任务调度.

接下来

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第29张图片

看个案例,如果咱们不使用信号量,而直接去操作访问共享资源会怎么样

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第30张图片

首先创建两个任务

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第31张图片

然后定义一个数组作为共享资源区.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第32张图片

去看看任务1,这里咱们会向共享资源区也就是上面

声明的share_resource去copy内容到这个共享资源区,

然后再延时200ms,这个延时的时候要注意,延时的过程中是会发生任务调度的.

printf()

一直到这个时候,其实这个task1都是在占用着这个share_resource这个共享资源的.

再去看看task2

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第33张图片

可以看到task2也是这样做的,

那么按照咱们看的结果应该是,

task1打印一个字符串,然后

task2打印一个字符串,然后

task1打印一个字符串....是这样.

 

但是,由于现在我们没有对共享资源区做代码保护,他是什么效果呢,咱们看看

下载到开发版

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第34张图片

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第35张图片

可以看到打印出来的效果全部是任务2的,任务1都没有抢占到资源.

这个打印是乱套的,

这个就是没有用信号量保护的现象.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第36张图片

然后咱们再看看,使用信号量来访问,共享资源区.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第37张图片

也是两个任务,跟上面是一样的,然后

声明

共享资源区

share_resource[30]

然后这里要用信号量,先声明一个信号量OS_SEM MY_SEM

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第38张图片

在开始任务重首先去创建信号量,这里定义的信号量是1,也就是,只能用一次,同时,这个信号量

OS_SEM_CTR 是1

然后task1中

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第39张图片

使用的时候可以看去请求

OSSemPend,等待信号量,请求信号量,这里超时时间是0,也就是一直等待,

然后,OS_OPT_PEND_BLOCKING这个是等待不到信号量,系统就在这不继续执行,

然后0,这个是需要返回时间戳,也就是请求到信号量的时间点.

使用完信号量以后,再释放信号量,发送信号量.

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第40张图片

可以看到任务2也是这样,使用信号量来保护共享资源区

下载到开发版,再去看看

STM32工作笔记0085---UCOSIII信号量和互斥信号量(上)_第41张图片

可以看到这样就得到自己想要的结果了,

当然你也可以通过禁止任务调度,或者关闭中断的方式实现也行.

一般建议不要关闭中断的方式,采用信号量,或者是,上锁,任务调度器加锁的机制都可以

中断的方式会影响系统的稳定性会关闭滴答定时器等,串口的通信等可能会有影响.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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