?
目錄
前言
一、主函數內容
二、osKernelInitialize ()內核初始化函數內容
三、IS_IRQ()宏定義中斷檢測函數內容
四、如果這篇文章能幫助到你,請點個贊鼓勵一下吧ξ( ?>??)~
前言
????????使用STM32CubeMX添加FreeRTOS進入工程之后,會自動在main函數中生成FreeRTOS的初始化和啟動代碼。
一、主函數內容
? ? ? ? main.c函數代碼如下:
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C2_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Init scheduler */osKernelInitialize(); //FreeRTOS內核初始化/* Call init function for freertos objects (in cmsis_os2.c) */MX_FREERTOS_Init(); //FreeRTOS初始化/* Start scheduler */osKernelStart(); //FreeRTOS內核啟動,任務調度算法/* 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 */}/* USER CODE END 3 */
}
二、osKernelInitialize ()內核初始化函數內容
???????? main函數中完成時鐘和外設初始化之后,開始執行對FreeRTOS的初始化和啟動流程,首先從osKernelInitialize ()內核初始化函數開始執行,osKernelInitialize ()函數代碼如下所示:
osStatus_t osKernelInitialize (void) {osStatus_t stat;if (IS_IRQ()) //如果當前程序處于中斷上下文中{stat = osErrorISR; //stat狀態寄存器變量賦異常值}else //如果不在中斷中{ if (KernelState == osKernelInactive) //如果內核狀態標志位處于未激活狀態{#if defined(USE_TRACE_EVENT_RECORDER) //如果開啟事件軌跡記錄標志位EvrFreeRTOSSetup(0U); //觸發FreeRTOS初始化開始事件,0表示初始階段,用于性能分析#endif//如果定義了使用HEAP_5規則來進行堆棧內存分配#if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1) vPortDefineHeapRegions (configHEAP_5_REGIONS); //初始化堆內存區域#endifKernelState = osKernelReady; //內核狀態切換為就緒狀態stat = osOK; //函數狀態返回值切換為OK} else { //如果內核狀態不處于未激活狀態stat = osError; //函數狀態返回值賦值為osError}}return (stat); //返回值
}
????????這個FreeRTOS內核初始化函數的主要作用,就是在保障安全的情況下(檢查當前程序是否處于中斷上下文中),將FreeRTOS與運行狀態標志位KernelState由osKernelInactive未激活狀態切換為osKernelReady就緒狀態。為什么不能在中斷中進行處理呢?因為在中斷中有可能會發生中斷嵌套,如果兩個中斷都操作了同一寄存器,可能會引起同一變量的競爭,造成異常現象。
三、IS_IRQ()宏定義中斷檢測函數內容
? ? ? ? ?其中,IS_IRQ()是宏定義的中斷檢測函數入口,其引用的函數原型是 __get_IPSR(void),這個函數將32位的變量映射到ARM的IPSR寄存器,IPSR寄存器內部存儲當前中斷號或代碼異常標志,若其返回值不為0,表示當前程序正處在中斷函數中。
#define IS_IRQ_MODE() (__get_IPSR() != 0U)
#define IS_IRQ() IS_IRQ_MODE()/**\brief Get IPSR Register\details Returns the content of the IPSR Register.\return IPSR Register value*/
__STATIC_INLINE uint32_t __get_IPSR(void) //獲取IPSR寄存器的數值
{//register是C語言中的關鍵字,功能是建議將變量存儲在寄存器而非內存中//__asm是匯編語言的關鍵字,將register映射到ipsr寄存器,這是編譯器的擴展語法,強制將變量__regIPSR與ARM的ipsr特殊寄存器綁定register uint32_t __regIPSR __ASM("ipsr"); return(__regIPSR); //返回寄存器的值
}