基于固件库的RT-THREAD移植

本文阐述了在嵌入式领域中使用RTOS如FreeRTOS的原因,包括简化编程复杂度和提升职业发展。详细介绍了RT-Thread的移植过程,涉及准备工作、文件结构、系统定时器配置以及FinSH组件的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要使用操作系统

当我们进入嵌入式这个领域的时候, 往往首先接触的都是单片机编程, 单片机编程又首选 51 单片机来入门。 这里面说的单片机编程通常都是指裸机编程,即不加入任何 RTOS(Real Time Operation System 实时操作系统) 的程序。 常用的 RTOS 有国外的 FreeRTOS、μC/OS、 RTX 和国内的 RT-Thread、 Huawei LiteOS 和 AliOS-Things 等, 其中尤以国外开源且免费的 FreeRTOS 的市场占有率最高。
在裸机系统中,所有的程序基本都是自己写的, 所有的操作都是在一个无限的大循环里面实现。现实生活中的很多中小型的电子产品用的都是裸机系统, 而且也能够满足需求。但是为什么还要学习 RTOS 编程,偏偏还要整个操作系统进来。一是项目需要,随着产品要实现的功能越来越多,单纯的裸机系统已经不能够完美地解决问题,反而会使编程变得更加复杂,如果想降低编程的难度, 我们可以考虑引入 RTOS 实现多线程管理, 这是使用RTOS 的最大优势。二是学习的需要,必须学习更高级的东西,实现更好的职业规划,为将来走向人生巅峰迎娶白富美做准备,而不是一味的在裸机编程上面死磕。作为一个合格的嵌入式软件工程师,学习是永远不能停歇的事,时刻都得为将来准备。书到用时方恨少,我希望机会来临时你不要有这种感觉。

RT_thread的移植

准备工作:
1.准备一个工程(LED灯,按键,USART,系统定时器等驱动)
在这里插入图片描述

2.准备RT_thread的源码
在这里插入图片描述

解压过后的源码:
在这里插入图片描述

bsp--文件保存的板级支持包,支持不同的芯片
components--包含了一些组件信息 finsh--用于调试打印,在终端上显示调试信息(使用到底层的串口资源)
include--包含的都是头文件
libcpu--和底层硬件相关的库函数
src--内核源码

1.将压缩包中的内容全部复制到工程中
在这里插入图片描述

复制到如下位置(以下是自己准备的裸机代码位置):
在这里插入图片描述

修改名字3.0.3为rt_thread
在这里插入图片描述

复制如下文件到工程中的user目录中:
在这里插入图片描述
在这里插入图片描述

打开工程添加分组:
在这里插入图片描述

rtt_src添加的的是系统中SRC文件中的内容:
在这里插入图片描述

添加rtt_port分组,:
在这里插入图片描述

在这里插入图片描述
添加头文件:
在这里插入图片描述

编译代码,编译完成之后,修改错误:

..\User\rtconfig.h(6): error:  #5: cannot open source input file "RTE_Components.h": 
No such file or directory

在这里插入图片描述

注释掉此头文件(如果不能修改,查看文件属性,进行修改)
在这里插入图片描述

重复定义:

.\Objects\BH-F103.axf: Error: 
L6200E: Symbol HardFault_Handler multiply defined (by context_rvds.o and 
stm32f10x_it.o).
.\Objects\BH-F103.axf: Error: 
L6200E: Symbol PendSV_Handler multiply defined (by context_rvds.o and stm32f10x_it.o).
.\Objects\BH-F103.axf: Error: 
L6200E: Symbol SysTick_Handler multiply defined (by board.o and delay.o).

SysTick_Handler:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

rtconfig.h文件的修改:

修改优先级和系统定时器
在这里插入图片描述

修改栈区空间:
在这里插入图片描述

打开信号量和事件、互斥
在这里插入图片描述

使能堆区:
在这里插入图片描述

修改board.c文件
此文件中操作系统和底层硬件的链接部分,比如系统定时器
需要先将board.c文件添加到rtt_src分组
首先我们先来看内核中的系统定时器地址:
core_cm3.h
SysTick_BASE 地址–0xe000e010
在这里插入图片描述

再看OS中的,定时器地址:
在这里插入图片描述
在这里插入图片描述

void rt_hw_board_init()
包含了我们底层设备的驱动信息
修改:注释掉或者删除
在这里插入图片描述

添加初始化内容:
在这里插入图片描述
添加一个board.h
路径和Board.c一样
在这里插入图片描述
编译代码,查看有没有错误:
在这里插入图片描述

验证工程可用性

#include <rtthread.h>
#include <rthw.h>
#include "board.h"
void LED1_Pthread(void *para);
rt_thread_t led1_thread;
int main(void)
{
    //创建线程--LED
led1_thread=rt_thread_create("led1",LED1_Pthread,NULL,128,5,20);
    if(led1_thread !=RT_NULL)
    {
        rt_thread_startup(led1_thread);
    }
    while(1)
    {
        
    
    }
    return 0;
}


void LED1_Pthread(void *para)
{
    while(1)
    {
        LED1ON();
        rt_thread_delay(500);
        rt_kprintf("led1 running!!\r\n");//将打印信息输出到我们的串口助手中
        LED1OFF();
        rt_thread_delay(500);
    }
}

finsh组件:

FinSH 是 RT-Thread 的命令行组件,提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信。
用户在控制终端输入命令,控制终端通过串口、USB、网络等方式将命令传给设备里的 FinSH,FinSH 会读取设备输入命令,解析并自动扫描内部函数表,寻找对应函数名,执行函数后输出回应,回应通过原路返回,将结果显示在控制终端上。
使用以下函数的前提,必须配置好串口1的驱动:
rt_kprintf–修改此函数的打印方向:
在这里插入图片描述

void rt_hw_console_output(const char *str)
{    
    /* 进入临界段 */
    rt_enter_critical();

    /* 直到字符串结束 */
    while (*str!='\0')
    {
        /* 换行 */
        if (*str=='\n')
        {
            USART_SendData(USART1, '\r'); 
            while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        }

        USART_SendData(USART1, *str++);                 
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);    
    }    

    /* 退出临界段 */
    rt_exit_critical();
}
<think>好的,我现在需要帮助用户了解如何将STM32的标准库移植RT-Thread操作系统上。首先,我需要回顾用户提供的引用内容,这些引用都是关于STM32移植RT-Thread的教程和注意事项。用户明确提到了标准库的移植,所以我要重点参考引用[2]和引用[4],因为引用[2]的标题直接提到了标准库移植,而引用[4]虽然提到的是HAL库,但可能包含一些通用的步骤。 接下来,我需要整理移植的基本步骤。根据引用[2],移植过程大致分为准备工程、添加RT-Thread Nano源码、修改配置文件、编写应用代码、修改启动文件和编译调试。此外,引用[3]提到了启动线程调用的函数rt_thread_startup,这可能是在应用实例中需要使用的。引用[4]则介绍了Nano的特点,说明其轻量级,适合小型应用,这可能影响配置时的选项选择。 用户的问题是关于标准库的移植,所以需要确保步骤中的工程是基于标准库的,比如在准备工程时,用户需要有一个使用标准库的STM32裸机工程。然后,添加RT-Thread Nano源码时,可能需要从官网下载,如引用[1]提到的官网下载链接。修改配置文件如rtconfig.h,调整内核组件和时钟配置,这部分需要根据具体的MCU型号来设置,比如STM32F103的时钟频率。 在修改启动文件方面,引用[3]提到需要手动启动线程调度,所以在启动文件中可能需要添加相关的函数调用,比如在main函数初始化后创建线程并启动。同时,中断处理可能需要修改,比如SysTick和PendSV的中断服务函数替换为RT-Thread提供的,这部分需要参考引用[2]中的步骤。 在编写应用代码时,用户需要创建线程并定义线程入口函数,然后在main函数中初始化硬件并启动调度器。引用[3]中的rt_thread_startup函数就是用来启动线程的,需要确保正确调用。 最后,编译和调试阶段需要检查是否有错误,比如链接错误或者配置错误,并根据提示进行修正。可能的问题包括头文件路径不正确、系统时钟配置错误或者堆栈大小不足等。 现在需要将以上步骤结构化,用清晰的中文逐步说明,同时注意LaTeX格式的正确使用,比如行内公式用$...$,独立公式用$$...$$,但在这个问题中可能涉及较少的数学公式,更多是代码和步骤。需要确保引用标识正确添加,例如在提到官网下载时引用[^1],提到标准库移植步骤时引用[^2],线程启动时引用[^3],Nano特点时引用[^4]。 同时,生成的相关问题需要围绕移植过程中可能涉及的性能分析、优化方法、应用场景等,参考示例中的结构,比如如何优化RT-Thread的内存占用,或者RT-ThreadSTM32上的应用场景。 总结,回答需要分步骤详细说明移植过程,引用对应的参考资料,确保用户能够按照步骤操作,并解答可能的相关问题。</think>### STM32标准库移植RT-Thread操作系统方法 以下是基于STM32标准库移植RT-Thread Nano操作系统的详细步骤: --- #### **1. 准备工作** - **下载RT-Thread Nano源码** 从RT-Thread官网下载Nano版本源码包,解压后找到`rt-thread-nano`文件夹,包含内核源码和配置文件。 - **准备STM32标准库工程** 创建一个基于标准库的STM32裸机工程(如使用Keil或STM32CubeIDE)[^2]。 --- #### **2. 添加RT-Thread源码到工程** - **复制内核文件** 将Nano源码中的`include`、`libcpu`、`src`文件夹复制到工程目录下。 - **添加头文件路径** 在IDE中配置头文件路径,包含`include`和`libcpu/arm/cortex-m3`(根据MCU架构选择)。 - **添加源文件** 将`src/*.c`和`libcpu/arm/cortex-m3/context_gcc.S`(或`context_iar.S`)添加到工程。 --- #### **3. 修改配置文件** - **调整`rtconfig.h`** 在`include`文件夹中修改`rtconfig.h`,启用所需功能(如信号量、线程等),并配置系统时钟和堆栈大小: ```c #define RT_THREAD_PRIORITY_MAX 8 // 最大优先级 #define RT_TICK_PER_SECOND 1000 // 系统时钟频率 #define RT_USING_HEAP 1 // 启用动态内存管理 ``` - **适配系统时钟** 在`board.c`中实现`SysTick_Handler`,并初始化系统时钟(如使用外部晶振需配置PLL)。 --- #### **4. 修改启动文件** - **替换中断向量表** 在STM32标准库的启动文件(如`startup_stm32f10x_hd.s`)中,将`SysTick_Handler`和`PendSV_Handler`替换为RT-Thread的中断服务函数: ```c void SysTick_Handler(void) { rt_tick_increase(); } // 替换SysTick void PendSV_Handler(void) { /* RT-Thread上下文切换 */ } ``` - **初始化线程栈** 在启动文件中预留堆空间,例如修改`Heap_Size`为`0x800`(2KB)。 --- #### **5. 编写应用代码** - **创建线程** 在`main.c`中定义线程入口函数并启动线程调度: ```c static void led_thread_entry(void *param) { while(1) { GPIO_WriteBit(GPIOA, GPIO_Pin_0, !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)); rt_thread_delay(500); // 延时500ms } } int main(void) { // 硬件初始化(如GPIO、时钟) SystemInit(); GPIO_Init(...); // 创建线程并启动调度 rt_thread_t thread = rt_thread_create("led", led_thread_entry, RT_NULL, 512, 3, 10); rt_thread_startup(thread); // 启动线程 rt_system_scheduler_start(); // 启动调度器 } ``` --- #### **6. 编译调试** - **解决常见问题** - **内存不足**:增大`Heap_Size`或优化线程栈大小。 - **中断冲突**:检查是否遗漏中断服务函数的重定向。 - **时钟配置错误**:确认`SystemCoreClock``RT_TICK_PER_SECOND`匹配[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值