ARM官方《CMSIS-RTOS教程》之线程Threads
创建线程Creating Threads
一旦RTOS开始运行,就会有很多系统调用来管理和控制活跃的线程。默认情况下,main()函数自动被创建为第一个可运行的线程。在第一个例子里我们使用main()函数创建了其他线程,并且随后让main()结束运行。然而我们还可以让main当成一个真正的thread使用。首先,我们需要获取它的ID号。此时,我们第一个要调用的RTOS函数就是osThreadGetId(),这个函数返回当前运行thread的ID号,并把它存在ID句柄里。当我们未来某一时刻在OS调用中需要这个线程时,我们使用的就是这个线程的句柄,而非线程的函数名。
- osThreadId main_id;//创建线程句柄
- void main(void)
- {
- /*获取main线程的ID号*/
- main_id = osThreadGetId();
- while(1)
- {}
- }
现在我们有了main的ID句柄,就可以创建其他应用线程,并随后调用osTermainate(main_id)来结束main线程。相比让一个线程运行到最后一个花括号来结束,这种结束方法更好一些。当然,我们还可以添加while(1)这个循环来继续使用main函数。
在第一个例子中我们就看到main线程可以作为一个launcher 线程来创建其他应用线程。仅需要两步就行:第一步,定义线程结构体(同时还可以定义线程传递参数)。
- osThreadId thread_id; //线程句柄
- void thread1(void const *argument); //thread1的函数原型
- osThreadDef(thread1, osPriorityNormal, 1, 0); //线程定义结构体
定义线程结构体需要先定义线程函数名、线程优先级、创建线程的实例化个数和它的栈大小。这些参数后续会详细说明。一旦定义了线程结构体,我们就可以用osThreadCreated() API来创建线程。线程经常在main线程里创建,当然也可以在其他地方。
thread1_id = osThreadCreated(osThread(thread1), NULL);
上面这条代码创建线程并启动它运行。另外,在启动线程时可以给它传递个参数。
- uint32_t startupParameter = 0x23;
- thread1_id = osThreadCreate(osThread(thread1), startupParameter);
当创建线程时,还将给它分配一个栈,用来存储上下文切换的数据。注意不要和Cortex处理器栈混淆,它只是分配给线程的一段存储空间。在RTOS配置文件里已经定义了一个默认的栈大小,当然我们也可以自定义栈的大小。osThreadDef()这个函数的最后一个参数设为0时表示使用默认栈大小。如果需要的话,也可以通过在线程结构体里定义一个更大的栈来增加额外的存储资源。
- osThreadDef(thread1, osPriorityNomal, 1, 0); //分配默认栈大小
- osThreadDef(thread2, osPriorityNomal, 1, 1024); //分配1kB的栈大小
当然,如果你分配了更大的栈空间,在RTOS配置文件里就需要增加额外的存储空间。
线程的管理和优先级Thread Management and Priority
在创建线程的时候就会给它分配一个优先级。RTOS的调度器靠线程的优先级来决定要调度哪个线程运行。假如同时有几个线程都准备运行,优先级最高的线程就会进入运行状态。如果一个高优先级线程处于准备运行状态,它就会抢占正在运行的低优先级线程。有一点非常重要,高优先级线程占用CPU运行的时候永远不会停止,除非有RTOS API调用来阻塞它,或者有更高优先级的线程来抢占它。线程的优先级在线程结构体中定义,下面列出可用的优先级定义,其中一般默认的优先级是osPriorityNormal。
| CMSIS-RTOS Priority Levels |
|---|
| osPriorityIdle |
| osPriorityLow |
| osPriorityBelowNormal |
| osPriorityNormal |
| osPriorityAboveNormal |
| osPriorityHigh |
| osPriorityRealTime |
| osPriorityError |
一旦线程开始运行,我们就可以使用几个OS系统调用来管理线程。当然也可以通过其他函数或在它自己代码里面提升或者降低它的优先级。
osStatus osThreadSetPriority(threadID, priority);
osPriority osThreadGetPriority(threadID);
在创建线程之后,也可以通过它自己或者其他活跃的线程来删除它。再强调一次,我们使用thread ID而不是它的函数名来操作。
osStatus = osThreadTermainate(threadID1);
另外,同优先级线程间的切换有一种特殊情况,就是使用协作(co-operative)切换方式:
osStatus osThreadYield();//切换到另外一个准备运行的线程
多重实例化Multiple Instances
RTOS的一个有趣功能就是可以针对一个线程进行多个实例化,例如你可以基于一个线程代码创建多个用于控制UART的实例,此时,每个UART的实例都会管理一个不同的UART硬件。
首先我们要创建线程结构体,并设置线程实例个数为2:
osThreadDef(thread1, osPriorityNormal, 2, 0);
空闲线程Idle Demon
CMSIS-RTOS提供的最后一个定时器服务函数并不是一个真正的定时器,但是这里是最合适讨论它的地方。如果在我们的RTOS程序里没有任何线程正在运行,或者准备运行(举个例子,所有的线程都处于等待延时函数中),那么RTOS就会利用空闲的运行时间调用一个“Idle Demon”的线程,这个函数同样位于RTX_Conf_CM.c文件里面,空闲线程拥有一个低优先级,只有在没有其他任何线程准备运行的情况下才会运行。
void os_idle_demon(void)
{
for(;;){
/*此处包含一些用户的的可选代码,在没有线程运行时执行*/
}
}
你可以在这个线程里加入任何代码,但是同样要遵守常规线程的基本准则,一个最简单的应用就是在此线程中添加控制器MCU的低功耗模式。
void os_idle_demon(void)
{
__wfe();
}
下一步什么情况取决于MCU的功耗模式选择,至少CPU会暂停,直到sysTick产生中断并继续执行调度器。如果有线程准备运行,CPU就会去执行这个线程,否则,就会重新进入空闲线程,系统也会重新进入睡眠状态。
线程间通信 Inter-Thread Communication
前面我们已经学习了如何把你的应用代码设计成独立的线程,以及如何访问RTOS的时间服务函数。在实际的工程应用中,线程间的通信是必不可少的,任何一个RTOS都会支持几种通信方式来连接各种不同的线程。CMSIS-RTOS API支持的通信方式有:信号(signals),信号量(semaphores),互斥锁(mutexes),邮箱(mailboxes)和消息队列(message queues)。所有这些首要的核心概念就是并发性。在这一章,将集中讨论多任务间的同步问题。
信号 Signals
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);
来源:https://blog.csdn.net/ichamber/article/details/53116253
ARM官方《CMSIS-RTOS教程》之线程Threads的更多相关文章
- 【转帖】ECLIPSE-JEE-LUNA-SR2官方汉化教程
ECLIPSE-JEE-LUNA-SR2官方汉化教程 工具/原料 Eclipse-jee-luna-SR2 步骤/方法 1.在浏览器输入网址http://www.eclipse.org/babel/d ...
- ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表
本篇文章将介绍区域报表和页面报表的常见使用场景.区别和选择报表类型的一些建议,两种报表的模板设计.数据源(设计时和运行时)设置.和浏览报表的区别. ActiveReports 报表控件官方中文入门教程 ...
- ActiveReports 报表控件官方中文入门教程 (1)-安装、激活以及产品资源
本系列文章主要是面向初次接触 ActiveReports 产品的用户,可以帮助您在三天之内轻松的掌握ActiveReports控件的基本使用方法,包括安装.激活.创建报表.绑定数据源以及发布等内容.本 ...
- ActiveReports 报表控件官方中文入门教程 (2)-创建、数据源、浏览以及发布
本篇文章将阐述首次使用 ActiveReports 报表控件 的方法,包括添加报表文件.绑定数据源以及如何发布报表等内容. ActiveReports 报表控件官方中文入门教程 (1)-安装.激活以及 ...
- ARM开发软件ADS教程
ARM开发软件ADS教程 ADS(ARM Developer Suite)是ARM公司推出ARM集成开发环境,操作简单方便,获得广大开发人员的青睐.下面使用ADS v1.2做一个实例教程,帮助大家学会 ...
- Spring Boot 与 OAuth2 官方最详细教程
https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247484357&idx=1&sn=73e501de8591e6 ...
- ActiveReports 报表控件官方中文新手教程 (1)-安装、激活以及产品资源
本系列文章主要是面向初次接触 ActiveReports 产品的用户,能够帮助您在三天之内轻松的掌握ActiveReports控件的基本用法,包含安装.激活.创建报表.绑定数据源以及公布等内容. ...
- 微信小程序导航:官方工具+精品教程+DEMO集合(1月7更新)
1:官方工具:https://mp.weixin.qq.com/debug/w ... tml?t=14764346784612:简易教程:https://mp.weixin.qq.com/debug ...
- CMSIS RTOS -- embOS segger
#ifndef __CMSIS_OS_H__ #define __CMSIS_OS_H__ #include <stdint.h> #include <stddef.h> #i ...
随机推荐
- 如何解决bib的一些问题
胡老师留的大作业要求综述,因而有很多文献引用.但是当使用bibtex的方法,特别是中文文献的引用会遇到一些问题. 网上相关的解答有: http://blog.sciencenet.cn/blog-10 ...
- hiho 171周 - 水题,并查集
题目链接 题目描述: 输入4 alice 2 alice@hihocoder.com alice@gmail.com bob 1 bob@qq.com alicebest 2 alice@gmail. ...
- HDU 1166 敌兵布阵【线段树 单点更新】
题意:给出n个数,a1,a2,a3,,,,,an,再给出一些操作 add i j 表示给第i个节点增加j sub i j 表示给第i个节点减少j query i j 表示询问第i个节点到第j个节点 ...
- 预测一下web前端未来的6个趋势
2018年前端技术的发展也将进入到一个相对稳定的阶段, 就前端主流技术框架的发展而言,过去的几年里发展极快,在填补原有技术框架空白和不足的同时也渐渐趋于成熟. 未来前端在已经趋向成熟的技术方向上面将会 ...
- 运维派 企业面试题6 防dos攻击
Linux运维必会的实战编程笔试题(19题) 企业实战题6:请用至少两种方法实现! 写一个脚本解决DOS攻击生产案例 提示:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到 ...
- python一些被我忽略的知识
最后一个不小心打错了,刚看到,try ...else 与 while/for else的相同
- nessus 漏洞扫描安装和使用
介绍 Nessus 是目前全世界最多人使用的系统漏洞扫描与分析软件.总共有超过75,000个机构使用Nessus 作为扫描该机构电脑系统的软件. 软件特色 * 提供完整的电脑漏洞扫描服务, 并随时更 ...
- (51) magento集成增加到款通知
这篇主要讲述如何二开增加自己的功能,我没有继承方式二开,习惯是不好的,直接改了原来的模块. 达到效果就这样,当在网站支付成功,会同步到ERP系统中.下面来讲述实现过程 建立文件 payment_not ...
- 6款 jQuery Lightbox图片查看触控插件
偶然间在网上看到的几个图片预览的插件,挺好用的,顺手整理下来. 1:Zoomify – jQuery缩放效果lightbox插件 地址:http://www.dowebok.com/214.html ...
- linux进程管理之概念(一)
一.进程和线程的概念 1.进程和线程的定义 进程并不只是一段可以运行的代码,也包含了运行代码所需要的资源. 在操作系统来看,进程是资源管理的最小单元,而我们又知道,线程是程序执行的最小单元. 话说回来 ...