邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛
分类: 嵌入式
2015-09-17 10:56:12
主要讲在freertos中,如何管理任务:这就包括如何创建任务,删除任务,改变任务的优先级等等。
软实时: 对每个输入的响应应当限定在一个恰当的时间范围内,但是如果响应时间超出了限定范围,也能接受。术语:
硬实时: 响应必须在给定的时间内完成,如果无法做到,可能引起灾难性的后果。
大多数嵌入式系统都能完成软实时和硬实时的要求。
在freertos中,每个执行线程都被称作为“任务”。
void ATaskFunction(void *pvParameters);任务状态:
想一个问题,下面这个让LED闪烁的任务,state如何定义呢?
是定义成:
u8 state = 0;还是:
static u8 state = 0;这跟以前我们写法,还是不同的,想想为什么可以定义成: u8 state =0 ???
void redLed_Task(void *pvParameters)
{
u8 state = 0;
pvParameters = pvParameters;
while(1)
{
//(state = !state) == 1 ? RED_ON(): RED_OFF();
state ++;
if(state == 1) RED_ON();
else if(state == 2) RED_OFF();
else if(state == 3) RED_ON();
else if(state == 4) {RED_OFF(); state = 0;}
vTaskDelay(1000/portTICK_RATE_MS); // ???±?à?????????è?? ???±500??????
}
}
应用程序可以包含多个任务。如果运行应用程序的微控制器只有一个核(core),那么在任意给定时间,实际上只会有一个任务被执行。这就意味着一个任务可以有一个或
两个状态,即运行状态和非运行状态。我们先考虑这种最简单的模型——但请牢记这其实是过于简单,我们稍后将会看到非运行状态实际上又可划分为若干个子状态。
当某个任务处于运行态时,处理器就正在执行它的代码。当一个任务处于非运行态时,该任务进行休眠,它的所有状态都被妥善保存,以便在下一次调试器决定让它进入
运行态时可以恢复执行。当任务恢复执行时,其将精确地从离开运行态时正准备执行的那一条指令开始执行。
创建任务:
是一个宏定义:
#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask )
xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) )
点击(此处)折叠或打开
- /*-----------------------------------------------------------
- * TASK CREATION API
- *----------------------------------------------------------*/
- /**
- * task. h
- *<pre>
- BaseType_t xTaskCreate(
- TaskFunction_t pvTaskCode,
- const char * const pcName,
- uint16_t usStackDepth,
- void *pvParameters,
- UBaseType_t uxPriority,
- TaskHandle_t *pvCreatedTask
- );</pre>
- *
- * Create a new task and add it to the list of tasks that are ready to run.
- *
- * xTaskCreate() can only be used to create a task that has unrestricted
- * access to the entire microcontroller memory map. Systems that include MPU
- * support can alternatively create an MPU constrained task using
- * xTaskCreateRestricted().
- *
- 第一个参数: pvTaskCode 是指向任务函数的指针
- * @param pvTaskCode Pointer to the task entry function. Tasks
- * must be implemented to never return (i.e. continuous loop).
- *
- 第二个参数: 是具有描述性的函数名字
- * @param pcName A descriptive name for the task. This is mainly used to
- * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default
- * is 16.
- *
- 第三个参数: 用于分配任务堆栈大小。注意: 这里不是指字节数,而是跟处理器的位宽相关。
- * @param usStackDepth The size of the task stack specified as the number of
- * variables the stack can hold - not the number of bytes. For example, if
- * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
- * will be allocated for stack storage.
- *
- 第四个参数: 传递到任务中的参数
- * @param pvParameters Pointer that will be used as the parameter for the task
- * being created.
- *
- 第五个参数: 任务的优先级。最低优先级从0开始,优先级没有上限。
- * @param uxPriority The priority at which the task should run. Systems that
- * include MPU support can optionally create tasks in a privileged (system)
- * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For
- * example, to create a privileged task at priority 2 the uxPriority parameter
- * should be set to ( 2 | portPRIVILEGE_BIT ).
- *
- 第六个参数: 用于传出任务的句柄。
- * @param pvCreatedTask Used to pass back a handle by which the created task
- * can be referenced.
- *
- 返回参数: 如果返回pdPASS,则创建成功。
- * @return pdPASS if the task was successfully created and added to a ready
- * list, otherwise an error code defined in the file projdefs.h
- *
- * Example usage:
- <pre>
- // Task to be created.
- void vTaskCode( void * pvParameters )
- {
- for( ;; )
- {
- // Task code goes here.
- }
- }
- // Function that creates a task.
- void vOtherFunction( void )
- {
- static uint8_t ucParameterToPass;
- TaskHandle_t xHandle = NULL;
- // Create the task, storing the handle. Note that the passed parameter ucParameterToPass
- // must exist for the lifetime of the task, so in this case is declared static. If it was just an
- // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
- // the new task attempts to access it.
- xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
- configASSERT( xHandle );
- // Use the handle to delete the task.
- if( xHandle != NULL )
- {
- vTaskDelete( xHandle );
- }
- }
- </pre>
- * \defgroup xTaskCreate xTaskCreate
- * \ingroup Tasks
- */
建立两个任务,只是周期性的打印字符串到串口,指定了相同的优先级。
main.c函数:
点击(此处)折叠或打开
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- // FreeRTOS head file, add here.
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "list.h"
- #include "portable.h"
- #include "FreeRTOSConfig.h"
- void task1(void *pvParameters)
- {
- u8 state = 0;
- while(1)
- {
- printf("task 1 is running \r\n");
- (state = !state) == 1 ? RED_ON(): RED_OFF();
- vTaskDelay(1000/portTICK_RATE_MS);
- }
- }
- void task2(void *pvParameters)
- {
- u8 state1 = 0;
- while(1)
- {
- printf("task 2 is running \r\n");
- (state1 = !state1) == 1 ? GREEN_ON() : GREEN_OFF();
- vTaskDelay(1000/portTICK_RATE_MS);
- }
- }
- int main(void)
- {
- // board initialize.
- LED_Init();
- uart_init(115200);
- //create two tasks, with the same priority.
- // 优先级一样
- xTaskCreate( task2, "task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
- xTaskCreate( task1, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
- // start scheduler now
- vTaskStartScheduler();
- return 0;
- }
打印输出信息:
可见,task1和task2轮流运行,打印字符串。
在main函数中,创建了两个任务,当然也可以从一个任务中创建另一个任务。
点击(此处)折叠或打开
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- // FreeRTOS head file, add here.
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "list.h"
- #include "portable.h"
- #include "FreeRTOSConfig.h"
- void task2(void *pvParameters)
- {
- u8 state1 = 0;
- while(1)
- {
- printf("task 2 is running \r\n");
- (state1 = !state1) == 1 ? GREEN_ON() : GREEN_OFF();
- vTaskDelay(1000/portTICK_RATE_MS);
- }
- }
- void task1(void *pvParameters)
- {
- u8 state = 0;
- // 在任务中创建另一个任务
- xTaskCreate( task2, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
- while(1)
- {
- printf("task 1 is running \r\n");
- (state = !state) == 1 ? RED_ON(): RED_OFF();
- vTaskDelay(1000/portTICK_RATE_MS);
- }
- }
- int main(void)
- {
- // board initialize.
- LED_Init();
- uart_init(115200);
- //create two tasks, with the same priority.
- xTaskCreate( task1, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
- // start scheduler now
- vTaskStartScheduler();
- return 0;
- }
例1 中创建的两个任务几乎完全相同,唯一的区别就是打印输出的字符串。这种重复性可以通过创建同一个任务代码的两个实体来去除。这时任务参数就可以用来传递各自打印输出的字符串。
见main.c
点击(此处)折叠或打开
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- // FreeRTOS head file, add here.
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "list.h"
- #include "portable.h"
- #include "FreeRTOSConfig.h"
- void vTaskFunction(void *pvParameters)
- {
- char *taskName;
- // 接收创建任务时候传递过来的参数
- taskName = (char *)pvParameters;
- while(1)
- {
- printf(taskName);
- vTaskDelay(1000/portTICK_RATE_MS);
- }
- }
- static const char * task1 = "task 1 is running \r\n";
- static const char * task2 = "task 2 is running \r\n";
- int main(void)
- {
- // board initialize.
- LED_Init();
- uart_init(115200);
- //create two tasks, with the same priority.
- // 将参数传递给任务实体
- xTaskCreate( vTaskFunction, "task1", configMINIMAL_STACK_SIZE, (void *)task1, 1, NULL);
- xTaskCreate( vTaskFunction, "task2", configMINIMAL_STACK_SIZE, (void *)task2, 1, NULL );
- // start scheduler now
- vTaskStartScheduler();
- return 0;
- }