赞
踩
前面我们已经学习了如何把你的应用代码设计成独立的线程,以及如何访问RTOS的时间服务函数。在实际的工程应用中,线程间的通信是必不可少的,任何一个RTOS都会支持几种通信方式来连接各种不同的线程。CMSIS-RTOS API支持的通信方式有:信号(signals),信号量(semaphores),互斥锁(mutexes),邮箱(mailboxes)和消息队列(message queues)。所有这些首要的核心概念就是并发性。在这一章,将集中讨论多任务间的同步问题。
CMSIS RTOS RTX支持单线程16种信号标志,这些信号存储在线程控制块里,一个线程会暂停执行,直到一个或一组信号标志被其他线程置位。
每个线程有16个信号标志,一个线程可能被置于等待状态,直到一种模式的信号被其他线程置位。然后此线程就会返回等待状态,并等待调度器调度到运行状态。
调用信号等待后,系统会挂起正在运行的线程,并把它置于等待事件(wait_event)状态,直到所有的信号标志被置位,线程才会恢复运行。当然也可以加入超时机制,以便让线程可以顺利返回等待状态。默认初始化超时值是0xFFFF。
osEvent osSignalWait(int32_t signals, uint32_t millisec);
调用osSignalWait之后会把信号复位,如果后面还有信号被置位,线程就可以继续执行,你可以读osEvent.value.signals的值来获取哪个标志被置位。
任何一个线程都可以置位或清除另外一个线程的信号:
int32_t osSinalSet(osThreadId thread_id, int32_t signals);
int32_t osSignalClear(osThreadId thread_id, int32_t signals);
在这个练习里,我们将学会如何在两个线程之间使用信号触发线程执行。
打开Pack Installer,并选择”Ex 8 Signals,然后install到你的自定义路径。
从代码中可以看到,两个线程都是执行的LED闪烁程序,其中一个通过调用osDelay()暂停执行,同时置位一个信号来唤醒另外一个LED线程:
void led_Thread2(void const *argument){
f(;;){
LED_On(2);
osSignalSet(T_led_ID1, 0x01);
osDelay(500);
LED_Off(2);
osSignalSet(T_led_ID1, 0x01);
osDelay(500);
}
}
第二个线程等待信号被置位,然后才会执行LED闪烁程序:
void led_Thread1(void const *argument){
for(;;){
osSignalWait(0x01, osWaitFover);//无超时机制
LED_On(1);
osSignalWait(0x01, osWaitFover);
LED_Off(1);
}
}
编译工程,请启动debugger环境。
打开GPIOB窗口,并全速运行代码。
从窗口中可以看到两个管脚亮灭是同步的,给人的错觉就是两个LED线程是并行运行的。
这个例子虽然简单,却揭示了线程间同步的核心概念,而这又是RTOS最基本的应用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。