购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

7.3 FreeRTOS的API模块

FreeRTOS是一种开源的嵌入式操作系统。FreeRTOS提供了系统定制功能,同时也提供了多种API函数用来实现任务控制和内核控制。

7.3.1 定制

FreeRTOS 允许一定数量的参数存在,使得 FreeRTOS 内核可以剪裁来更加适合具体的应用程序。这些参数位于FreeRTOSConfig.h文件中。每一个包含FreeRTOS源代码演示程序,都有它自己的FreeRTOSConfig.h文件。典型的FreeRTOSConfig.h文件示例如下:

这里是一个普通的例子,下面介绍每个参量的含义。

● configUSE_PREEMPTION:设置为1,使用抢先式内核;设置为0,为合作轮转内核。

● configUSE_IDLE_HOOK:设置为1,使用空闲钩子;设置为0,不使用空闲钩子。

● configUSE_TICK_HOOK:如果希望使用时间片钩子,就设置为1,设置为0,不使用。

● configCPU_CLOCK_HZ:内部处理器执行的频率。这个值需要正确配置外围定时器。

● configTICK_RATE_HZ:RTOS时间片中断的频率。时间片中断用来测量时间。因此更高时间片频率意味着时间测量可以有更高分辨率,同时意味着内核占用更多的CPU(效率很低)。多个任务共有同一优先级。通过切换任务,在每一个RTOS时间片内,内核将在同一优先级的任务间分配处理器时间。高时间片频率意味着将减少给予每个任务的时间份额。

● configMAX_PRIORITIES:应用程序任务中可用优先级的数目。任何数量的任务,都可以分配同一优先级。任务单独分配优先级,可以参考 configMAX_CO_ROUTINE_PRIORITIES。内核分配的每个可用的优先级都消耗 RAM,因此这个值不应该设置为高于实际应用程序中需要的。

● configMINIMAL_STACK_SIZE:空闲任务使用的堆栈大小。通常这个值不用少于FreeRTOSConfig.h file 中演示程序提供的。

● configTOTAL_HEAP_SIZE:内核总共可用的RAM数量。

● configMAX_TASK_NAME_LEN:当创建一个任务,能够给予描述任务名称的最大容许长度。这个长度指定符号数目,包括NULL终止字节。

● configUSE_TRACE_FACILITY:设置为1,使用可视化追踪功能;设置为0,就不使用。如果使用可视化追踪,必须提供追踪缓冲区。

● configUSE_16_BIT_TICKS:时间片(内核开始执行后,时间片中断的次数)来测量时间。时间片计数器定义为可用的 portTickType.类型。定义 configUSE_16_BIT_TICKS为1,将使portTickType定义为16位无符号类型。定义为0,将是32位无符号类型。使用16位类型,将大幅度提高性能。但是,这样限制了最大指定可用时间周期(65535时间片)。然而,假定时间片频率为 250Hz,一个任务在16 位上,最大延时或中断时间位262秒,而32位为17179869秒。

● configIDLE_SHOULD_YIELD:这个参数控制任务与空闲任务优先级相同时的行为。

● configUSE_MUTEXES:设置为1,将使用互斥功能;设置为0,将不使用。

● configUSE_RECURSIVE_MUTEXES:设置为1,将使用递归互斥功能;设置为0,将不使用。

● configUSE_COUNTING_SEMAPHORES:设置为 1,将使用计数器型信号量功能;设置为0,将不使用。

● configUSE_ALTERNATIVE_API:设置为1,将包含替代队列函数;设置为0,将不包含。替代API在queue.h头文件中有详细的描述。

● configCHECK_FOR_STACK_OVERFLOW:堆栈溢出检测。

● configQUEUE_REGISTRY_SIZE:队列记录。允许一个队列相关的名称,可以在 GUI调试中容易定义。另外,也包含了调试器所需的信息,来定位每个记录的队列和信号量。队列记录除了进行内核相关的调试外,没有什么目的。configQUEUE_REGISTRY_SIZE定义了可以记录的队列和信号量的最大数目。

● configUSE_CO_ROUTINES:设置为1,将使用(协同例程)合作轮转式程序;设置为0,将不使用。当使用时,必须把Croutine.c包含进项目中。

● configMAX_CO_ROUTINE_PRIORITIES:合作式应用程序中可用的优先级数目。任何合作式程序可使用同一优先级。

● configKERNEL_INTERRUPT_PRIORITY:一般适用于 Cortex-M3,PIC24,dsPIC andPIC32 接口。

● configMAX_SYSCALL_INTERRUPT_PRIORITY:一般PIC32和Cortex-M3接口中可用。其他接口将很快更新。

7.3.2 任务创建和删除

在FreeRTOS中,任务的创建和删除分别采用xTaskCreate函数和vTaskDelete函数。其中, xTaskCreate函数的原型如下:

该函数创建新的任务并添加到任务队列中,准备运行。如果任务成功创建并且添加到就绪列中,另外错误代码在projdefs. H文件定义。该函数的各个参数的含义如下。

● pvTaskCode:指向任务的入口函数,任务必须执行并且永不返回(即无限循环)。

● pcName:描述任务的名字,主要便于调试。最大长度由 定义。

● usStackDepth:指定任务堆栈的大小,堆栈能保护变量的数目。例如,如果堆栈为 16位宽度,usStackDepth 定义为 100、200 字节,这些将分配给堆栈。堆栈嵌套深度(堆栈宽度)不能超过最大值,包含了size_t类型的变量。

● pvParameters:指针用于作为一个参数传向创建的任务。

● uxPriority:任务运行时的优先级。

● pvCreatedTask:用于传递一个处理,引用创建的任务。

而删除任务的函数vTaskDelete原型如下:

在使用时,该函数从RTOS实时内核管理中移除任务。要删除的任务将从就绪、封锁、挂起、事件列表中移除,空闲任务负责释放内核分配给已删除任务的内存。因此,如果应用程序调用了vTaskDelete(),微控制器执行期间,空闲任务不假死是很重要的。内存分配给任务的代码不会自动释放,应该在任务删除之前。

7.3.3 任务控制

FreeRTOS操作系统的任务控制通过一系列的API函数来实现。这里分别介绍各个任务控制API函数。

1.vTaskDelay

vTaskDelay函数的原型如下:

vTaskDelay函数指定一个任务希望的时间段,这个时间之后任务解锁。例如,指定周期段为100时间片,将使任务在调用vTaskDelay函数100个时间片之后解锁。vTaskDelay函数不提供一个控制周期性任务频率的好方法,像通过代码采取的路径,和其他任务和中断一样,在调用vTaskDelay函数后影响频率,因此任务所需的时间下一次执行。

2.vTaskDelayUntil

vTaskDelayUntil函数的原型如下:

其中,pxPreviousWakeTime指定一个变量来掌握任务最后开启的时间。这个变量在第一次使用时必须使用当前时间来初始化。xTimeIncrement为循环周期时间。

这个函数在一个重要方面上不同于vTaskDelay函数,vTaskDelay函数指定的这个时间(任务希望开启)与vTaskDelay函数有关,而vTaskDelayUntil函数指定是一个绝对时间(任务希望开启)。

3.uxTaskPriorityGet

uxTaskPriorityGet函数的原型如下:

该函数用于获得任务的优先级。其中,输入参数pxTask为需要处理的任务,当传递NULL时,将返回所调用任务的优先级。

4.vTaskPrioritySet

vTaskPrioritySet函数的原型如下:

该函数设置任务的优先级。如果设置的优先级高于当前执行任务的优先级,则上下文切换将在此函数返回之前发生。

其中,输入参数 pxTask 为需要设置优先级的任务,当传递 NULL,将设置调用任务的优先级。输入参数uxNewPriority为任务需要设置的优先级。

5.vTaskSuspend

vTaskSuspend函数的原型如下:

该函数用于挂起任务。当挂起一个任务时,不管优先级是多少,不需要占用任何微控制器处理器时间。调用 vTaskSuspend 不会累积,也就是说,如果在统一任务中调用 vTaskSuspend两次,此时只需调用一次vTaskResume ()来使挂起的任务就绪。

其中,输入参数pxTaskToSuspend为处理需要挂起的任务。传递NULL将挂起调用此函数的任务。

6.vTaskResume

vTaskResume函数的原型如下:

该函数用于唤醒挂起的任务。必须是调用 vTaskSuspend 函数后挂起的任务,才有可能通过调用vTaskResume 函数重新运行。

其中,输入参数pxTaskToResume为就绪的任务的句柄。

7.vTaskResumeFromISR

vTaskResumeFromISR函数的原型如下:

该函数从ISR中唤醒挂起的任务。其中,输入参数pxTaskToResume为就绪任务的句柄。vTaskResumeFromISR 函数不应该用于任务和中断同步,因为可能会在中断发生期间,任务已经挂起,这将导致错过中断。使用信号量作为同步机制将避免这种偶然性。

8.vTaskSetApplicationTag

vTaskSetApplicationTag函数的原型如下:

该函数能为每个任务分配标签值。这个值仅在应用程序中使用,内核本身不使用它。其中,输入参数 xTask 为将分配给标签值的任务,传递 NULL 将分配标签给调用的任务。输入参数pxTagValue 为分配给任务的标签值,类型为 pdTASK_HOOK_CODE,允许一个函数指针赋值给标签。因此实际上任何值都可以分配。

9.vxTaskCallApplicationTaskHook

vxTaskCallApplicationTaskHook函数的原型如下:

该函数可以为每个任务分配一个标签值。正常情况下,这个值仅用于应用程序,内核并不存储。然而,可以使用标签赋值给钩子(或回调)函数给任务,钩子函数将通过调用xTaskCallApplicationTaskHook()执行。每个任务定义自己的返回值,或者仅仅定义一个返回值。

其中,输入参数xTask为处理将被调用钩子函数的任务。xTask当做NULL传递,将调用钩子函数赋值给当前执行的任务。输入参数 pvParameter 为传递给钩子函数的值。可以是指向结构或数值的指针。

7.3.4 内核控制

FreeRTOS操作系统的内核控制也是通过一系列的API函数来实现的。这里分别介绍各个内核控制API函数。

1.vTaskStartScheduler

vTaskStartScheduler函数的原型如下:

该函数用于启动实时内核处理。在调用之后,内核已经控制执行的任务。

当 vTaskStartScheduler()被调用时,空闲任务自动创建。如果 vTaskStartScheduler()成功调用,这个函数不返回,直到执行任务调用 vTaskEndScheduler()。如果可供给空闲任务的 RAM不足,那么函数调用失败,并立即返回。

2.vTaskEndScheduler

vTaskEndScheduler函数的原型如下:

该函数用于停止实时内核运行。所有创建的任务将自动删除,并且多任务(优先级或合作式)将停止。vPortEndScheduler()导致所有由内核分配的资源释放,但是不会释放由应用程序的任务分配的资源。

3.vTaskSuspendAll

vTaskSuspendAll函数的原型如下:

该函数挂起所有活动的实时内核,同时允许中断(包括内核滴答)。

任务在调用 vTaskSuspendAll()后,这个任务将继续执行,不会有任何被切换的危险,直到调用xTaskResumeAll()函数。API中有可能影响上下文切换的函数,一定不能在调度器挂起时被调用。 /9QaIP78fxUGuR+5kfB68e/wspCwliQmovpGYqQ+U1f7DfxfOCeF0CpX9Uxp5iqw

点击中间区域
呼出菜单
上一章
目录
下一章
×