一、单任务系统和多任务系统
单任务系统一般为裸机系统,while(1)做一个大循环,也包含一些中断,完成所有的程序逻辑处理。如果应用程序需求繁多,程序设计复杂,应考虑多任务系统。
多任务系统在操作系统基础上实现,可将繁杂的应用程序“分而治之”,将大问题划分为多个小问题,由不同的任务去解决,可以认为它们是并发运行的(其实是多个任务轮转运行,每个任务执行时间很短),RTOS中有一个任务调度器决定哪个任务先运行,哪个后运行。
二、FreeRTOS任务特点:
在程序设计中,一个应用业务可以单独作为一个任务,每个任务都拥有自己独立的运行环境,不依赖于其他任务,一个时刻同时只有一个任务在运行,由任务调度器决定哪个任务运行。在调度过程中,任务调度器需保证一个任务在开始运行时,其上下文环境与任务上一次退出的时候相同。故,每个任务都必须有独立的堆栈保存上下文环境。
任务支持抢占/优先级/独立的堆栈。
三、任务的状态
FreeRTOS任务的状态有4种:运行态,就绪态,阻塞态,挂起态。
- 运行态
该任务正在运行,正占用处理器。
2. 就绪态
指已经准备好运行的任务(没有被挂起或阻塞),就绪态还没有运行,在等待同优先级任务或者更高优先级任务让出处理器。
3. 阻塞态
任务在等待某个外部事件,处于阻塞状态。如任务调用vTaskDelay(),在等待延时完成,等待队列/信号量/事件组/通知/互斥信号量等,阻塞态会有超时时间,超过改时间,退出阻塞态。
4. 挂起态
与阻塞态类似,进入挂起态也不能被调用进入运行态,但是挂起态没有超时时间,调用vTaskSuspend()和xTaskResume()使任务进入和退出挂起态。
状态之间转换如下图:
![](https://img-blog.csdnimg.cn/20201116151443964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxOTE3ODYz,size_16,color_FFFFFF,t_70)
每个任务都有优先级,0~(configMAX_PRIOIRTES-1),0的优先级最低,FreeRTOS调度器确保处于就绪态的最高优先级任务优先执行,当宏configUSE_TIME_SLICING定义为1时,多个任务可以使用相同优先级,数量不限,对于处于就绪态的优先级相同的任务,将由时间片轮转调度器决定谁先运行。
四、任务的创建
FreeRTOS中创建任务使用xTaskCreate()或者xTaskCreateStatic()来创建任务,
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) ;
TaskHandle_t xTaskCreateStatic(
TaskFunction_t pxTaskCode,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer );
xTaskCreate()动态创建任务,xTaskCreateStatic()静态创建任务(需自己定义堆栈),一般常用xTaskCreate()。pxTaskCode为任务的执行函数,在该函数中完成该任务的工作。FreeRTOS官方给出的任务模板如下:
void vTaskCode( void * pvParameters )
{
for( ;; )
{
// Task code goes here.
```
vTaskDelay();
```
}
vTaskDelete(NULL);
}
1.任务函数的返回值必须为viod类型,参数为void*类型;
2,任务具体执行过程是一个大循环,在该循环中处理业务逻辑;
3.可使用延时函数,请求信号量,队列等;
4.任务函数中一般不允许跳出循环,若跳出循环,则需调用vTaskDelete(NULL)删除此任务,删除任务时需释放掉在内存中动态申请的内存。
五、任务控制块
任务控制块结构体包含一个任务所有需要存储的属性,使用xTaskCreate()创建一个任务,系统自动给该任务分配一个任务控制块。
typedef struct tskTaskControlBlock
{
volatile StackType_t *pxTopOfStack; /*任务堆栈顶,必须为第一个成员*/
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< MPU相关设置*/
#endif
ListItem_t xStateListItem; /*< 状态列表项(链表节点),阻塞/就绪/挂起 */
ListItem_t xEventListItem; /*事件列表项(链表节点) */
UBaseType_t uxPriority; /*任务优先级 */
StackType_t *pxStack; /*堆栈起始地址 */
char pcTaskName[ configMAX_TASK_NAME_LEN];/*任务名字*/
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t *pxEndOfStack; /*任务堆栈栈底*/
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
#endif
#if ( configUSE_TRACE_FACILITY == 1 ) /*debug或trace的时候用*/
UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; /*基础优先级,优先级反转时用到*/
UBaseType_t uxMutexesHeld; /*获取到信号量个数*/
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag;
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
/* Allocate a Newlib reent structure that is specific to this task.
Note Newlib support has been included by popular demand, but is not
used by the FreeRTOS maintainers themselves. FreeRTOS is not
responsible for resulting newlib operation. User must be familiar with
newlib and must provide system-wide implementations of the necessary
stubs. Be warned that (at the time of writing) the current newlib design
implements a system-wide malloc() that must be provided with locks. */
struct _reent xNewLib_reent;
#endif
#if( configUSE_TASK_NOTIFICATIONS == 1 ) /*任务通知相关变量*/
volatile uint32_t ulNotifiedValue; /*任务通知值*/
volatile uint8_t ucNotifyState; /*通知状态*/
#endif
/* See the comments in FreeRTOS.h with the definition of
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
uint8_t ucStaticallyAllocated; /*< pdTRUE表示任务是静态创建,pdFALSE表示任务时动态创建*/
#endif
#if( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
#if( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno;
#endif
} tskTCB;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)