FreeRTOS使用多任务完成功能,首先要了解任务的基本知识。
裸机编程中,单任务系统的编程方式,即裸机的编程方式,这种编程方式的框架一般都是在 main()函数 中使用一个大循环,在循环中顺序地调用相应的函数以处理相应的事务,这个大循环的部分可 以视为应用程序的后台,而应用程序的前台,则是各种中断的中断服务函数。
多任务系统在处理事务的实时性上比单任务系统要好得多,从宏观上来看,多任务系统的 多个任务是可以“同时”运行的,因此紧急的事务就可以无需等待 CPU 处理完其他事务,在被 处理。 要注意的是多任务系统的多个任务可以“同时”运行,是从宏观的角度而言的,对于单核 的 CPU 而言,CPU 在同一时刻只能够处理一个任务,但是多任务系统的任务调度器会根据相 关的任务调度算法,将 CPU 的使用权分配给任务,在任务获取 CPU 使用权之后的极短时间(宏 观角度)后,任务调度器又会将 CPU 的使用权分配给其他任务,如此往复,在宏观的角度看来, 就像是多个任务同时运行了一样。
从上图可以看出,相较于单任务系统而言,多任务系统的任务也是具有优先级的,高优先 级的任务可以像中断的抢占一样,抢占低优先级任务的 CPU 使用权;优先级相同的任务则各自 轮流运行一段极短的时间(宏观角度),从而产生“同时”运行的错觉。以上就是抢占式调度和 时间片调度的基本原理。 在任务有了优先级的多任务系统中,用户就可以将紧急的事务放在优先级高的任务中进行 处理,那么整个系统的实时性就会大大地提高。
关于任务的相关函数
xTaskCreate() | 动态方式创建任务 |
xTaskCreateStatic() | 静态方式创建任务 |
xTaskCreateRestricted() | 动态方式创建使用 MPU 限制的任务 |
xTaskCreateRestrictedStatic() | 静态方式创建使用 MPU 限制的任务 |
vTaskDelete() | 删除任务 |
这里常用的就是动态创建和静态创建
1.动态创建
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);
pxTaskCode | 任务函数 |
pcName | 任务名 |
usStackDepth | 任务堆栈大小 |
pvParameters | 传递给任务函数的参数 |
uxPriority | 任务优先级 |
pxCreatedTask | 任务句柄,任务成功创建后,会返回任务句柄。任务句柄就 是任务的任务控制块 |
注意,任务的堆栈这里给的是Depth也就是深度,个人理解实际的大小是深度×宽度,宽度就是事先定义好的字的长度,,那么实际的堆栈大小就是usStackDepth*一个字的字节。
为什么需要堆栈?通过前面的图可以知道,任务是相互切换完成执行的,A任务切换到B任务的时候,CPU从接管A任务的状态切换到接管B任务的装填,那么就需要对A任务的当前现场进行保护,在下次再进行A任务的时候再恢复现场,这里说的保护和恢复,实际上是针对A任务中的一些变量进行的,所以A任务需要一个堆栈,同理,B任务也需要一个自己的堆栈。
uxPriority就是任务的优先级,数字小的优先级低,数字大的优先级高,先执行优先级高的。pxCreatedTask任务句柄,可以整体的控制任务,可以删除或者挂起和恢复时传入相应任务的句柄。
2.静态创建
静态创建和静态创建的区别就是要自己创建一个空闲任务和用户自己申请堆栈内存。
TaskHandle_t xTaskCreateStatic(
TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer);
静态和动态参数不同的地方
puxStackBuffer | 任务栈指针,内存由用户分配提供 |
pxTaskBuffer | 任务控制块指针,内存由用户分配提供 |
静态任务的作用
1.创建空闲任务和定时器任务的目的是为了提供系统的基本功能和调度。
空闲任务(Idle Task): 空闲任务是系统中的一个特殊任务,它在没有其他任务需要运行时执行。空闲任务的作用是防止系统进入死循环,保证系统的正常运行。当系统中没有其他任务需要运行时,空闲任务会被调度执行。它通常执行一些低优先级的操作,如系统休眠、节能模式等。
创建空闲任务的静态任务控制块和堆栈是为了分配空闲任务的内存空间,并在系统启动时使用这些内存空间创建空闲任务。
2.为什么创建动态任务不需要创建空闲任务和定时器任务?
创建动态任务时,不需要显式地创建空闲任务和定时器任务的原因是因为FreeRTOS会自动创建和管理这些任务。
空闲任务: FreeRTOS会自动创建一个名为"Idle"的空闲任务,并在系统没有其他任务需要运行时执行。空闲任务的优先级是最低的,它会执行一些低优先级的操作,如系统休眠、节能模式等。由于空闲任务是自动创建和管理的,因此在动态创建任务时不需要显式地创建空闲任务。
定时器任务: FreeRTOS会自动创建一个名为"Timer"的定时器任务,用于管理系统的软件定时器。定时器任务负责管理和处理软件定时器的相关操作,包括创建、删除、启动、停止定时器等。由于定时器任务是自动创建和管理的,因此在动态创建任务时不需要显式地创建定时器任务。
创建动态任务时,只需要调用FreeRTOS提供的任务创建函数,传入任务相关的参数,即可创建动态任务。FreeRTOS会自动进行任务调度和管理,包括空闲任务和定时器任务的创建和执行。