RT-Thread 学习启动篇

RT-Thread 系统

RT-Thread 是一款完全由国内团队开发维护的嵌入式实时操作系统(RTOS)。

RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。事实上,一个处理器核心在某一时刻只能运行一个任务,由于每次对一个任务的执行时间很短、任务与任务之间通过任务调度器进行非常快速地切换(调度器根据优先级决定此刻该执行的任务),给人造成多个任务在一个时刻同时运行的错觉。在 RT-Thread 系统中,任务通过线程实现的,RT-Thread 中的线程调度器也就是以上提到的任务调度器。

与 Linux 系统比较

相较于 Linux 操作系统,RT-Thread 体积小,成本低,功耗低、启动快速,除此以外 RT-Thread 还具有实时性高、占用资源小等特点,非常适用于各种资源受限(如成本、功耗限制等)的场合。虽然 32 位 MCU 是它的主要运行平台,实际上很多带有 MMU、基于 ARM9、ARM11 甚至 Cortex-A 系列级别 CPU 的应用处理器在特定应用场合也适合使用 RT-Thread。

RT-Thread 的系统架构

RT-Thread 与其他很多 RTOS 如 FreeRTOS、uC/OS 的主要区别之一是,它不仅仅是一个实时内核,还具备丰富的中间层组件,如下图所示。

RT-Thread的系统架构图 RT-Thread的系统架构图

内核层

RT-Thread 内核,是 RT-Thread 的核心部分,包括了内核系统中对象的实现,例如多线程及其调度、信号量、邮箱、消息队列、内存管理、定时器等;libcpu/BSP(芯片移植相关文件 / 板级支持包)与硬件密切相关,由外设驱动和 CPU 移植构成。

组件与服务

组件是基于 RT-Thread 内核之上的上层软件,例如虚拟文件系统、FinSH 命令行界面、网络框架、设备框架等。采用模块化设计,做到组件内部高内聚,组件之间低耦合。

软件包

运行于 RT-Thread 物联网操作系统平台上,面向不同应用领域的通用软件组件,由描述信息、源代码或库文件组成。RT-Thread 提供了开放的软件包平台,这里存放了官方提供或开发者提供的软件包,该平台为开发者提供了众多可重用软件包的选择,这也是 RT-Thread 生态的重要组成部分。软件包生态对于一个操作系统的选择至关重要,因为这些软件包具有很强的可重用性,模块化程度很高,极大的方便应用开发者在最短时间内,打造出自己想要的系统。RT-Thread 已经支持的软件包数量已经达到 60+.

  • 物联网相关的软件包:Paho MQTT、WebClient、mongoose、WebTerminal 等等。
  • 脚本语言相关的软件包:目前支持 JerryScript、MicroPython。
  • 多媒体相关的软件包:Openmv、mupdf。
  • 工具类软件包:CmBacktrace、EasyFlash、EasyLogger、SystemView。
  • 系统相关的软件包:RTGUI、Persimmon UI、lwext4、partition、SQLite 等等。
  • 外设库与驱动类软件包:RealTek RTL8710BN SDK。

MDK-ARM

MDK-ARM(MDK-ARM Microcontroller Development Kit)软件是一套完整的集成开发环境(IDE),它出自 ARM 公司,包括了针对 ARM 芯片(ARM7,ARM9,Cortex-M 系列,Cortex-R 系列等)的高效 C/C++ 编译器;针对各类 ARM 设备、评估板的工程向导,工程管理;用于软件模拟运行硬件平台的模拟器;以及与市面上常见的如 ST-Link,JLink 等在线仿真器相连接以配合调试目标板的调试器。MDK-ARM 软件中的软件仿真模拟器,采用完全软件模拟方式解释执行 ARM 的机器指令,并实现外围的一些外设逻辑,从而构成一套完整的虚拟硬件环境,使得用户能够不借助真实的硬件平台就能够在电脑上执行相应的目标程序。

MDK-ARM 集成开发环境截图 MDK-ARM 集成开发环境截图

RT-Thread 示例程序

首先去 GitHub 克隆 master 分支或者发布版本。目录结构如下:

名称描述
BSPBoard Support Package(板级支持包)基于各种开发板的移植
componentsRT-Thread 的各个组件代码,例如 finsh,gui 等。
documentation相关文档,如编码规范等
examples相关示例代码
includeRT-Thread 内核的头文件。
libcpu各类芯片的移植代码。
srcRT-Thread 内核的源文件。
toolsRT-Thread 命令构建工具的脚本文件。

其余的我们现在暂时不看,只看 BSP 里面的示例代码,首先找到我们开发板的对应文件夹,我手头开发板是潘多拉,如下图:

正点原子-潘多拉开发板 正点原子-潘多拉开发板

选择此开发板对应的 /bsp/stm32/stm32l475-atk-pandora 文件夹,进入后双击 project.uvprojx 打开工程。

此时我们还需要安装 pack 包,去官网下载:https://www.keil.com/dd2/pack/

下载MDK对芯片的支持包 下载MDK对芯片的支持包

BSP: Board Support Package 板级支持包。 DFP: Device Family Pack 设备系列包,对处理器的支持能力。

或者点击 pack installer 进行安装:

使用usb线连接电脑,安装驱动程序,接着,编译下载到开发板。

编译,烧录程序 编译,烧录程序

接下来我们修改一下 Applications 目录下的 main.c 文件内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

/* defined the LED0 pin: PE7 */
#define LED0_PIN    GET_PIN(E, 7)
#define LED1_PIN    GET_PIN(E, 8)
#define LED2_PIN    GET_PIN(E, 9)

int main(void)
{
    int count = 1;

    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
	rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
	rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);

    while (count++)
    {
		rt_pin_write(LED0_PIN, PIN_HIGH);
        rt_pin_write(LED1_PIN, PIN_LOW);
		rt_pin_write(LED2_PIN, PIN_LOW);
        rt_thread_mdelay(1000);

		rt_pin_write(LED0_PIN, PIN_LOW);
        rt_pin_write(LED1_PIN, PIN_HIGH);
		rt_pin_write(LED2_PIN, PIN_LOW);
        rt_thread_mdelay(1000);

		rt_pin_write(LED0_PIN, PIN_LOW);
        rt_pin_write(LED1_PIN, PIN_LOW);
		rt_pin_write(LED2_PIN, PIN_HIGH);
		rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

这段程序很容易理解,首先定义了三个管脚。

1
2
3
#define LED0_PIN    GET_PIN(E, 7)
#define LED1_PIN    GET_PIN(E, 8)
#define LED2_PIN    GET_PIN(E, 9)

接着使用 rt_pin_mode 函数设定指定引脚的工作模式。

参数说明
PIN_MODE_OUTPUT输出
PIN_MODE_INPUT输入
PIN_MODE_INPUT_PULLUP上拉输入
PIN_MODE_INPUT_PULLDOWN下拉输入
PIN_MODE_OUTPUT_OD开漏输出

紧接着使用 rt_pin_write 函数去分别输出高低电平,显示效果如下:

电路原理

打开潘多拉开发板的资料,找到电路原理图中的三色发光二极管电路图如下:

三色发光二极管电路原理图 三色发光二极管电路原理图

STM32对应管脚示意图 STM32对应管脚示意图

总结

基于上面知识总算是窥探了一下这个 RT-Thread 的整体效果,至于 RT-Thread 怎么使用到目前为止还没有涉及到,我们还需要逐步了解 RT-Thread 的内核工作原理,然后再学习 Env, scons 的使用,最后再玩玩系统移植。

附录

去 STM32 官网就可以找到 ST_Link 的驱动文件,地址:https://www.st.com/zh/development-tools/stsw-link009.html

ST_Link驱动下载 ST_Link驱动下载

重构后的流水灯

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>


#define LED_PIN_RED 		GET_PIN(E, 7)  //红灯管脚
#define LED_PIN_GREEN 	    GET_PIN(E, 8)  //绿灯管脚
#define LED_PIN_BLUE 		GET_PIN(E, 9)  //蓝灯管脚


//根据下标点亮LED
void change_lighting_led(int lightIndex)
{
	  rt_base_t rgbs[] = {LED_PIN_RED, LED_PIN_GREEN, LED_PIN_BLUE};
		for(int i = 0; i < 3; i++)
	  {
				if(i == lightIndex)
				{
						rt_pin_write(rgbs[i], PIN_LOW);
				}
				else
				{
						rt_pin_write(rgbs[i], PIN_HIGH);
				}
		}
}

int main(void)
{
    int count = 1;
	
	//设置管脚的模式
    rt_pin_mode(LED_PIN_RED, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_PIN_GREEN, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_PIN_BLUE, PIN_MODE_OUTPUT);

    while (count++)
    {
				change_lighting_led(count % 3);
				rt_thread_mdelay(1000);
    }

    return RT_EOK;
}