当前位置: 首页 > news >正文

【嵌入式】RT-Thread入门(一)内核移植

文章目录

    • 0 前言
    • 1 RT-Thread Nano
    • 2 Keil项目下移植
    • 3 STM32CubeMX移植
    • 4 代码启动流程

0 前言

  因为项目的关系,需要使用实时操作系统RT-Thread,虽然很早之前就听过他的大名,但一直没有正式接触,所以也算是入门,打算写几篇文章来记录一下自己的学习例程。

1 RT-Thread Nano

  既然要认真学,那肯定得参考官方的资料。首先打开官方的文档,结构还是非常明确的:

在这里插入图片描述

可以先从新手指导开始学习,了解整个RTOS的框架,以及各个部分的介绍,这里暂且按下不表。如果是刚接触RT-Thread,建议还是从Nano版本开始。

2 Keil项目下移植

  只看文档是没有用的,关键在于实操。这里以Keil这个最常用的嵌入式开发软件,以STM32这个最常见的芯片为例,来介绍RT-Thread Nano下的移植方法,还是比较简单的。

  首先在Pack Installer中找到RT-Thread(如果一直在加载中记得科学上网):

在这里插入图片描述

在左侧随便选中一个期间,然后在右边一直划到最底下(按字母排序,R),然后安装即可。

如果实在是加载不出来,也可以到ARM Keil官网去下载——> 链接直达。

  然后正常安装即可,这一步比较简单。

  安装好之后,就可以开始使用了。先找一个可以编译通过且正常运行的项目工程,至少要启用一个串口,然后在RTE中启用RT-Thread:

在这里插入图片描述

在这里插入图片描述

一般来说,只启用kernal和shell即可,device框架并不完善,如果实在要用还是移步标准版。

  回到工程,可以发现多了一些文件,其中不带黄色钥匙图标的文件(非只读文件)才需要修改,也是添加到项目工程目录中的文件,其他带🔑的文件只是一个引用,原文件并没有复制到项目工程下。

在这里插入图片描述

  • 1 finsh终端移植

  首先点开board.c文件,可以看到其实已经用error标示了怎么移植(如果直接编译就可以通过error直接定位到这里)

在这里插入图片描述
所以第一个地方直接调用串口初始化的函数,第二个地方调用串口输出的函数即可。

在这里插入图片描述

和上面一样,字符串输入也需要移植,在finsh_port.c中:

在这里插入图片描述

  • 2 屏蔽由RTOS接管的中断

  当添加RT-Thread时,它会自动接管HardFault和PendSV两个异常中断(在context_rvds.s文件中),所以原先stm32f10x_it.c中的中断服务函数需要注释掉,不然会报重复定义的错误。
在这里插入图片描述

在这里插入图片描述

  • 3 系统时钟中断函数

  还是在上面的board.c文件中,有一个RT-Thread所需要的时钟中断函数:

在这里插入图片描述

需要将这个函数添加到Systick_Handler中:

在这里插入图片描述

所有都移植之后,再点击编译,理论上应该是不会再报错了。

3 STM32CubeMX移植

  作为STM32开发未来的趋势,STM32CubeMX其实也已经支持直接在配置中添加RT-Thread Nano内核。RT-Thread官网给出的教程是需要额外添加一个链接,才能够安装RT-Thread包,但其实,新版的STM32CubeMX已经可以直接下载安装RT-Thread库:

在这里插入图片描述

同样,在Middleware中也可以看到RT-Thread的选项:

在这里插入图片描述

  这里再简单提个题外话。RT-Thread官网给出的教程是需要添加一个链接,然后再下载安装,而且展示的安装版本是3.1.5,和Keil中是一致的,但是我实测发现最新版本只有3.1.3,但实际添加的链接是完全一致的,所以猜测可能是出啥问题导致版本回退了?反倒是直接通过Cube安装的这个带X-CUBE前缀的RT-Thread包的版本是4.1.1,好像要新一点,所以建议还是使用Cube自带的包比较好。而且官网的B站账号下的教程视频也是使用这个版本:

STM32CubeMX使用RT-Thread nano v4.1.1资源包教学

  题外话结束,接下来看一下怎么使用。

  和配置其他外设一样,先选中然后使能对应的组件:

在这里插入图片描述

根据上面的视频介绍,kernal、libcpu是必选,shell就是finsh终端,也建议选上。配置好之后,只是表示这个可以选,但还需要使能并配置,如下图所示:

在这里插入图片描述

这里需要注意:配置这些的时候一定要仔细看下面的提示,因为设置时不会自动解决依赖关系,这点需要自己手动配置好,比如使能定时器就需要使能堆内存。

  和Keil一样,因为使能了RTOS,有些异常中断会被RTOS接管,因此在生成代码这里要取消生成:

在这里插入图片描述

在这里插入图片描述

另外,很重要的一点是,在使能了RT-Thread,如果TimeBase还是Systick的话,会弹出一个警告:

在这里插入图片描述

上面的视频教程中是直接忽略了,但可能是和芯片型号有关,我在使用STM32F7时,如果这里仍然坚持使用Systick,那么程序运行就会卡在HAL_Delay函数这里,猜测应该是中断优先级设置有问题,因为Systick的中断也被接管了,中断的优先级到底是多少也不清楚,如果遇到这种情况,不用太纠结,建议直接换一个定时器。

  最后,再来介绍几个可能会出现的错误:

在这里插入图片描述

报错找不到board.h文件,为了避免每次生成都需要改一次,这里可以自己定义一个board.h文件,空的都行。

在这里插入图片描述

这里的寄存器有问题,在STM32F7的HAL库中,数据寄存器分为输入数据寄存器(RDR)和输出数据寄存器(TDR),根据上下文语境,这里应该是输入数据寄存器,所以改为RDR,而且,这里有一个问题就是else部分中的延时,经过测试,发现这个延时没有任何作用,反倒是会导致数据接收不完整等问题,所以这里也需要注释掉。改完之后如下所示。

在这里插入图片描述

4 代码启动流程

  为什么可以在原先裸机代码工程的基础上直接添加一个RT-Thread,而且不用修改任何原来的代码,这到底是怎么实现的呢?其实就涉及到了RT-Thread项目的启动流程。如果在芯片中仿真,可以发现,程序执行完了启动代码之后,首先跳转的并不是main函数,而是components.c中的这里:

在这里插入图片描述

执行完了这个rtthread_startup函数之后才会跳转到main函数。那这个在函数名中加上$Sub$$是啥意思?其实这个涉及到MDK编译器的一个功能——即给一个函数打补丁,实现在已经被“固定死”的函数前后加上一段自定义的代码。

  一般$Sub$$要和$Super$$一起使用,其中,后者用来声明需要打补丁的函数,前者用来定义补丁的内容,举个例子:

//以下demo来自arm mdk开发者手册
//这个demo比较清晰地列出了补丁操作的框架,这个操作可以说十分简单但是考验概念理解力;
//执行完sub函数之后,在sub函数中extern一下 super函数,然后调用super函数回到原函数去执行;
extern void ExtraFunc(void);    //补丁操作;

extern void $Super$$foo(void):
void $Sub$$foo(void)
{
    ExtraBeforeFunc();     // 函数执行之前的补丁操作;    
    $Super$$foo();         // 通过$Super$$foo()调用函数原型;
    ExtraAfterFunc();      // 函数执行之后执行的部分
}

Reference

相关文章:

  • 【汇编语言】单片机程序执行过程
  • MySQL数据库复杂的增删改查操作
  • 【算法 C/C++】一维差分
  • 本科毕业论文开题报告需要查重吗?
  • API随心搭接口:一键定制你的专属数据解决方案
  • 图片的拖拽+缩放
  • envsetup和python venv
  • 跟踪性能提高11%|端到端新架构DMAD:通过分离语义-运动学习解决负迁移难题
  • 山东大学离散数学第五章习题解析
  • 理论+实操:MyBlockly 可视化编程工具详解,以及如何基于 pymycobot 库控制ultraArm 机械臂
  • C#-扩展方法-Linq
  • u盘和硬盘的存储结构
  • 拦截器与过滤器
  • LPZero: Language Model Zero-cost Proxy Search from Zero(未更新完预览版本)
  • C++算法——差分
  • 在Vue中 使用 Web Worker
  • 2025-3-9 一周总结
  • 强化学习(赵世钰版)-学习笔记(4.值迭代与策略迭代)
  • 算力100问☞第80问:如何实现算力的弹性伸缩?
  • 配置 Thunderbird 以使用 QQ 邮箱
  • 怎样做游戏网站/兰州网站seo优化
  • 风中有朵雨做的云网站观看/bt种子磁力搜索引擎
  • 做旅游网站的产品经理如何/一键seo提交收录
  • 网站开发后端/网络营销sem培训
  • 建设网站需要会什么/鱼头seo软件
  • 医疗网站建设方案/代刷网站推广