文章目录
0 前言
@ Author :Dargon
@ Record Date :2021/07/13
@ Reference Book : `FreeRTOS源码详解与应用开发`,`ARM Cortex-M3与Cortex-M4权威指南`,`B站正点原子FreeRTOS讲解视频`
@ Purpose :学习正点原子的miniFly,该飞控基于FreeRTOS系统开发的,所以学习一下记录下关于RTOS系统的一些基本操作,大概了解系统的工作原理,如何创建,运行,切换任务等等基本操作流程。在此进行学习的记录。
1 任务调度器的开启
- 这里所提到的应该是FreeRTOS最核心的东西了,首先在创建了一个start的任务的时候,最后就会调用
vTaskStartScheduler()
来开启任务调度器。
1.1 如何启动第一个任务的
-
vTaskStartScheduler() 任务源码分析
void vTaskStartScheduler( void ) { BaseType_t xReturn; /* Add the idle task at the lowest priority. */ #else // --利用动态方法创建 任务 { /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } #endif /* configSUPPORT_STATIC_ALLOCATION */ #if ( configUSE_TIMERS == 1 ) // --判断是否需要创建软件定时器 { if( xReturn == pdPASS ) { xReturn = xTimerCreateTimerTask(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_TIMERS */ if( xReturn == pdPASS ) // --xReturn 针对返回值 创建通过 { /* Interrupts are turned off here, to ensure a tick does not occur before or during the call to xPortStartScheduler(). The stacks of the created tasks contain a status word with interrupts switched on so interrupts will automatically get re-enabled when the first task starts to run. */ portDISABLE_INTERRUPTS(); // --先关闭中断 #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent structure specific to the task that will run first. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ // --相应的参数初始化 一些静态全局变量 xNextTaskUnblockTime = portMAX_DELAY; // --初始化下一个阻塞解放时刻 为32位最大值 xSchedulerRunning = pdTRUE; xTickCount = ( TickType_t ) 0U; /* If configGENERATE_RUN_TIME_STATS is defined then the following macro must be defined to configure the timer/counter used to generate the run time counter time base. */ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); // --就是一个macro 来定义是否使用时间计数器的问题 不用管它 /* Setting up the timer tick is hardware specific and thus in the portable interface. */ // --进入这个内核硬件初始化函数 就不会在回来了 // --初始化systick 和PendSV中断 if( xPortStartScheduler() != pdFALSE ) { /* Should not reach here as if the scheduler is running the function will not return. */ } else { /* Should only reach here if a task calls xTaskEndScheduler(). */ } } else // --创建失败 一个断言 就是打印一些错误信息