基于 CubeMX 移植 RT-Thread Nano完成多任务

一、RT-Thread Nano 简介

RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。
RT-Thread Nano 的软件框图:
在这里插入图片描述
支持架构:ARM:Cortex M0/ M3/ M4/ M7 等、RISC-V 及其他。

功能:线程管理、线程间同步与通信、时钟管理、中断管理、内存管理。

二、Nano 的特点

1.简单

1、下载简单

RT-Thread Nano 以软件包的方式集成在 Keil MDK 与 CubeMX 中,可以直接在软件中下载 Nano 软件包获取源码,获取方式详见 基于 Keil MDK 移植 RT-Thread Nano 与 基于 CubeMX 移植 RT-Thread Nano 。

同时也提供 下载 Nano 源码压缩包 的途径,方便在其他开发环境移植 RT-Thread Nano,如 基于 IAR 移植 RT-Thread Nano。

2、代码简单

与 RT-Thread 完整版不同的是,Nano 不含 Scons 构建系统,不需要 Kconfig 以及 Env 配置工具,也去除了完整版特有的 device 框架和组件,仅是一个纯净的内核。

3、移植简单

由于 Nano 的极简特性,使 Nano 的移植过程变得极为简单。添加 Nano 源码到工程,就已完成 90% 的移植工作。

在 Keil MDK 与 Cube MX 中还提供了 Nano 的软件包,可以一键下载加入到工程。另外,在 RT-Thread Studio 中可以基于 Nano 创建工程直接使用。以下是使用不同开发环境时,可以选择移植或使用 Nano 的方法:

在 RT-Thread Studio 上使用 RT-Thread Nano
基于 KEIL MDK 移植 RT-Thread Nano
基于 CubeMX 移植 RT-Thread Nano
基于 IAR 移植 RT-Thread Nano
移植 RT-Thread Nano 到 RISC-V
4、使用简单

RT-Thread Nano 在使用上也非常简单,带给开发者友好的开发体验。

易裁剪:Nano 的配置文件为 rtconfig.h,该文件中列出了内核中的所有宏定义,有些默认没有打开,如需使用,打开即可。具体的配置可见 Nano 版块的 RT-Thread Nano 配置 教程。
易添加 FinSH 组件:FinSH 组件 可以很方便的在 Nano 上进行移植,而不再依赖 device 框架,只需要对接两个必要的函数即可完成 FinSH 移植。
自选驱动库:可以使用厂商提供的固件驱动库,如 ST 的 STD 库、HAL 库、LL 库等,可以自行选择。
完善的文档:包含 内核基础、线程管理 (例程)、时钟管理 (例程)、线程间同步 (例程)、线程间通信 (例程)、内存管理 (例程)、中断管理,以及 Nano 版块的移植教程。

2.小巧

资源占用小:对 RAM 与 ROM 的开销非常小,在支持 semaphore 和 mailbox 特性,并运行两个线程 (main 线程 + idle 线程) 情况下,ROM 和 RAM 依然保持着极小的尺寸,RAM 占用约 1K 左右,ROM 占用 4K 左右。

Nano 资源占用情况举例:在运行两个线程 (main 线程 + idle 线程) 情况下,ROM 和 RAM 依然保持着极小的尺寸。以下是基于 Cortex M3 的 MDK 工程编译结果(优化等级 3)。

Total RO  Size (Code + RO Data)                 4000 (   3.91kB)
Total RW  Size (RW Data + ZI Data)              1168 (   1.14kB)
Total ROM Size (Code + RO Data + RW Data)       4092 (   4.00kB)

复制错误复制成功
注:如果需要丰富的组件、驱动以及软件包等功能,则建议使用 RT-Thread 完整版。

3.开源免费(Apache 2.0)

RT-Thread Nano 实时操作系统遵循 Apache 许可证 2.0 版本,实时操作系统内核及所有开源组件可以免费在商业产品中使用,不需要公布应用程序源码,没有潜在商业风险。

三、cubeMX添加RT-Thread操作系统组件

参考官方文档

四、项目创建

同样参考上面链接后面部分
我选择了两个引脚PC3,PB0以及USAER1作为我接下来要完成的三个任务,

任务引脚或串口时间
LED闪烁PC31s
LED闪烁PC02s
串口打印USART13s

PC3,PB0分别为LED闪烁任务间隔1s和2s,USART1为串口打印任务;
生成代码后需修改部分:

  1. 需要初始化USART1且需要修改USART2位USART1
    在这里插入图片描述

  2. 取消注释#include "finsh_config.h"的注释
    在这里插入图片描述

  3. 如果你设置了串口中断可能会报下面的错误
    在这里插入图片描述
    由于rtthread重写了部分中断服务函数,所以我们需要将stm32f0xx_it.c中部分函数设置为weak
    在这里插入图片描述

五、代码实现

# include "rtthread.h"
# include "stdio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
int fputc(int ch,FILE *f){
 uint8_t temp[1]={ch};
 HAL_UART_Transmit(&huart1,temp,1,2);
 return ch;
}
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
//任务线程
struct rt_thread led1_thread;
struct rt_thread led2_thread;
//任务栈
rt_uint8_t rt_led1_thread_stack[128];
rt_uint8_t rt_led2_thread_stack[128];
//任务函数
void led1_task_entry(void *parameter);
void led2_task_entry(void *parameter);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//初始化线程函数
void MX_RT_Thread_Init(void)
{
	//初始化LED线程
	/*
		静态线程对象
		线程名
		线程入口函数
		线程入口参数
		线程栈地址
		线程栈空间大小
		线程优先级
		线程时间片
		
	*/
	rt_thread_init(&led1_thread,"led1",led1_task_entry,RT_NULL,&rt_led1_thread_stack[0],sizeof(rt_led1_thread_stack),3,20);
	//开启线程调度
	rt_thread_startup(&led1_thread);
	rt_thread_init(&led2_thread,"led2",led2_task_entry,RT_NULL,&rt_led2_thread_stack[0],sizeof(rt_led2_thread_stack),3,20);
	//开启线程调度
	rt_thread_startup(&led2_thread);
}


//LED1任务
void led1_task_entry(void *parameter)
{
	//1000ms闪烁一次
	while(1)
	{
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
		rt_thread_delay(1000);
	}
}
//LED1任务
void led2_task_entry(void *parameter)
{
	//1000ms闪烁一次
	while(1)
	{
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
		rt_thread_delay(2000);
	}
}
//主任务
void MX_RT_Thread_Process(void)
{
	printf("Hello RT_Thread!!!\n");
	rt_thread_delay(3000);
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  MX_RT_Thread_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  MX_RT_Thread_Process();
  }
  /* USER CODE END 3 */
}

注意:这里重写了printf,编译的时候记得勾选Use microLIB,否则无法运行

六、效果

请添加图片描述
在这里插入图片描述

七、总结

RT-Thread与其他很多 RTOS 如 FreeRTOS、uC/OS 的主要区别之一是,它不仅仅是一个实时内核,还具备丰富的中间层组件
相比于裸机程序RTOS有以下优势
1.硬实时响应
基于优先级抢占的RTOS,根据任务的实时需求,执行优先调度。有严格时序限制的任务可以优先执行,提高应用程序对时间关键事件的响应。
2.系统性能最大化
针对大型的、复杂的嵌入式应用,使用一个事件驱动的RTOS,来替代基于轮询的超循环结构,可以生成一个更有效的设计,更小的存储占用,应用可以获得更多的处理器时间。
3.降低复杂度
RTOS允许应用划分为一个个小的自主运行的任务。任务执行自己的上下文中,不依赖其它任务或调度器。
4.高峰负载管理
RTOS提供了为管理系统高峰活动提供了一个有效的方法。更高的优先级分配给执行峰值负载活动的任务,确保他们在临界时间内访问处理器,在此期间,较低优先级的任务被延迟。
5.紧密集成的中间件
RTOS的模块化设计使得它可以很容易的增加中间件。中间件组件以任务和驱动的方式增加。他们使用RTOS提供的资源与其它任务通信。基于相应的事件被RTOS调度。
6.更大的开发团队
每个任务可以被认为是一个项目。通过RTOS提供的资源(队列、信号量等)来定义输入输出。将系统定义为一个个的任务,可以更容易的部署更多开发人员到一个项目。
7.易于调试和验证
系统划分为功能明确的任务,不依赖其它任务。在整个系统集成之前,可以很容易的调试和验证每个任务。
8.代码重用
RTOS系统中的模块化设计,鼓励将软件功能创建为独立的、验证过的任务。其独立性使得在其它设计中重用这些模块变得很简单。

八、参考

官方文档
https://blog.csdn.net/xt_v2012/article/details/93787061

STM32F103是意法半导体(STMicroelectronics)生产的一款32位嵌入式微控制器,具有高性能和低功耗的特点。RT-Thread Nano是RT-Thread实时操作系统的一个轻量级版本,适用于资源受限的嵌入式系统。 在将RT-Thread Nano移植STM32F103上之前,需要先了解RT-Thread Nano的架构和STM32F103的硬件特性。 首先,需要确保RT-Thread Nano的源代码和STM32F103的开发环境已经准备好。接着,根据STM32F103的芯片手册和引脚映射表,需要对RT-Thread Nano的硬件抽象层进行适配,确保操作系统可以正确地访问外设和断。 其次,需要根据STM32F103的内存和存储器大小来合理配置RT-Thread Nano的内存管理器和文件系统。可以根据实际需求对系统进行裁剪,移除不必要的模块和功能,以减小系统的内存占用和代码体积。 然后,需要配置STM32F103的系统时钟和断向量表,并在启动代码初始化硬件资源和系统任务。可以参考RT-Thread Nano的官方文档和示例代码,根据具体的硬件平台和应用需求进行相应的设置和调试。 最后,进行系统的编译、烧录和调试。可以使用STM32F103的开发工具链和调试器,对编译后的固件进行烧录和调试,确保系统能够正确地启动和运行。 总结来说,将RT-Thread Nano移植STM32F103上需要进行硬件适配、内存管理和系统配置等工作,最终通过编译、烧录和调试来验证移植的正确性。这样可以使得STM32F103可以运行使用RT-Thread Nano操作系统的应用程序,实现更灵活和可靠的嵌入式系统设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值