基于FreeRTOS的STM32多任务程序

一、材料准备

STM32指南者开发板(包括USB串口转换线、所需软件及驱动
在这里插入图片描述

二、 FreeRTOS移植

FreeRTOS是什么

我们看一下FreeRTOS的名字,可以分为两部分:Free和RTOS, Free 就是免费的、自由的、不受约束的意思,RTOS全称是Real Time Operating System,中文名就是实时操作系统。可以看出FreeROTS就是一个免费的RTOS类系统。这里要注意,RTOS不是指某-一个确定的系统,而是指一类系统。比如UCOS,FreeRTOS, RTX,RT-Thread 等这些都是RTOS类操作系统。

操作系统允许多个任务同时运行,这个叫做多任务,实际上,一个处理器核心在某一时刻只能运行一个任务。操作系统中任务调度器的责任就是决定在某一时刻究竟运行哪个任务,任务调度在各个任务之间的切换非常快!这就给人们造成了同一时刻有多个任务同时运行的错觉。操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分配同样的运行时间,时间到了就轮到下一个任务,Unix 操作系统就是这样的。RTOS 的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的,实时环境中要求操作系统必须对某一个事件做出实时的响应,因此系统任务调度器的行为必须是可预测的。像FreeRTOS这种传统的RTOS类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根据此优先级来决定下一刻应该运行哪个任务。

FreeRTOS是RTOS系统的- -种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,当然了,FreeRTOS不仅局限于在微控制器中使用。但从文件数量上来看FreeRTOS 要比UCOSII和UCOSIII小的多。

FreeRTOS移植到STM32上(MDK开发环境)

嫌麻烦跳到 程序编写 模块,不需要手动移植

1.下载FreeRTOS源代码

官网下载或者向你万能的老师要

2.前期准备

把FreeRTOS\Source\portable\RVDS目录下的ARM_CM3文件夹拷贝到FreeRTOS\Source\portable\Keil目录下
在这里插入图片描述
在这里插入图片描述
把FreeRTOS\Demo\CORTEX_STM32F103_IAR的FreeRTOSConfig.h文件拷贝到FreeRTOS\Source下
在这里插入图片描述
在这里插入图片描述
对源文件的处理就完成了

3.手动移植RreeRTOS

建立或打开一个MDK工程
在这里插入图片描述
添加FreeRTOS源文件
在这里插入图片描述

源文件清单路径如下:
FreeRTOS\Source\list.c
FreeRTOS\Source\tasks.c
FreeRTOS\Source\portable\MemMang\heap_4.c
FreeRTOS\Source\FreeRTOSConfig.h
FreeRTOS\Source\event_groups.c
FreeRTOS\Source\croutine.c
FreeRTOS\Source\queue.c
FreeRTOS\Source\timers.c
FreeRTOS\Source\portable\Keil\ARM_CM3\port.c

添加头文件路径如下
在这里插入图片描述
修改stm32f10x_it.c文件:

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
void SVC_Handler(void)
{
}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
void PendSV_Handler(void)
{
}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
}

在这里插入图片描述
此时FreeRTOS的手动移植基本完成,可以编写多任务程序了。

程序的编写

任务要求: 在STM32下完成一个基于FreeRTOS的多任务程序,执行2个周期性task,task1,每间隔500ms闪烁(变化)一次LED;task2,每间隔2000ms,向串口发送一次指令数据“helloworld!";

由于手动移植操作较为麻烦,而且很容易出现各种疑难杂症,因此我采用在野火官网下载已经移植好的系统,看看 RTOS里面的 API 使用说明,然后调用这些 API 实现自己想要的功能。
这种方式简单粗暴,不用关心底层的移植,这是最简单快速的入门方法。
此方法各有利弊,如果是做产品,好处是可以快速的实现功能,将产品推向市场,赢得先机。
弊端是当程序出现问题的时候,因对这个RTOS 不够了解,会导致调试困难,焦头烂额,一筹莫展。如果是学习,那么只会简单的调用 API,那是不可取的,我们应该深入的学习其中一款 RTOS。

如想深入了解的请自行移植并解决那些疑难杂症

程序如下
main.c

#include "FreeRTOS.h"
#include "task.h"
#include "bsp_led.h"
#include "bsp_usart.h"
static TaskHandle_t AppTaskCreate_Handle = NULL;
static TaskHandle_t LED1_Task_Handle = NULL;
static TaskHandle_t LED2_Task_Handle = NULL;
static void AppTaskCreate(void);

static void LED1_Task(void* pvParameters);
static void LED2_Task(void* pvParameters);

static void BSP_Init(void);
int main(void)
{	
  BaseType_t xReturn = pdPASS;
  BSP_Init();

  xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  
                        (const char*    )"AppTaskCreate",
                        (uint16_t       )512, 
                        (void*          )NULL,
                        (UBaseType_t    )1, 
                        (TaskHandle_t*  )&AppTaskCreate_Handle);        
  if(pdPASS == xReturn)
    vTaskStartScheduler(); 
  else
    return -1;  
  
  while(1);     
}

static void AppTaskCreate(void)
{
  BaseType_t xReturn = pdPASS;
  
  taskENTER_CRITICAL();           
  xReturn = xTaskCreate((TaskFunction_t )LED1_Task, 
                        (const char*    )"LED1_Task",
                        (uint16_t       )512, 
                        (void*          )NULL,	
                        (UBaseType_t    )2,	  
                        (TaskHandle_t*  )&LED1_Task_Handle);
  if(pdPASS == xReturn)
    printf("´´½¨LED1_TaskÈÎÎñ³É¹¦!\r\n");
  xReturn = xTaskCreate((TaskFunction_t )LED2_Task, 
                        (const char*    )"LED2_Task",
                        (uint16_t       )512,  
                        (void*          )NULL,	
                        (UBaseType_t    )3,	    
                        (TaskHandle_t*  )&LED2_Task_Handle);
  if(pdPASS == xReturn)
    printf("´´½¨LED2_TaskÈÎÎñ³É¹¦!\r\n");
  
  vTaskDelete(AppTaskCreate_Handle); 
  
  taskEXIT_CRITICAL();          
}
static void LED1_Task(void* parameter)
{	
    while (1)
    {
        LED1_ON;
        vTaskDelay(500);  
        printf("LED1_Task Running,LED1_ON\r\n");
        
        LED1_OFF;     
        vTaskDelay(500); 	 		
        printf("LED1_Task Running,LED1_OFF\r\n");
    }
}
static void LED2_Task(void* parameter)
{	
    while (1)
    {

        vTaskDelay(2000);  
        printf("hello windows !! \r\n");
    }
}
static void BSP_Init(void)
{
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
	LED_GPIO_Config();
	USART_Config();
}

在这里插入图片描述
编译后烧录到stm32上

运行结果

这次采用的是stm32指南者开发板,用起来和核心板有些不同,主要是不需要ST-Link接口,转而使用串口进行程序的烧录,此时就需要下载一个串口驱动和串口工具软件,具体操作步骤移步 STM32串口通信

打开野火多功能调试助手,结果如下,运行成功
在这里插入图片描述
再来看看我们的板子现在如何
在这里插入图片描述
LED灯以500ms一次的频率闪烁,符合预期。

三、心得与参考

总结

开发板真好用嘻嘻嘻再见了核心板

参考

基于Ubuntu的嵌入式开发练习(十)FreeRTOS的移植和设计一个基本的多任务程序
keil下的FreeRtos多任务程序

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值