【STM32 FreeRTOS】FreeRTOS的移植

其实这篇文章不侧重移植,因为我们会使用CubeMX配置,那样会自动移植FreeRTOS。

关于FreeRTOS,可以参考官网:FreeRTOS - Quick start guide

在这里插入图片描述
当我们在CubeMX中配置了CMSIS_V2后尝试编译的时候会有一个弹窗。
第一个问题就是强烈建议不要使用Systick作为HAL的时基。
在这里插入图片描述
默认情况下,我们会选用Systick(滴答定时器)作为HAL的时基,这个时基有什么用呢?我们看HAL库源码就会发现,在配置时钟树函数中会调用滴答计时器的初始化函数,初始化函数中配置的是1ms一个中断,并且在中断服务函数中在累加一个全局变量,这个变量就是在进行中断计数。

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}

HAL_Delay()函数就是在此基础上实现的,他是一种轮询计数的方式实现delay。

__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while((HAL_GetTick() - tickstart) < wait)
  {
  }
}

或者在封装的外设驱动函数中的超时判断,也是使用的Systick。那么为什么加入RTOS后,就不建议我们使用了呢?
RTOS会强制将Systick的中断优先级设置为最低,RTOS还会使用Systick中断服务函数进行任务调度,如果这个时候有一个中断优先级较高(高于Systick中断)的中断服务函数中调用了HAL_Delay(),那么意味着会卡死,因为HAL_Delay()函数中也会等待Systick中断进行计算,但是现在还在执行更高优先级的中断。所以这样是有风险的。。。
但是其实我们是不建议在中断服务函数中进行延迟操作的。但是出于软件健壮的考虑,我们的HAL时基可以使用其他定时器来实现。
在这里插入图片描述
我们现在使用TIM4来作为时基。同样的,在时钟树配置后就会初始化TIM4作为时基。

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM4 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM4) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

然后,我们也会发现SysTick_Handler函数在cmsis_os2.c文件中定义了。

/*
  SysTick handler implementation that also clears overflow flag.
*/
void SysTick_Handler (void) {
  /* Clear overflow flag */
  SysTick->CTRL;

  if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
    /* Call tick handler */
    xPortSysTickHandler();
  }
}

会在最开始的HAL_Init函数中初始化Systick。最后,还有三点需要关注一下。
一个就是在main函数中,osKernelStart函数下面的注释。

  /* Init scheduler */
  osKernelInitialize();

  /* Call init function for freertos objects (in freertos.c) */
  MX_FREERTOS_Init();

  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */

表示不会执行osKernelStart函数后面的代码,因为控制器被调度器拿走了。
二是在vTaskStartScheduler函数中,默认会创建一个任务,叫空闲任务,他的优先级是配置为最低的0。这个空闲任务是干嘛用的呢?我们看源码注释:

/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
	SCHEDULER IS STARTED. **/

	/* In case a task that has a secure context deletes itself, in which case
	the idle task is responsible for deleting the task's secure context, if
	any. */

在某些任务自己删除自己后,空闲任务可以帮忙释放堆栈空间和TCB。
三是在CubeMX中添加FreeRTOS后,会有一个文件夹CMSIS_RTOS_V2,这是MX对FreeRTOS接口的再一次封装,一般是os开头的函数名或者变量名。当然,我们也可以直接使用FreeRTOS的原生接口。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值