
本章节开始讲解ThreadX的另一个重要的任务间的同步和资源共享机制,信号量。
19.1 信号量
19.2 信号量任务通知(又称Event Chaining事件)
19.3 信号量创建函数
19.4 信号量发送函数
19.5 信号量接收函数
19.6 实验例程
19.7 总结
信号量(semaphores)是20世纪60年代中期Edgser Dijkstra发明的。使用信号量的最初目的是为了给共享资源建立一个标志,该标志表示该共享资源被占用情况。这样,当一个任务在访问共享资源之前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。
实际的应用中,信号量的作用又该如何体现呢?比如有个30人的电脑机房,我们就可以创建信号量的初始化值是30,表示30个可用资源,不理解的初学者表示信号量还有初始值?是的,信号量说白了就是共享资源的数量。另外我们要求一个同学使用一台电脑,这样每有一个同学使用一台电脑,那么信号量的数值就减一,直到30台电脑都被占用,此时信号量的数值就是0。如果此时还有几个同学没有电脑可以使用,那么这几个同学就得等待,直到有同学离开,有一个同学离开,那么信号量的数值就加1,有两个就加2,依次类推。刚才没有电脑用的同学此时就有电脑可以用了,有几个同学用,信号量就减几,直到再次没有电脑可以用,这么一个过程就是使用信号量来管理共享资源的过程。
平时使用信号量主要实现以下两个功能:
实际上信号量还有很多其它用法,而且极具挑战性,可以大大的开拓大家的视野,有兴趣的同学可以阅读一下《The Little Book Of Semaphores》,作者是Allen B. Downy。
http://www.armbbs.cn/forum.php?mod=viewthread&tid=15645
ThreadX提供的信号量是32bit计数信号量,计数范围0 到 4,294,967,295。通过函数tx_semaphore_create创建计数信号量,并可以计数信号量初始值。调用一次函数tx_semaphore_get,可以将计数值减1。调用一次函数tx_semaphore_put,可以将计数值加1。
任务间信号量的实现是指各个任务之间使用信号量实现任务的同步或者资源共享功能。下面我们通过如下的框图来说明一下TheadX信号量的实现,让大家有一个形象的认识。

运行条件:
运行过程描述如下:
上面就是一个简单ThreadX任务间信号量的使用过程。
ThreadX中断方式信号量的实现是指中断函数和ThreadX任务之间使用信号量。信号量的中断方式主要是用于实现任务同步,与上个章节讲解事件标志组中断方式是一样的。
下面我们通过如下的框图来说明一下ThreadX中断方式信号量的实现,让大家有一个形象的认识。

运行条件:
运行过程描述如下:
上面就是一个简单ThreadX中断方式信号量同步过程。实际应用中,中断方式的消息机制切记注意以下四个问题:
ThreadX 中的通知功能可用于将各种信号量“连接”在一起。当单个线程必须处理多个同步事件时,这通常很有用。
例如,应用程序可以为每个对象注册一个通知回调函数,而不是为队列消息、事件标志和信号量挂起单独的线程。当被调用时,应用程序通知例程然后可以恢复单个线程,该线程可以询问每个对象以便查找和处理新事件。
通常,事件链导致更少的线程、更少的开销和更小的 RAM 需求。它还提供了一种高度灵活的机制来处理更复杂系统的同步要求。
函数原型:
UINT tx_semaphore_create(
TX_SEMAPHORE *semaphore_ptr,
CHAR *name_ptr,
ULONG initial_count);函数描述:
此函数用于创建信号量。
1、 第1个参数是信号量控制块。
2、 第2个参数是信号量名字。
3、 第3个参数是信号量初始值,范围0x00000000 到 0xFFFFFFFF。
4、 返回值
TX_SUCCESS (0x00) 创建成功。
TX_SEMAPHORE_ERROR (0x0C) 信号量控制块无效。
TX_CALLER_ERROR (0x13) 无效的调用
注意事项:
使用举例:
TX_SEMAPHORE Semaphore;
/* 创建信号量,初始值为0,用于信号同步 */
tx_semaphore_create(&Semaphore, "Semaphore", 0);函数原型:
UINT tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr);
函数描述:
此函数用于信号量发送(信号量释放),反映到ThreadX内核操作上,对计数值执行加一操作。
1、 第1个参数是信号量控制块。
2、 返回值
TX_SUCCESS (0x00) 发送成功。
TX_SEMAPHORE_ERROR (0x0C) 信号量控制块无效。
注意事项:
使用举例:
TX_SEMAPHORE Semaphore;
/* 信号量释放 */
tx_semaphore_put(&Semaphore);函数原型:
UINT tx_semaphore_get(
TX_SEMAPHORE *semaphore_ptr,
ULONG wait_option);函数描述:
此函数用于信号量接收(获取),反映到ThreadX内核操作上,对计数值执行减一操作。
1、 第1个参数是信号量控制块。
2、 第2个参数是等待选项:
如果信号量计数值为零,这个形参将派上用场:
3、 返回值
注意事项:
使用举例:
TX_SEMAPHORE Semaphore;
/*
*********************************************************************************************************
* 函 数 名: AppTaskMsgPro
* 功能说明: 消息处理,这里用作信号量获取。
* 形 参: thread_input 是在创建该任务时传递的形参
* 返 回 值: 无
优 先 级: 3
*********************************************************************************************************
*/
static void AppTaskMsgPro(ULONG thread_input)
{
UINT status;
while(1)
{
status = tx_semaphore_get(&Semaphore, TX_WAIT_FOREVER);
if(status == TX_SUCCESS)
{
/* 接收到信号量 */
printf("接收到同步信号量\r\n");
}
}
}配套例子:
V6-3014_ThreadX Semaphore
实验目的:
实验内容:
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况
========================================================
CPU利用率 = 0.89%
任务执行时间 = 0.586484645s
空闲执行时间 = 85.504470575s
中断执行时间 = 0.173225395s
系统总执行时间 = 86.264180615s
=======================================================
任务优先级 任务栈大小 当前使用栈 最大栈使用 任务名
Prio StackSize CurStack MaxStack Taskname
2 4092 303 459 App Task Start
5 4092 167 167 App Msp Pro
4 4092 167 167 App Task UserIF
5 4092 167 167 App Task COM
0 1020 191 191 System Timer Thread
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。
App Task Start任务 :启动任务,这里用作BSP驱动包处理。
App Task MspPro任务 :消息处理,这里用作信号量获取。
App Task UserIF任务 :按键消息处理。
App Task COM任务 :这里用作LED闪烁。
System Timer Thread任务:系统定时器任务
2、K2键按下,发送信号量同步信号。
3、任务App Task MspPro接收到消息后,串口打印。
4、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
(2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
5、默认上电是通过串口打印信息,如果使用RTT打印信息
(1) MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
#define Enable_RTTViewer 1
(2) Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
串口打印信息方式(AC5,AC6和IAR):
波特率 115200,数据位 8,奇偶校验位无,停止位 1

RTT打印信息方式(AC5,AC6和IAR):

Embedded Studio仅支持调试状态RTT打印:

由于Embedded Studio不支持中文,所以中文部分显示乱码,不用管。
程序执行框图:

本章节主要为大家讲解了另一个重要的任务间的同步和资源共享机制信号量,建议初学者务必将其掌握,因为实际项目中用到信号量的地方很多。