性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

小麥大叔
認(rèn)證:普通會(huì)員
所在專題目錄 查看專題
基于CubeIDE快速整合FreeRTOS創(chuàng)建第一個(gè)任務(wù)
【FreeRTOS學(xué)習(xí)02】源碼結(jié)構(gòu)/數(shù)據(jù)類型/命名規(guī)則總結(jié)
【FreeRTOS學(xué)習(xí)03】Task Management 任務(wù)管理基本概念介紹
【FreeRTOS學(xué)習(xí)04】Queue Management 消息隊(duì)列使用詳解
【FreeRTOS學(xué)習(xí)05】深度解剖FreeRTOSConfig.h實(shí)現(xiàn)對系統(tǒng)的自定義剪裁
【FreeRTOS學(xué)習(xí)06】深度解剖中斷與任務(wù)之間同步的具體使用場景
作者動(dòng)態(tài) 更多
一款輕量級(jí)的開源GUI項(xiàng)目——SimpleGUI,可以完美適配單色屏
02-22 09:47
看到這100多個(gè)軟硬件開源項(xiàng)目,真是爽爆了
2024-11-30 14:12
推薦一個(gè)高效,可靠,安全的串口通訊開源方案
2024-11-27 11:17
推薦一款開源hack硬件平臺(tái)工具
2024-11-26 13:58
新手學(xué)STM32的話,先學(xué)標(biāo)準(zhǔn)庫還是HAL庫?
2024-10-18 15:09

基于CubeIDE快速整合FreeRTOS創(chuàng)建第一個(gè)任務(wù)

本文主要介紹了如何創(chuàng)建FreeRTOS的任務(wù),基于STM32F767 Nucleo-144平臺(tái),在CubeIDE下進(jìn)行開發(fā),結(jié)合官方的HAL庫。如果覺得不錯(cuò),歡迎關(guān)注、分享、收藏、點(diǎn)贊。希望能幫助到大家,如有錯(cuò)誤敬請指出,謝謝!

文章目錄

  • FreeRTOS
  • 獲取源碼
  • 源碼結(jié)構(gòu)
  • CubeMX 整合 RTOS
  • 新建RTOS任務(wù)
  • 總結(jié)

1 FreeRTOS

FreeRTOS是免費(fèi)的嵌入式實(shí)時(shí)系統(tǒng),可以訪問官網(wǎng),至少目前是免費(fèi),并且社區(qū)相當(dāng)活躍,但是以后會(huì)不會(huì)被割韭菜就不清楚了,所以感覺還是支持國產(chǎn)比較好,大家可以參考一下RT-Thread;

1.1 獲取源碼

我們可以登陸到官網(wǎng)下載源碼的壓縮包,如下圖所示;

FreeRTOS還將源碼托管到github上,登陸官網(wǎng)可以看到下圖的兩個(gè)倉庫;

  • FreeRTOS-Kernel:這個(gè)倉庫是RTOS最核心的東西,很純凈,包括調(diào)度算法,信號(hào)量,內(nèi)存管理等等,它同時(shí)作為一個(gè)子模塊存在于FreeRTOS倉庫中;
  • FreeRTOS:這個(gè)倉庫是比較全的源碼,除了核心的部分,還包括對各個(gè)芯片平臺(tái)的支持以及各個(gè)主流IDE的demo,因此如果要移植的話,主要還是下載這個(gè)源碼;

但是本文暫不會(huì)介紹如何移植RTOS,在遠(yuǎn)古時(shí)期,因?yàn)榈谌降闹С至Χ炔粔?因此有一些平臺(tái)只能自己移植,現(xiàn)在第三方的支持相當(dāng)于給力,直接拿來用即可.

1.2 源碼結(jié)構(gòu)

自動(dòng)生成的代碼中找到FreeRTOS的源碼如下;

對于相應(yīng)的文件夾和源碼文件做一下介紹;

  • CMSIS_RTOS_V2:這是API的版本,對應(yīng)的還有CMSIS_RTOS_V1;
  • portable:這里主要是移植的時(shí)候需要修改的一些文件,針對不同的MCU以及不同的編譯器,需要對這塊進(jìn)行修改;
    • portmacro.h:定義編譯器相關(guān)的數(shù)據(jù)類型和中斷處理的宏定義;
    • port.c:實(shí)現(xiàn)任務(wù)的堆棧初始化、systick任務(wù)上下文切換
  • MemMang:內(nèi)存管理的文件,目前主要用heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c;
  • list.c:雙向鏈表的實(shí)現(xiàn),主要供給內(nèi)核調(diào)度器使用;
  • queue.c: 隊(duì)列的實(shí)現(xiàn),主要支持中斷環(huán)境和信號(hào)量控制;
  • croutine.c :任務(wù)使用同一個(gè)堆棧,這樣使得減小RAM的使用,但是在使用上會(huì)受到相當(dāng)大的限制;
  • task.c:每個(gè)任務(wù)都有各自的獨(dú)立堆棧,支持完全的搶占式調(diào)度

2 CubeMX 整合 RTOS

  1. 在配置工程的時(shí)候或者打開后綴名為.ioccubemx配置文件;
  2. 點(diǎn)擊菜單欄Pinout&Configuration
  3. 點(diǎn)擊Middleware選擇FREERTOS;

具體如下圖所示;

最終生成的文件結(jié)構(gòu)如下圖所示;

這時(shí)候已經(jīng)將FreeRTOS集成到工程中了,*****,簡直不能再方便了;

3 新建RTOS任務(wù)

直接生成的工程中,系統(tǒng)已經(jīng)創(chuàng)建好了一個(gè)任務(wù)StartDefaultTask;整體的main.c代碼如下;

#include "main.h"
#include "cmsis_os.h"

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void StartDefaultTask(void *argument);

int main(void)
{
  HAL_Init();
  
  SystemClock_Config();

  MX_GPIO_Init();

  osKernelInitialize();

  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
  /* Start scheduler */
  osKernelStart();
  /* We should never get here as control is now taken by the scheduler */
  while (1)
  {

  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_GPIO_Init(void)
{

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

}
void StartDefaultTask(void *argument)
{
  for(;;)
  {
    osDelay(1);
  }
}

void Error_Handler(void)
{

}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 

}
#endif /* USE_FULL_ASSERT */
 

這里可以看到整體的流程為兩部分HAL層和OS層;

HAL

  • 硬件初始化 HAL_Init
  • 時(shí)鐘配置 SystemClock_Config;
  • BSP初始化 MX_GPIO_Init;

OS

  • 內(nèi)核初始化 osKernelInitialize;
  • 創(chuàng)建任務(wù)/線程 osThreadNew;
  • 任務(wù)調(diào)度 osKernelStart

整體流程圖如下所示;

從OS的設(shè)計(jì)上來講,`Thread`擁有自己的`id`,并且可以分配`timer` 并且擁有一個(gè)類似線程的任務(wù)函數(shù)或者稱為任務(wù)回調(diào)函數(shù)(可能不太嚴(yán)謹(jǐn),下面統(tǒng)一稱之為任務(wù)回調(diào)函數(shù)),因此這里定義一個(gè)FreeRTOS任務(wù)需要三點(diǎn);
  1. osThreadId_t defaultTaskHandle;定義一個(gè)變量,后面創(chuàng)建任務(wù)會(huì)分配一個(gè)id作為該任務(wù)的唯一標(biāo)識(shí)符/身份證;
  2. osThreadAttr_t defaultTask_attributes;作為定義一個(gè)任務(wù)時(shí)的參數(shù),包括任務(wù)的優(yōu)先級(jí),所需要分配的棧空間大小.以及任務(wù)的名字等等;具體結(jié)構(gòu)體osThreadAttr_t如下所示;
typedef struct {
  const char                   *name;   ///< name of the thread
  uint32_t                 attr_bits;   ///< attribute bits
  void                      *cb_mem;    ///< memory for control block
  uint32_t                   cb_size;   ///< size of provided memory for control block
  void                   *stack_mem;    ///< memory for stack
  uint32_t                stack_size;   ///< size of stack
  osPriority_t              priority;   ///< initial thread priority (default: osPriorityNormal)
  TZ_ModuleId_t            tz_module;   ///< TrustZone module identifier
  uint32_t                  reserved;   ///< reserved (must be 0)
} osThreadAttr_t; 

  1. 創(chuàng)建任務(wù)回調(diào)函數(shù),這里有一個(gè)生命周期的問題,通常在任務(wù)中放一個(gè)死循環(huán),以便于任務(wù)保持存活,可以被一直調(diào)度;
void StartDefaultTask(void *argument)
{
  	for(;;)
  	{
    	osDelay(1);
  	}
} 

最后,調(diào)用osThreadNew創(chuàng)建任務(wù);該函數(shù)聲明如下所示;

osThreadId_t osThreadNew (	osThreadFunc_t func, 
							void *argument, 
							const osThreadAttr_t *attr);   

4 總結(jié)

通過cube自動(dòng)生成了一個(gè)FREERTOS工程,簡單分析了一下如何創(chuàng)建一個(gè)任務(wù),后續(xù)需要在實(shí)踐中深入到源碼中學(xué)習(xí)FreeRTOS;

筆者能力和水平有限,文中難免有錯(cuò)誤和紕漏之處,請大佬們不吝賜教。


聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 3
收藏 3
關(guān)注 144
成為作者 賺取收益
全部留言
0/200
  • 天賜時(shí)間 2020-12-14 16:23
    感謝分享
    回復(fù)
  • 記得誠 2020-12-13 18:25
    優(yōu)秀
    回復(fù)