一、移植RT-Thread准备

  1. RT-Thread源码

    源码版本和下载方式,可以参考RT-Thread移植入门学习

  2. keil软件

  3. STM32工程项目模板

    因为每一厂家提供的库文件可能有一些区别,在移植时可能会出现各种不同的问题,对于刚了解RT-Thread的小伙伴不友好,所以我已经将之前创建好的项目模板放在百度网盘了,当然也可以参考STM32新建模板之库文件,百度的下载连接是:https://pan.baidu.com/s/1_H3l4Dy5aZHfZ_FirBjgtA ,提取码是:vbzt

  4. STM32F103C8T6开发版

    想要购买通关开发版的我也提供了卖家的连接,需要的小伙伴可以参考STM32零基础入门教程

二、RT-Thread 帮助文档

这里我移植的是标准版,当然需要移植的组件也是很多的,我们从内核开始移植,然后在进行外设的移植。学习RT-Thread 过程中有什么不明白的可以参考官方提供的帮助文档。

RT-Thread标准版文档:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/basic/basic?id=rt-thread-内核配置示例

移植RT-Thread的内核有两种方法,一种是通过keil提供的插件进行一起,一种是通过下载官方的源码进行移植,这里主要是了解通过源码的方式进行移植,这样在后面进行外设的移植时比较方便。

三、使用keil提供的工具进行移植

  1. 打开模板工程

  2. 通过keil下载RT-Thread内核接口

  3. 添加RT-Thread

  4. 添加完成后项目工程中会增加一个RTOS路径

  5. 编译,编译完成后会发现两个错误



    注意:这里主要的错误是在board.c文件中,声明了SystemCoreClockUpdate(void)方法和SystemCoreClock变量,但是没有对进进行定义导致的错误。

  6. 函数SystemCoreClockUpdate()



    这个函数主要是用于获取SystemCoreClock 定时器和处理器的频率,这一我们只是想测试一下移植的效果我们可以不用对其进行实现,我们会在下次笔记中进行分析。当然有在system_stm32fqox.c文件中已经实现了,这里就不会出现这样的错误,现在的解决办法比较简单,在文件最后定义一下这个函数即可。

  7. SystemCoreClock变量

    SystemCoreClock是当前系统时钟评率,并且是通过函数SystemCoreClockUpdate()中获取的,这里我们也不用过多了解,因为不同的库文件对系统时钟频率的命名是不一样的,比如我现在使用库文件的命名如下图所示:



    从图中可知,SystemFrequency的时钟频率是通过变量SYSCLK_FREQ_72MHz的赋值,所有我们只需要知道当前系统的频率赋值给SystemCoreClock变量即可。

  • 解决办法

    • 在board.c文件中引入头文件stm32f10x.h

    • 在函数rt_hw_board_init()中定义SystemCoreClock变量并赋值。

  1. 开启堆内存



    打开的方式比较简单,只需要在rtconfig.h文件中取消RT_USING_HEAP宏的注释即可

  2. 在次编译,这次编译即便会发现没有错误了,其中的警告我们先忽视。

  3. 编写主程序,在线程中进行led灯闪烁,main.c文件如下所示


#include "stm32f10x.h"
#include "led.h"
#include <rtthread.h> int main(void)
{ LED_GPIO_Config(); while (1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
rt_thread_delay(1000); // 延时1000 ms
GPIO_SetBits(GPIOB, GPIO_Pin_12 );
rt_thread_delay(1000); // 延时1000 ms
}
}

到这里我们便可以简单的使用RT-Thread的延时函数进行led的闪烁试验了。

四、通过官方源码移植

  1. 在模板工程中创建RT_Thread、RT_Thread/kernel、board文件

  2. 将源码路径下的include和src文件拷贝到创建的RT_Thread/kernel文件中

  3. 将路径libcpu\arm中的cortex-m3文件拷贝到创建的RT_Thread文件中



    注意:这里拷贝的是项目架构文件,因为我这里使用的是M3的芯片,小伙们需要根据自己的芯片类型拷贝相应的文件

  4. 在board文件中创建board.c和rtconfig.h文件

  5. 添加源码到工程组文件

  6. board.c文件,相信这个文件已经不陌生了,没错我们将上一流程更改的内容拷贝过来

/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-07-24 Tanek the first version
* 2018-11-12 Ernest Chen modify copyright
*/ #include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#include "stm32f10x.h" #define _SCB_BASE (0xE000E010UL)
#define _SYSTICK_CTRL (*(rt_uint32_t *)(_SCB_BASE + 0x0))
#define _SYSTICK_LOAD (*(rt_uint32_t *)(_SCB_BASE + 0x4))
#define _SYSTICK_VAL (*(rt_uint32_t *)(_SCB_BASE + 0x8))
#define _SYSTICK_CALIB (*(rt_uint32_t *)(_SCB_BASE + 0xC))
#define _SYSTICK_PRI (*(rt_uint8_t *)(0xE000ED23UL)) // Updates the variable SystemCoreClock and must be called
// whenever the core clock is changed during program execution.
extern void SystemCoreClockUpdate(void); // Holds the system core clock, which is the system clock
// frequency supplied to the SysTick timer and the processor
// core clock.
extern uint32_t SystemCoreClock; static uint32_t _SysTick_Config(rt_uint32_t ticks)
{
if ((ticks - 1) > 0xFFFFFF)
{
return 1;
} _SYSTICK_LOAD = ticks - 1;
_SYSTICK_PRI = 0xFF;
_SYSTICK_VAL = 0;
_SYSTICK_CTRL = 0x07; return 0;
} #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 1024
static uint32_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{
return rt_heap;
} RT_WEAK void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#endif /**
* This function will initial your board.
*/
void rt_hw_board_init()
{
uint32_t SystemCoreClock = 72000000; /* 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
} void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter(); rt_tick_increase(); /* leave interrupt */
rt_interrupt_leave();
} void SystemCoreClockUpdate(void)
{ }
  1. 拷贝rtconfig.h文件,同样是将上一流程中更改的内容拷贝过来
/* RT-Thread config file */

#ifndef __RTTHREAD_CFG_H__
#define __RTTHREAD_CFG_H__ #if defined(__CC_ARM) || defined(__CLANG_ARM)
#include "RTE_Components.h" #if defined(RTE_USING_FINSH)
#define RT_USING_FINSH
#endif //RTE_USING_FINSH #endif //(__CC_ARM) || (__CLANG_ARM) // <<< Use Configuration Wizard in Context Menu >>>
// <h>Basic Configuration
// <o>Maximal level of thread priority <8-256>
// <i>Default: 32
#define RT_THREAD_PRIORITY_MAX 8
// <o>OS tick per second
// <i>Default: 1000 (1ms)
#define RT_TICK_PER_SECOND 1000
// <o>Alignment size for CPU architecture data access
// <i>Default: 4
#define RT_ALIGN_SIZE 4
// <o>the max length of object name<2-16>
// <i>Default: 8
#define RT_NAME_MAX 8
// <c1>Using RT-Thread components initialization
// <i>Using RT-Thread components initialization
#define RT_USING_COMPONENTS_INIT
// </c> #define RT_USING_USER_MAIN // <o>the stack size of main thread<1-4086>
// <i>Default: 512
#define RT_MAIN_THREAD_STACK_SIZE 256 // </h> // <h>Debug Configuration
// <c1>enable kernel debug configuration
// <i>Default: enable kernel debug configuration
//#define RT_DEBUG
// </c>
// <o>enable components initialization debug configuration<0-1>
// <i>Default: 0
#define RT_DEBUG_INIT 0
// <c1>thread stack over flow detect
// <i> Diable Thread stack over flow detect
//#define RT_USING_OVERFLOW_CHECK
// </c>
// </h> // <h>Hook Configuration
// <c1>using hook
// <i>using hook
//#define RT_USING_HOOK
// </c>
// <c1>using idle hook
// <i>using idle hook
//#define RT_USING_IDLE_HOOK
// </c>
// </h> // <e>Software timers Configuration
// <i> Enables user timers
#define RT_USING_TIMER_SOFT 0
#if RT_USING_TIMER_SOFT == 0
#undef RT_USING_TIMER_SOFT
#endif
// <o>The priority level of timer thread <0-31>
// <i>Default: 4
#define RT_TIMER_THREAD_PRIO 4
// <o>The stack size of timer thread <0-8192>
// <i>Default: 512
#define RT_TIMER_THREAD_STACK_SIZE 512
// </e> // <h>IPC(Inter-process communication) Configuration
// <c1>Using Semaphore
// <i>Using Semaphore
#define RT_USING_SEMAPHORE
// </c>
// <c1>Using Mutex
// <i>Using Mutex
//#define RT_USING_MUTEX
// </c>
// <c1>Using Event
// <i>Using Event
//#define RT_USING_EVENT
// </c>
// <c1>Using MailBox
// <i>Using MailBox
#define RT_USING_MAILBOX
// </c>
// <c1>Using Message Queue
// <i>Using Message Queue
//#define RT_USING_MESSAGEQUEUE
// </c>
// </h> // <h>Memory Management Configuration
// <c1>Dynamic Heap Management
// <i>Dynamic Heap Management
#define RT_USING_HEAP
// </c>
// <c1>using small memory
// <i>using small memory
#define RT_USING_SMALL_MEM
// </c>
// <c1>using tiny size of memory
// <i>using tiny size of memory
//#define RT_USING_TINY_SIZE
// </c>
// </h> // <h>Console Configuration
// <c1>Using console
// <i>Using console
#define RT_USING_CONSOLE
// </c>
// <o>the buffer size of console <1-1024>
// <i>the buffer size of console
// <i>Default: 128 (128Byte)
#define RT_CONSOLEBUF_SIZE 128
// </h> #if defined(RT_USING_FINSH)
#define FINSH_USING_MSH
#define FINSH_USING_MSH_ONLY
// <h>Finsh Configuration
// <o>the priority of finsh thread <1-7>
// <i>the priority of finsh thread
// <i>Default: 6
#define __FINSH_THREAD_PRIORITY 5
#define FINSH_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 8 * __FINSH_THREAD_PRIORITY + 1)
// <o>the stack of finsh thread <1-4096>
// <i>the stack of finsh thread
// <i>Default: 4096 (4096Byte)
#define FINSH_THREAD_STACK_SIZE 512
// <o>the history lines of finsh thread <1-32>
// <i>the history lines of finsh thread
// <i>Default: 5
#define FINSH_HISTORY_LINES 1 #define FINSH_USING_SYMTAB
// </h>
#endif // <<< end of configuration section >>> #endif
  1. 编译,这是会发现找不到RTE_Components.h文件



    因为这个是之前keil软件中的头文件,编译的时候会自动生成,这里我们不需要,直接删除这个引用即可。

  2. main.c文件


#include "stm32f10x.h"
#include "led.h"
#include <rtthread.h> int main(void)
{ LED_GPIO_Config(); while (1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
rt_thread_delay(1000); // 延时1000 ms
GPIO_SetBits(GPIOB, GPIO_Pin_12 );
rt_thread_delay(1000); // 延时1000 ms
}
}

五、文件保护

防止在开发中不小心更改到内核文件,导致新的错误产生,所以我们需要进行文件保护。



处理办法也比较简单,在项目文件中把需要保护的文件改为只读即可





设置为只读模式后,在项目文件上就可以看到一把钥匙的存在,这样就可以避免在更改程序时,意外改动导致新的错误产生,如下图所示:

到此移植RT-Thread的内核也算基本完成了,当然还存在一些问题,接下来只需要哦边学习边修改即可,感兴趣的小伙伴可以看我之后的文章,哪里写得不好望小伙本们指出。

六、常见问题

  1. HardFault_Handler、PendSV_Handler、SysTick_Handler三个函数重复定义

  • 解决办法,这个问题是因为在工程中导入了stm32f10x_it.c文件,而这个文件主要是提供了一些模板,这里我们不需要,所以解决方法有两种,

    • 方式一: 直接将stm32f10x_it.c文件重项目中删除即可。
    • 方式二: 在stm32f10x_it.c文件中将重复定义的函数屏蔽即可。

参考文献

stm32 移植 rt-thread:https://blog.csdn.net/qq_36958104/article/details/111604665

RT-Thread移植到stm32的更多相关文章

  1. Basic脚本解释器移植到STM32

    本文来自http://blog.csdn.net/hellogv/ .引用必须注明出处! 上次讲了LUA移植到STM32.这次讲讲Basic脚本解释器移植到STM32. 在STM32上跑Basic脚本 ...

  2. FreeRTOS移植到STM32上的移植过程

    所有的单片机都是顺序执行的,而对于多任务而言就显得力不从心了,虽然在一些小项目中可以通过定时器来实现,但这种实现方式没有实时性,一旦任务需要在规定时间内做出响应,那只能通过实时操作系统来完成了.在很多 ...

  3. 基于Linux的kfifo移植到STM32(支持os的互斥访问)

    基于Linux的kfifo移植到STM32(支持os的互斥访问) 关于kfifo kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现:它提供一个 ...

  4. RT Thread 通过ENV来配置SFUD,操作SPI Flash

    本实验基于正点原子stm32f4探索者板子 请移步我的RT Thread论坛帖子. https://www.rt-thread.org/qa/forum.php?mod=viewthread& ...

  5. HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验

    HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验 硬件平台 基于正点原子战舰V3开发板 MCU:STM32F103ZET6 片上SRAM大小:64KBytes 片上FLASH大小 ...

  6. STM32 + RT Thread OS 学习笔记[二]

    串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1.   目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...

  7. STM32 + RT Thread OS 串口通讯

    1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因 ...

  8. STM32 + RT Thread OS 学习笔记[三]

    RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...

  9. STM32 + RT Thread OS 学习笔记[四]

    1.  补注 a)      硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...

随机推荐

  1. HTML5 head标签meta标签、title的功能

    <!DOCTYPE html> <!-- 解释器--> <html lang="en"> <head> <!--meta标签中 ...

  2. 痞子衡嵌入式:揭秘i.MXRT1170上用J-Link连接复位后PC总是停在0x223104的原因

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上安全调试策略实现对JLink调试的影响. 痞子衡之前写过一篇旧文 <i.MXRT600的ISP模式下用J-L ...

  3. SpringBoot简单整合分布式任务调度平台(XXL-JOB)

    官方文档:https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%8 ...

  4. SpringBoot项目给静态变量static注入@Value

    @value不能直接注入值给静态属性,spring 不允许/不支持把值注入到静态变量中:spring支持set方法注入,我们可以利用非静态setter 方法注入静态变量 @Component publ ...

  5. xcode使用spdlog(1.7)总结

    !!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 注意️ 请选择对c++11支持完善的编译器, 因为spdlog一直更新. 本文演示环境: m ...

  6. 【LeetCode】389. Find the Difference 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:字典统计次数 方法二:异或 方法三:排序 日 ...

  7. 【LeetCode】731. My Calendar II 解题报告(Python)

    [LeetCode]731. My Calendar II 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题 ...

  8. King's Order(hdu5642)

    King's Order  Accepts: 381  Submissions: 1361  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: ...

  9. Codeforces 872B:Maximum of Maximums of Minimums(思维)

    B. Maximum of Maximums of Minimums You are given an array a1, a2, ..., an consisting of n integers, ...

  10. 去除input标签点击时的默认样式

    去除input标签点击时的默认样式的方法 outline:none; //去除点击时的边框 border : none; //去除input框的边框