进阶HAL开发——第二集-FreeRTOS

大三了,在保研、考研、保研加分政策改变的焦虑中渡过了2021的前5个月。好久没有认真学东西了。不管了,先学点东西把手里的比赛做完,加不加分都随缘。

一、简介

FreeRTOS是一个迷你的实时操作系统内核。
作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程 等,可基本满足较小系统的需要。

二、理解

main初始化函数中多了两个函数:
①MX_FREERTOS_Init()
是hal库自动生成的freertos任务创建函数
②osKernelStart()
是开启任务调度

任务调度开启之后,就正式进入FreeRTOS系统接管领域,之后程序只会跑在中断任务函数中,这时候就可以对while(1)说再见了!

三、使用

3.1 移植FreeRTOS ---- 添加任务

在这里插入图片描述

【注意】基时建议选择TIM1
在这里插入图片描述

3.2 认识程序框架

1、Cude生成的Keil工程,架构从底往上依次是:内核、驱动层、硬件抽象层、应用层。
在这里插入图片描述
2、上三层跟裸机程序是一样的,主要增加了内核层
在这里插入图片描述

  • croutine.c : 协程相关
  • event_groups.c : 事件标志组相关
  • tasks.c: 任务控制块:描述任务属性的结构体,用于任务创建、挂起、恢复、调度
  • list.c: 列表和列表项,FreeRTOS的一种基础数据结构
  • queue.c : 队列相关
  • timers.c : 软件定时器相关
  • heap_4.c : 内存管理相关
  • port.c : 针对不同硬件平台的接口

3.3 阅读FreeRTOS.c与main.c

FreeRTOS.c

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/*--------创建 任务句柄【CubeMX 配置】----------*/
osThreadId defaultTaskHandle;
osThreadId myTask01Handle;
osThreadId myTask02Handle;

/*--------声明 任务处理函数【CubeMX 配置】----------*/
void StartDefaultTask(void const * argument);
void StartTask01(void const * argument);
void StartTask02(void const * argument);
/*--------声明 FREERTOS初始函数-------------------*/
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */


void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}

/*--------初始化函数实现----对每个任务配置----------*/
void MX_FREERTOS_Init(void)
{
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  osThreadDef(myTask01, StartTask01, osPriorityIdle, 0, 128);
  myTask01Handle = osThreadCreate(osThread(myTask01), NULL);

  osThreadDef(myTask02, StartTask02, osPriorityIdle, 0, 128);
  myTask02Handle = osThreadCreate(osThread(myTask02), NULL);
}

/*--------默认任务 实现----------*/
void StartDefaultTask(void const * argument)
{
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
}
void StartTask01(void const * argument)
{
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
}

运行到osDelay() 系统就会把cpu让出来,给别的任务(取决于优先级)

main.c

  MX_FREERTOS_Init();  //初始化RTOS
  osKernelStart();     //开启调度命令,接下来就全归RTOS调度

3.4 A任务删除B任务

在A任务处理函数加:vTaskDelete(TaskBHandle)

四、实例:

两个任务向同一个串口发送消息,频率分别为1s每次和5s每次

void Task1(void const * argument)
{
  /* USER CODE BEGIN Task1 */
  /* Infinite loop */
  for(;;)
  {
	uint8_t TxData[10]= "1111111111";
    HAL_UART_Transmit(&huart4,TxData,10,0xffff);
    osDelay(1000);
  }
void Task2(void const * argument)
{
  /* USER CODE BEGIN Task2 */
  /* Infinite loop */
  for(;;)
  {
	uint8_t TxData[10]= "2222222222";
    HAL_UART_Transmit(&huart4,TxData,10,0xffff);
    osDelay(5000);
  }
}
————————————————
版权声明:本文为CSDN博主「外来务工人员徐某」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33033059/article/details/106677140

五、总结

注意 任务与任务间的通讯:①申明外部变量extern ②任务通讯机制

注意 串口中断&任务优先级 串口中断最高
配置完成后,在任务处理函数 实现自己原本的 算法即可。

  • 8
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
刚开始接触这个STM32Cube+FreeRTOS的时候也是遇到这个问题,这个问题的原因是没有足够的内存分配给栈空间,以下是我的分析过程: 1.出现了调度器无法调度的问题,追查调度函数osKernelStart和vTaskStartScheduler发现错误出现在以下位置: xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); 也就是说创建IDLE任务时失败,使得xReturn 不等于 pdPASS,那么vTaskStartScheduler代码后续的: if(xRetern == pdPass) { ...... } 就不会执行,调度器就无法工作 2.继续跟踪读IDLE任务分配的代码,一直到函数xTaskGenericCreate,发现程序在这个地方出错: pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); if(pxNewTCB != NULL) { ...... } 最后会返回内存不足的错误,如下代码: xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; traceTASK_CREATE_FAILED(); 这个地方给任务分配TCB控制块和栈的内存空间,产生了失败 3.您可以继续跟踪prvAllocateTCBAndStack函数,看看内存可用空间是怎么定义的 4.我给出的具体方法是减小栈空间字节数或者其他内存节省办法 我将原来是128的栈空间修改成了64就可以成功运行3个任务了,但是我认为随着任务的增多还是会出现这个内存不足的问题,以下是创建任务的代码,供你参考: while(NULL == defaultTaskHandle) { osThreadDef(test_task, test_task, osPriorityNormal, 1, 64);//128); defaultTaskHandle = osThreadCreate(osThread(test_task), NULL); } while(NULL == uc1recv_TaskHandle) { osThreadDef(uc1recv_task, uc1recv_task, osPriorityHigh, 1, 64);//128); uc1recv_TaskHandle = osThreadCreate(osThread(uc1recv_task), NULL); } #if 1 while(NULL == uc2recv_TaskHandle) { osThreadDef(uc2recv_task, uc2recv_task, osPriorityAboveNormal, 1, 64);//128); uc2recv_TaskHandle = osThreadCreate(osThread(uc2recv_task), NULL); } #endif osKernelStart();

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值