【RT

您所在的位置:网站首页 求教正点原子老师关于你的延时函数的问题及解答 【RT

【RT

2023-08-29 05:01| 来源: 网络整理| 查看: 265

STM32F103RB移植RT-Thread Nano 移植的主要工作内容基于 CubeMX 移植 RT-Thread Nano准备工作Nano pack 安装创建基础工程 添加 RT-Thread Nano 到工程选择 Nano 组件配置 Nano工程管理配置 MCU 适配 RT-Thread Nano中断与异常处理 MDK工程文件介绍控制台CONSOLE的串口配置系统时钟配置RT-Thread系统配置文件rtconfig.h文件 编写第一个应用在 Nano 上添加 FinSH 组件(实现命令输入)运行官方内核例程

移植的主要工作内容

RT-Thread 内核及底层结构 内核是操作系统最基础也是最重要的部分。上图为 RT-Thread 内核架构图,内核处于硬件层之上,内核部分包括内核库、实时内核实现。 内核库是为了保证内核能够独立运行的一套小型的类似 C 库的函数实现子集。这部分根据编译器的不同自带 C 库的情况也会有些不同,当使用 GNU GCC 编译器时,会携带更多的标准 C 库实现。

提示:C 库:也叫 C 运行库(C Runtime Library),它提供了类似 “strcpy”、“memcpy” 等函数,有些也会包括 “printf”、“scanf” 函数的实现。RT-Thread Kernel Service Library 仅提供内核用到的一小部分 C 库函数实现,为了避免与标准 C 库重名,在这些函数前都会添加上 rt_前缀。

实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是 3KB ROM,1.2KB RAM。我们的目标平台STM32F103RBT6有 128 KB ROM 和 20 KB SRAM,可支持RT-Thread Nano精简内核的运行。

从上面的架构图可知,RT-Thread内核移植的主要工作有两块,即分别根据芯片和开发板资源的配置移植修改 芯片架构支持部分 libcpu 和 板级支持包部分BSP。

基于 CubeMX 移植 RT-Thread Nano

接下来介绍如何基于 CubeMX 移植 RT-Thread Nano,并说明生成代码工程的步骤。

RT-Thread Nano 已集成在 CubeMX 中,可以直接在 IDE 中进行下载添加。本文档介绍了如何使用 CubeMX 移植 RT-Thread Nano,并以一个 stm32f103 的基础工程作为示例进行讲解。

移植 Nano 的主要步骤:

准备一个 CubeMX 基础工程,并获取 RT-Thread Nano pack 安装包进行安装。在基础工程中添加 RT-Thread Nano 源码。适配 Nano,主要从 中断、时钟、内存、应用 这几个方面进行适配,实现移植。最后可对 Nano 进行配置:Nano 是可裁剪的,可以通过配置文件 rtconfig.h 实现对系统的裁剪。 准备工作 下载 Cube MX 5.0 ,下载地址 https://www.st.com/en/development-tools/stm32cubemx.html 。在 CubeMX 上下载 RT-Thread Nano pack 安装包。 Nano pack 安装

要获取 RT-Thread Nano 软件包,需要在 CubeMX 中添加 https://www.rt-thread.org/download/cube/RealThread.RT-Thread.pdsc 。

具体步骤:进入打开 CubeMX,从菜单栏 help 进入 Manage embedded software packages 界面,点击 From Url 按钮,进入 User Defined Packs Manager 界面,其次点击 new,填入上述网址,然后点击 check,如下图所示:

完成安装

check 通过后,点击 OK 回到 User Defined Packs Manager 界面,再次点击 OK,CubeMX 自动连接服务器,获取包描述文件。回到 Manage embedded software packages 界面,就会发现 RT-Thread Nano 3.1.5 软件包,选择该软件包,点击 Install Now,如下图所示:

选择版本

点击安装之后,弹出 Licensing Agreement ,同意协议,点击 Finish,如下图所示:

选择版本

等待安装完成,成功安装后,版本前面的小蓝色框变成填充的黄绿色,现象如下图所示:

完成安装

至此,RT-Thread Nano 软件包安装完毕,退出 Manage embedded software packages 界面,进入 CubeMX 主界面。

创建基础工程

在 CubeMX 主界面的菜单栏中 File 选择 New Project,如下图所示

创建新工程

新建工程之后,在弹出界面芯片型号中输入某一芯片型号,方便锁定查找需要的芯片,双击被选中的芯片,如下图所示

创建新工程

添加 RT-Thread Nano 到工程 选择 Nano 组件

选中芯片型号之后,点击 Softwares Packages->Select Components,进入组件配置界面,选择 RealThread, 然后根据需求选择 RT-Thread 组件,然后点击 OK 按钮,如下图所示:

选择软件包

注意:RT-Thread Nano 软件包中包含 kernel, shell 和 device 三个部分,仅选择 kernel 表示只使用 RT-Thread 内核,工程中会添加内核代码;选择 kernel 与 shell 表示在使用 RT-Thread Nano 的基础上使用 FinSH Shell 组件,工程中会添加内核代码与 FinSH 组件的代码,FinSH 的移植详见 《在 RT-Thread Nano 上添加控制台与 FinSH》。再选择 device 表示使用 rt-thread 的 device 框架,用户基于此框架编写外设驱动并注册后,就可以使用 device 统一接口操作外设。

配置 Nano

选择组件之后,对组件参数进行配置。在工程界面 Pinout & Configuration 中,进入所选组件参数配置区,按照下图进行配置

配置 rt-thread

工程管理

给工程取名、选择代码存放位置、选择生成代码的 Toolchain/IDE。Cube MX 不仅能够生成 Keil4/Keil5 的工程,而且还能够生成 IAR7/IAR8 等 IDE 的工程,功能强大,本文从下拉框中选择 MDK5,操作如图所示

工程管理 代码生成选项卡Code Gennerator无需调整。 在这里插入图片描述

配置 MCU

根据需求配置 MCU 的功能。 在这里插入图片描述 在这个例子中我们会用到正点原子STM32F103 Nano开发板的GPIO(LED,按键)和 UART(控制台和Finsh组件),还需配置其运行时钟。所以需要在CubeMX中进行相应配置。

功能模块关联引脚LED 0~7PC 0~7KEY 0PC8KEY 1PC9CONSOLEUSART1

硬件配置 打开HSE和LSE。 在这里插入图片描述 将主频设为最高的72MHz。 在这里插入图片描述

适配 RT-Thread Nano 中断与异常处理

RT-Thread 操作系统重定义 HardFault_Handler、PendSV_Handler、SysTick_Handler 中断函数,为了避免重复定义的问题,在生成工程之前,需要在中断配置中,代码生成的选项中,取消选择三个中断函数(对应注释选项是 Hard fault interrupt, Pendable request, Time base :System tick timer),最后点击生成代码,具体操作如下图 所示:

中断配置

SysTick_Handler 将被用作操作系统的时基,如为了能成正常使用HAL 库的时基函数HAL_Delay,可将HAL时基改为TIM1基本定时器。 时基定时器修改等待工程生成完毕,点击打开工程,如下图所示,即可进入 MDK5 工程中。打开工程

MDK工程文件介绍

打开MDK工程,可看到RT-Thread已被配置到工程目录中。 工程目录 点开kernel文件夹 文件介绍

控制台CONSOLE的串口配置

其中移植工作中的芯片架构部分已经由CubeMX设置后自动生成完成,即其中的 context_rvds.S文件内容,我们只需要完成BSP部分的移植即可,在board.c文件中,点击打开文件。 在这里插入图片描述

在第71行,可看到,若我们使能了CONSOLE,会自动添加下面的UART初始化代码,这里只需要把其中的USART2修改为我们实际使用开发板上的UART1即可。

系统时钟配置

需要在 board.c 中实现 系统时钟配置(为 MCU、外设提供工作时钟)与 OS Tick 的配置 (为操作系统提供心跳 / 节拍)。此处无需修改,用系统生成的默认代码即可。

如下代码所示, HAL_Init() 初始化 HAL 库, SystemClock_Config() 配置了系统时钟, SystemCoreClockUpdate() 对系统时钟进行更新,_SysTick_Config() 配置了 OS Tick。此处 OS Tick 使用滴答定时器 systick 实现,需要用户在 board.c 中实现 SysTick_Handler() 中断服务例程,调用 RT-Thread 提供的 rt_tick_increase() ,如下图所示。

/* board.c */ void rt_hw_board_init() { HAL_Init(); SystemClock_Config(); /* System Clock Update */ SystemCoreClockUpdate(); /* System Tick Configuration */ _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); /* Call components board initial (use INIT_BOARD_EXPORT()) */ #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get()); #endif }

OS Tick 的实现

RT-Thread系统配置文件rtconfig.h文件

我们通过 rtconfig.h 文件查看和修改各个宏定义信息,从而配置和裁剪RT-Thread操作系统。通过任意rtthread文件中的万能头文件 rtthread.h 即可找到rtconfig.h。打开后,可利用MDK的图形化配置向导功能,快速对RT-Thread进行配置。这里我们对照下图箭头处进行修改即可。 在这里插入图片描述

编写第一个应用

移植好 RT-Thread Nano 之后,则可以开始编写第一个应用代码。此时 main() 函数就转变成 RT-Thread 操作系统的一个线程,现在可以在 main() 函数中实现第一个应用:板载 LED 指示灯闪烁,并使用rt_kprintf打印。

首先在文件首部包含 RT-Thread 的相关头文件 。 在这里插入图片描述

在 main() 函数中注释掉下图部分,这些初始化已在完成RT-Thread启动时完成。 在这里插入图片描述

在MX_GPIO_Init() 函数后添加INIT_BOARD_EXPORT(MX_GPIO_Init);即可将GPIO的初始化加入RT-Thread的启动过程。 GPIO初始化

在 main() 函数中(也就是在 main 线程中)写CONSOLE打印代码 和 LED 闪烁代码,在循环中点亮 / 熄灭 LED。 测试

延时函数使用 RT-Thread 提供的延时函数 rt_thread_mdelay(),该函数会引起系统调度,切换到其他线程运行,体现了线程实时性的特点。 编译程序之后下载到芯片就可以看到基于 RT-Thread 的程序运行起来了,LED 正常闪烁。

Note注:当添加 RT-Thread 之后,裸机中的 main() 函数会自动变成 RT-Thread 系统中 main 线程 的入口函数。由于线程不能一直独占 CPU,所以此时在 main() 中使用 while(1) 时,需要有让出 CPU 的动作,比如使用 rt_thread_mdelay() 系列的函数让出 CPU。

与裸机 LED 闪烁应用代码的不同:

1). 延时函数不同: RT-Thread 提供的 rt_thread_mdelay() 函数可以引起操作系统进行调度,当调用该函数进行延时时,本线程将不占用 CPU,调度器切换到系统的其他线程开始运行。而裸机的 delay 函数是一直占用 CPU 运行的。

2). 初始化系统时钟的位置不同:移植好 RT-Thread Nano 之后,不需要再在 main() 中做相应的系统配置(如 hal 初始化、时钟初始化等),这是因为 RT-Thread 在系统启动时,已经做好了系统时钟初始化等的配置,这在上一小节 “系统时钟配置” 中有讲解。

在 Nano 上添加 FinSH 组件(实现命令输入)

RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,打开通信软件PuTTY,根据端口号和配置的串口波特率进行配置。 在这里插入图片描述

使用 FinSH 组件基本命令的效果图如下所示:

效果图

输入help或直接按TAB键可调出当前可使用的MSH命令。 MSH命令有自动补全功能,输入头几个字母可按TAB自动补全。 PS命令可查看当前系统运行线程的情况。

运行官方内核例程

作为一个操作系统,RT-Thread 的代码规模怎么样呢?在弄清楚这些之前,我们先要做的就是获得与本文相对应的 RT-Thread 的例子,这份例子可以从以下链接获得:

RT-Thread Simulator 例程

这个例子是一个压缩包文件,将它解压,我们这里解压到 D:/。解压完成后的目录结构如下图所示:

rtthread_simulator_v0.1.0 代码目录

各个目录所包含的文件类型的描述如下表所示:

目录名描述applicationsRT-Thread 应用程序。rt-threadRT-Thread 的源文件。- componentsRT-Thread 的各个组件目录。- includeRT-Thread 内核的头文件。- libcpu各类芯片的移植代码,此处包含了 STM32 的移植文件。- srcRT-Thread 内核的源文件。- toolsRT-Thread 命令构建工具的脚本文件。driversRT-Thread 的驱动,不同平台的底层驱动具体实现。LibrariesST 的 STM32 固件库文件。kernel-sample-0.1.0RT-Thread 的内核例程。

kernel-sample-0.1.0中存放了RTT内核相关的演示例程,我们将其复制放入自己的工程文件中。 添加工程 使用工程管理工具,在创建例程目录,例程文件添加进工程。因STM32F103RB FLASH和SRAM限制,建议每次只将要使用的一个例程文件加入。此处只加入thread_sample.c,并将程序中的 thread1/2 栈空间由512B和1024B改为256B。 在这里插入图片描述 编译、烧录、运行,即可在串口控制台发现先导入的例程命令。输入命令thread_sample即可运行查看例程演示效果。 在这里插入图片描述 如此,可对照官方参考文档,将 内核基础 结合例程学习一遍。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3