admin 管理员组

文章数量: 1086019


2024年3月13日发(作者:switch case例题)

第39卷 第10期

2021年 10月

中图分类号:TP311.1

数字技术与应用

Digital Technology &Application

文献标识码:A

Vol.39 No.10

October 2021

2021年第 10 期

文章编号:1007-9416(2021)10-0023-04

DOI:10.19695/12-1369.2021.10.08

基于RT-Thread的多线程任务实时运行仿真及应用*

崔业梅

1

 杨焕峥

2

1.无锡商业职业技术学院;2.江苏省无线传感系统应用工程技术研究开发中心

为了解决物联网网关程序的多任务协调与实时工作,

研究了定时器中断,μC/OS、FreeRTOS、RTX和RT-

Thread嵌入式实时操作系统的特点。RT-Thread拥有硬

实时核心,具有稳定、实时与可剪裁的性能,是一种“小而

美”的物联网操作系统,适合物联网网关使用。分析了RT-

Thread在物联网网关的STM32微控制器中运行的流程,编

写了程序,利用Proteus软件实现了多线程任务实时运行仿

真,并在物联网网关的STM32微控制器中稳定运行。

系统(Embedded RTOS)是一种好的解决方案,常见的

RTOS有μC/OS、FreeRTOS、RTX和RT-Thread等。

1 μC/OS、FreeRTOS、RTX和RT-Thread RTOS的

特点

μC/OS分为μC/OS-Ⅱ和μC/OS-Ⅲ,有抢占式,

高度便携式和可扩展的实时内核,是Embedded RTOS

的关键组件。它提供任务的调度和管理、多个任务之间

的同步和通信、中断服务等功能,拥有高效的执行率、很

0 引言

研制的物联网网关采用STM32微控制器(MCU),需

假设传感器每1s启动一次,控制传感器需要花费0.3s,

NB-IoT通信模块每2s就要向外部发送一些信息,耗费的

时间大约为0.5s,此时系统中还要执行其他的一些控制,

小的占用空间和较好的实时性等特点。FreeRTOS是为

Embedded RTOS设计的可扩展的实时内核,能方便地

移植到单片机上运行。它提供任务、时间和内存管理、信

号量和消息队列等功能,拥有公开的源码、灵活的调度策

略、可移植和裁减和免费等特点。Keil RTX是为ARM

Cortex-M微控制器设计的Embedded RTOS。拥有免版

.. All Rights Reserved.

要控制多个复杂的外设,有传感器、NB-IoT通信模块等,

比如通过串口进行数据传输,使数据在液晶屏上显示等。

税和确定性,能够实时执行多个任务,应用程序的结构能

如果采用中断的方式编写程序,不是单纯一个定时器中

更好、维护更容易等特点。RT-Thread是中国的开源

断,会有其他的一些中断,不能把控制传感器和NB-IoT

通信模块的程序简单的放在定时器中断中去执行。当系

统中断很多时,中断时间执行过长,将导致比它优先级低

的中断被抢占而无法执行,对于不支持中断嵌套的

MCU,采用这种方式,会导致一个更重要的事件被阻塞,

对于支持中断嵌套的MCU,这样设计也不好,因为同级别

的中断一般是不可以被另外一个同级别的中断抢占的。通

常情况下,应该尽快的将中断程序执行结束。如何解决使

物联网网关程序不是在各个任务协调工作上耗费大量的

时间,而是专注于各个任务的功能,采用嵌入式实时操作

收稿日期:2021-08-05

*基金项目:无锡商业职业技术学院课题“一种嵌入式AI工业物联网网关的研发与应用”的阶段性研究成果(KJXJ

20801)

作者简介:崔业梅(1983—),女,江苏东台人,硕士,实验师,高级技师,研究方向:教育学、电路技术。

23

Embedded RTOS

[1]

,除了有类似μC/OS和FreeRTOS

的内核外,也包括TCP/IP协议栈,虚拟文件系统,POSIX

接口,图形用户界面,FreeMODBUS主从协议栈,CAN框

架,动态模块等应用组件和驱动框架。商业产品可以免费

使用其内核和开源组件。拥有硬实时核心,稳定、实时与

可剪裁的性能等特点

[2-3]

。RT-Thread和μC/OS-Ⅱ的

特点对比,如表1所示。

2 基于RT-Thread的多线程任务实时运行仿真

研制的物联网网关使用RT-Thread作为Embedded

第 39 卷 数字技术与应用

表1 RT-Thread和μC/OS-Ⅱ的特点对比

Tab.1 Comparison of features between RT-Thread and μC/OS-Ⅱ

项目

任务调度

调度算法

优先级数

支持任务数

任务状态数

RT-Thread

分时调度,协作调度,优先级调度

多级队列位图调度

256

不限

5(初始,挂起,就绪,运行,结束)

使用RT-Thread操作系统

μC/OS-Ⅱ

优先级调度

纯位图调度

64

64

5(休眠,就绪,运行,挂起,被中断)

设为就绪状态,main线程含有main_

thread_entry()函数,它是用户应用程

序main()函数的跳转入口,当程序执行

到rt_system_ scheduler_start()函数后,

此刻任务调度器已经启动。再次,含有

$Super$$main()的线程会立即得到执

行,从而转入到main()函数。最后,执行

在main()函数里添加的用户应用程序

HAL库初始化

系统时钟、滴答时钟初始化

GPIO、shell串口初始化

调用

$Sub$$main()函数

启动文件

startup_stm

32f103xe.s

调用

$Super$$main()函数

main()函数

不使用RT-Thread操作系统

rt_thread_startup();

$Sub$$main();rt_hw_interrupt_disable();

rt_hw_board_init();

rt_show_version();

rt_system_timer_init();

rt_system_scheduler_init();

rt_application_init();

{

初始化代码等。如图1所示。

研制的物联网网关通过传感器采

集数据,通过NB-IoT通信模块将数据

传输到物联网云平台,在Embedded

RTOS的多线程任务中,可以将这个任

.. All Rights Reserved.

创建“main”线程,并将该

线程设为就绪状态,定义

$Super$$main()函数

务分解成两个子任务,一个子任务不间

断地读取传感器数据,并将数据写到共

享内存中,另一个子任务周期性的从共

享内存中读取数据,并将数据通过NB-

rt_system_timer_thread_init();

rt_thread_idle_init();

rt_system_scheduler_start();

系统调度器开始启动

IoT通信模块传输到物联网云平台。在

RT-Thread中,使用线程实现任务,线

程描述了一个任务执行的运行环境和

图1 RT-Thread在STM32微控制器中运行的流程

Fig.1 The flow of RT-Thread running in the STM32 microcontroller

RTOS

[4]

。使用Keil(MDK-ARM)软件对STM32 MCU进

行编程,首先,程序启动后从汇编代码startup_stm32f103

xe.s开始运行,通过编译系统提供的一个函数__main(),

初始化库函数和应用程序的执行环境。其次,RT-

Thread的启动用到了Keil提供的$Sub$$和$Super$$函数

的功能,这个是在__CC_ARM编译器环境中的功能,程序

从启动文件的__main()函数执行完毕之后,会优先执行

$Sub$$main()函数,该函数包含了RT-Thread的初始化

过程,通过$Sub$$main()函数的rt_thread_startup()函数

来完成RT-Thread的初始化及启动等,具体有通过

rt_hw_board_init()函数实现STM32 HAL库初始化、系

统时钟、滴答时钟初始化、GPIO、串口初始化等,然后在

rt_application_init()函数中会创建main线程,并将该线程

24

所处的优先等级,根据任务的重要性不同可设置相对高

低不同的优先级,不同的任务还可以设置相同的优先级,

轮流运行

[5-6]

。使用Proteus软件的VSM Studio Keil编译

器仿真RT-Thread多线程任务在STM32 MCU里实时

运行,利用LED0指示灯模拟传感器,USART1串口数据

传输模拟NB-IoT通信模块,编写的Source Code里main.

c文件的开头线程定义如下:

static void led0_thread_entry(void*parameter){

while(1){

LED0=~LED0;

rt_thread_mdelay(500);

}

}

崔业梅 杨焕峥:基于RT-Thread的多线程任务实时运行仿真及应用

2021年第 10 期

static void USART1_thread_entry(void *

parameter){

while(1){

printf("%s","RT-Thread STM32 RealTime

USART1 Test!rn");

rt_thread_mdelay(500);

}

}

在main.c文件的main()函数中线程初始化及启动定

义如下:

rst1= rt_thread_init(&led0_thread,

"led0",

led0_thread_entry,

RT_NULL,

&led0_thread_stack[0],

sizeof(led0_thread_stack),

RT_THREAD_PRIORITY_MAX-1,

20);

rst3= rt_thread_init(&USART1_thread,

"USART1",

USART1_thread_entry,

RT_NULL,

&USART1_thread_stack[0],

sizeof(USART1_thread_stack),

RT_THREAD_PRIORITY_MAX-3,

20);

if(rst1==RT_EOK&&rst3==RT_EOK){

rt_thread_startup(&led0_thread);

rt_thread_startup(&USART1_thread);

}

while(1){

rt_thread_mdelay(100);

}

定义了led0_thread_entry()和USART1_thread_

entry()两个线程,分别实现LED0闪烁和通过USART1输

出字符串。通过函数rt_thread_init()对线程进行初始化,

通过函数rt_thread_startup()使线程实现就绪,调度器会

调度就绪的线程使其进入运行,通过rt_thread_delay()等

函数使运行的线程进入挂起,如果等待超时将返回就绪,

通过rt_thread_delete()函数使线程实现关闭或线程运行

结束时执行rt_thread_exit()函数实现关闭。Proteus软件

仿真结果如图2所示。

在STM32 MCU中运行RT-Thread,实现了LED0、

USART1等多线程任务的实时运行,LED0不停闪烁,

USART1不断输出字符串“RT-Thread STM32 RealTime

USART1 Test!”,解决了系统需要控制多个复杂的外设,

如果中断很多,中断时间执行过长,将导致比它优先级低

的中断被抢占而无法执行等问题。

3 多线程任务实时运行在物联网网关中的应用

研制的物联网网关采用STM32 MCU,包含传感器、

NB-IoT通信模块、RS-485电路、LED指示灯、继电器和

LCD等。可以通过多路传感器采集数据,通过NB-IoT通

信模块将数据发送到物联网云平台,可以通过云平台下

发命令控制继电器开关。使用RT-Thread实现多线程任

务实时运行,内核使用了调度器,信号量等,调度器是为

了创建多个线程来实现不同的工作,信号量是用来实现

线程间的同步。组件部分使用了UART和SENSOR框架,

UART框架指使用了2个串口,分别连接NB-IoT通信模

块和RS-485电路,分别用于跟物联网云平台和外设通

信,SENSOR框架指使用传感器采集数据。通过RT-

Thread对外设进行初始化,硬件驱动初始化,各个软件包

初始化,初始化后进入传感器采集数据、LCD显示、RS-

485数据传输线程,轮询线程,如图3所示。

STM32 MCU部分程序如下:

//初始化线程函数

void MX_RT_Thread_Init(void)

{

//初始化SENSOR1线程

rt_thread_init(&sensor1_thread,"sensor1",

sensor1_task_entry,RT_NULL,&rt_sensor1_thread_

stack[0],sizeof(rt_sensor1_thread_stack),3,20);

//初始化LCD线程

rt_thread_init(&LCD_thread,"LCD",LCD_task_

entry,RT_NULL,&rt_LCD_thread_stack[0],sizeof

(rt_LCD_thread_stack),3,20);

//初始化RS-485通信线程

rt_thread_init(&RS485_thread,"RS485",

RS485_task_entry,RT_NULL,&rt_RS485_thread_

25

.. All Rights Reserved.

第 39 卷 数字技术与应用

void sensor1_task_entry(void

*parameter){}

//LCD任务

void LCD_task_entry(void

*parameter) {}

//RS-485任务

void RS485_task_entry(void

*parameter){}

程序包含了初始化SENSOR1、

LCD和RS-485通信线程等,并开启了

它们的线程调度,SENSOR1线程的任

务用于读取温度传感器的数据,LCD线

程的任务用于将数据在液晶屏上显示,

RS-485线程的任务用于将数据传输给

外设等,程序在研制的物联网网关

图2 Proteus软件的RT-Thread多线程实时运行仿真

STM32 MCU中能稳定运行。

Fig.2 RT-Thread multi-thread real-time running simulation of Proteus software

RT-Thread

内核

4 结语

设备初始化

外设初始化,硬件驱动初

始化,各个软件包初始化

轮询

线程

初始化后

初始化后

初始化后

进入线程

进入线程

RT-Thread拥有硬实时核心,具有稳定、实时与可剪

裁的性能,具有全抢占的Embedded RTOS内核、轻型的

TCP/IP协议栈和多窗口多线程图形用户界面等特点,是

一种“小而美”的物联网操作系统。分析了RT-Thread在

物联网网关的STM32微控制器中运行的流程,编写了程

序,利用Proteus软件实现了多线程任务实时运行仿真,在

物联网网关的STM32 MCU中使用,能稳定运行,解决了

物联网网关程序的多任务协调与实时工作的问题。

引用

[1] 叶宏.国产嵌入式操作系统:在信息技术变迁中成长、发

展与壮大[J].单片机与嵌入式系统应用,2021(3):3.

[2] 邱

,熊谱翔,朱天龙.嵌入式实时操作系统:RT-Thread设

计与实现[D].北京:机械工业出版社,2019.

[3] 邱

.RT-Thread:两大安全措施保障嵌入式软件开发的安

全[J].电子产品世界,2021(4):9.

[4] 陈梦亮.基于嵌入式Linux的物联网网关设计与实现[D].

长沙:湖南大学,2020.

[5] 孙晋.基于北斗短报文和RT-Thread的远程通信系统设计

[D].南京:南京信息工程大学,2020.

[6] 张帝,权悦,国海,等.基于LoRa与RT-Thread的多功能矿灯

设计[J].工矿自动化,2021(6):96-102.

进入线程

.. All Rights Reserved.

轮询

轮询

线程

线程

RS-485数据

传输线程

LCD显示线程

传感器采集数

据线程

图3 基于RT-Thread的多线程任务实时运行程序框图

Fig.3 Block diagram of real-time operation of multi-

threaded tasks based on RT-Thread

stack[0],sizeof(rt_RS485_thread_stack),3,20);

//开启线程调度

rt_thread_startup(&sensor1_thread);

rt_thread_startup(&LCD_thread);

rt_thread_startup(&RS485_thread);

}

//主任务

void MX_RT_Thread_Process(void)

{

printf("***基于RT-Thread的多线程任务实时运行

仿真及应用***rn");

rt_thread_delay(2000);

}

//SENSOR1任务

26


本文标签: 任务 线程 运行 执行 中断