HAL库+CubeMX freeRTOS闪烁LED


1、概述

操作系统 (Operating System) 的本质是一个帮助用户进行功能管理的软件。操作系统运行在硬件之上,为其他工作的软件执行资源分配等管理工作。

一般称呼不使用操作系统的单片机开发方式为“裸机开发”,当进行裸机开发时,需要自己设计循环,中断,定时等功能来控制各个任务的执行顺序。而使用操作系统进行开发时,只需要创建任务,操作系统会自动按照一些特定的机制自动进行任务的运行和切换。

除了任务管理之外,操作系统还可以提供许多功能,比如各个任务之间的通信,同步,任务的堆栈管理,控制任务对重要资源的互斥访问等。

由于单片机的资源比较少,显然无法运行如Windows,MacOS等计算机操作系统,一般在单片机上运行的是经过专门设计的嵌入式实时操作系统 (RTOS)。

freeRTOS就是其中一种,其他比较常见的嵌入式实时操作系统还有uCOSⅡ,RTThread等。freeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行,并且有着庞大的社区和生态。

2、cubeMX中freeRTOS的配置

  1. 首先打开Middleware标签,选中其中的FREERTOS选项,进入FREERTOS的配置页面。
    在这里插入图片描述
  2. 在Mode页面下,选择Interface的版本,这里选择CMSIS_V1。CMSIS是由Keil提供的一套特殊的函数接口,他对freeRTOS的功能函数进行了封装,使其变得更加易用,在使用freeRTOS时,不需要再去直接调用freeRTOS的函数,只需要调用CMSIS为我们提供的函数即可,目前CMSIS有V1和V2两个版本。
  3. 通过以上方式就可以完成freeRTOS的开启,在生成代码之后,freeRTOS会自动被移植到工程中。接着在Configuration页面下进行freeRTOS的配置
    在页面中,可以配置freeRTOS的一些重要的属性,包括是否支持抢占机制,freeRTOS的系统时钟速率,最大优先级数量,最小任务栈尺寸,最大任务名称长度等。针对一些比较重要的配置列表如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3、cubeMX中创建任务

首先在freeRTOS的配置页面中的Configuration下,选中Tasks and Queues标签页,存在一个已经创建的默认任务为“defaultTask”,点击进入配置选项修改为如下图所示。
在这里插入图片描述
如果需要增加一个新任务,点击Add,就可以创建一个新的任务。
在这里插入图片描述
在弹出的页面中,可以配置任务名称,优先级,栈大小,入口函数等。各个参数的具体功能见下表:
在这里插入图片描述
设置完毕之后点击OK,就可以看到列表中多出了自己创建的任务。
在这里插入图片描述
在freertos.c中也可以找到修改的默认任务函数。

__weak void red_led_task(void const * argument) { 
	/* USER CODE BEGIN red_led_task */ 
	/* Infinite loop */ 
		for(;;) { 
		osDelay(1); 
	} 
	/* USER CODE END red_led_task */ 
}

由于选择了通过__weak修饰符创建一个弱函数,可以再在别处实现该任务函数。程序执行时会自动寻找到这个另外实现的任务函数。

void red_led_task(void const * argument) { 
	while(1) { 
		HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
		osDelay(500); 
		HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); 
		osDelay(500); 
		HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); 
		osDelay(500); 
	} 
}

由于新建了任务“LED_GREEN”,并且设置为As external,故而需要再在别处实现任务函数。程序执行时会自动寻找到实现的任务函数。

void green_led_task(void const * argument){ 
	while(1) { 
		HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
		osDelay(500); 
		HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET); 
		osDelay(500); 
		HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET); 
		osDelay(500); 
	} 
}

4、程序中创建任务

打开freertos.c文件,在MX_FREERTOS_Init中,找到创建两个进程的代码,分别是LED_RED和LED_GREEN。可以看到要创建任务时,只需要调用osThreadDef和osThreadCreate即可,创建“LED_BLUE”任务。

/* Create the thread(s) */ 
/* definition and creation of LED_RED */ 
osThreadDef(LED_RED, red_led_task, osPriorityNormal, 0, 128); 
LED_REDHandle = osThreadCreate(osThread(LED_RED), NULL); 

/* definition and creation of LED_GREEN */ 
osThreadDef(LED_GREEN, green_led_task, osPriorityHigh, 0, 128); 
LED_GREENHandle = osThreadCreate(osThread(LED_GREEN), NULL); 

/* USER CODE BEGIN RTOS_THREADS */ 
/* add threads, ... */ 
osThreadDef(LED_BLUE, blue_led_task, osPriorityHigh, 0, 128); 
led_blue_handle = osThreadCreate(osThread(LED_BLUE), NULL);
/* USER CODE END RTOS_THREADS */

4.1、osThreadDef

首先介绍osThreadDef,实际上这不是一个函数,而是一个由CMSIS提供的宏定义,用于对要创建的任务进行设置

#define osThreadDef(name, thread, priority, instances, stacksz) \ 
extern const osThreadDef_t os_thread_def_##name

在这里插入图片描述

4.2、osThreadCreate函数

接着通过CMSIS提供的osThreadCreate函数来创建任务

osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);

在这里插入图片描述
通过以上两步,一个任务就成功创建了,创建一个名称和osThreadDef中的thread参数一致的函数,操作系统会自动找到该函数并将其作为一个进程来执行。比如声明thread为blue_led_task,则还需要执行函数void blue_led_task(void const * argument),while(1)循环中的内容为用户自己的代码。

5、程序流程图

在这里插入图片描述

Copy From 大疆学习文档

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值