FreeRTOS开发指南

 1:任务模板

//任务优先级
#define XXX_TASK_PRIO		1
//任务堆栈大小	
#define XXX_STK_SIZE 		128  
//任务句柄
TaskHandle_t XXXTask_Handler = NULL; 

/*
*    放在开始任务,只需要执行一次为了创建任务
*/
void Create_XXX_Task(void)
{
	
	BaseType_t xReturned;
	
	  //创建XXX任务
	xReturned = xTaskCreate((TaskFunction_t )XXX_Task,             
							(const char*    )"XXX_Task",           
							(uint16_t       )XXX_STK_SIZE,        
							(void*          )NULL,                  
							(UBaseType_t    )XXX_TASK_PRIO,        
							(TaskHandle_t*  )&XXXTask_Handler);
							
	//判断任务是否正常创建						
	if( xReturned != pdPASS)
    {
        /* 任务创建失败  一般原因是栈空间不够 */
		vTaskDelete( XXXTask_Handler );
		/* 打印创建失败消息---使用宏定义选择性使用,一般就是调试的时候使用 */
#if 0
		printf("xxxx失败");
#endif
		
    }							
}

/*
*    任务函数
*/

void XXX_Task(void *pvParameters)
{
    while(1)
    {
		
    }
}   

2:常见问题

1:高优先级得任务必须存在阻塞状态,一个任务得大部分时间是处于阻塞状态得

2:对于新建工程以及新建任务,其任务得堆栈大小和优先级先配置为128和1,后面再调与改

3:内核控制函数

1:任务切换函数taskYIELD()

作用:切换任务(可手动切换任务)

我们知道当优先级任务相同的时候,每个任务运行的时间为一个时间片,假如我们此时的任务只需要0.5ms就可以了,不需要1ms,那么我们就可以手动切换任务了

taskYIELD() 用于请求切换上下文到另一个任务。 但是, 除非存在其他任务,其优先级等于或高于调用 taskYIELD() 的任务的优先级, 否则 RTOS 调度器将选择 调用了 taskYIELD() 的任务并使其再次运行。

2:临界段保护代码函数

//任务使用
void taskENTER_CRITICAL( void );
void taskEXIT_CRITICAL( void );
场景:很重要的代码,不允许被其他中断打断,比如我这里是数据处理,而有一个任务是数据判断
,我必须此时先处理数据才能有效,不然就浪费了一次
要求:执行代码必须要短,不能花很长时间
taskENTER_CRITICAL();
	/*执行语句代码*/
taskEXIT_CRITICAL();
//中断使用
UBaseType_t taskENTER_CRITICAL_FROM_ISR( void );
void taskEXIT_CRITICAL_FROM_ISR( UBaseType_t uxSavedInterruptStatus );
使用在中断中,与任务不同的事情是需要单独定义一个变量(模板)
使用起来与任务一样
UBaseType_t save_state;
save_state = taskENTER_CRITICAL_FROM_ISR();
	/*执行语句代码*/
taskEXIT_CRITICAL_FROM_ISR(save_state);

注意点:

临界区必须保持非常短,否则将影响 更高优先级的中断的响应时间,会导致该中断嵌套。 每次 taskENTER_CRITICAL_FROM_ISR() 调用都必须紧密配taskEXIT_CRITICAL_FROM_ISR() 调用一起使用。

不得从临界区调用 FreeRTOS API 函数

4:任务创建函数类

1:xTaskCreate

2:vTaskDelete

void vTaskDelete( TaskHandle_t xTask );//形参是句柄

INCLUDE_vTaskDelete 必须定义为 1 才能使用此函数

此函数的作用为从 RTOS 内核管理中移除任务。被删除的任务将从所有的就绪、阻塞、挂起和事件的列表中移除。

请注意,空闲任务负责从已删除任务中释放 RTOS 内核分配的内存。因此,重要的是,如果您的应用程序调用了 vTaskDelete (),空闲任务不会失去微控制器处理时间。任务代码分配的内存(相当于自己malloc的内存)不会自动释放,并且应在删除任务之前释放。

if( XXXTask_Handler != NULL )
{
	/* 这样写是防止输出重复删除任务,任务只能删除一次,不然会打印错误信息 */
	vTaskDelete( XXXTask_Handler ); 
	printf("任务删除");
	XXXTask_Handler = NULL;  //然后此任务会在空闲任务中回收资源,
	
}

5:任务控制类函数 

1:vTaskDelay

void vTaskDelay( const TickType_t xTicksToDelay );必须将 INCLUDE_vTaskDelay 定义为 1,此函数才可用

形参是多少个tick,因此不要觉得是多少个ms,只不过我们学的时候,一直是1tick就是1ms,因此初学会误认为这个函数是专门延时ms的

非周期延时

2:vTaskDelayUntil

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement 

INCLUDE_vTaskDelayUntil 必须被定义为 1 才能使用此函数

// Perform an action every 10 ticks.
 void vTaskFunction( void * pvParameters )
 {
 TickType_t xLastWakeTime;
 const TickType_t xFrequency = 10;

     // Initialise the xLastWakeTime variable with the current time.
     xLastWakeTime = xTaskGetTickCount();

     for( ;; )
     {
         // Wait for the next cycle.
         vTaskDelayUntil( &xLastWakeTime, xFrequency );

         // Perform action here.
     }
 }

周期延时

3:uxTaskPriorityGet


作用:获取任务的优先级
原型:UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );  //返回值为typedef unsigned long UBaseType_t;
返回值:优先级
使用步骤如下:
#define    INCLUDE_uxTaskPriorityGet 1

UBaseType_t TaskPriority_Num = 0;
TaskPriority_Num =  uxTaskPriorityGet( xHandle );//uxTaskPriorityGet( NULL );
printf("%ld",TaskPriority_Num);

4:vTaskPrioritySet
 

作用:改变任务的优先级
原型:void vTaskPrioritySet( TaskHandle_t xTask,
                       UBaseType_t uxNewPriority );
使用步骤如下:
#define INCLUDE_vTaskPrioritySet 1
UBaseType_t TaskNewPriority_Num = 20;  //TaskNewPriority_Num的范围为0-31(推荐是最大优先级数为32)
vTaskPrioritySet(xHandle,TaskNewPriority_Num); //vTaskPrioritySet(NULL,TaskNewPriority_Num); 

5:vTaskResume和vTaskSuspend

中断的恢复稍微复杂一点点

* 挂起和恢复函数模板使用 */
 /* 宏置一 */
//挂起不支持嵌套,多次挂起,一次恢复就可以了

//任务
vTaskResume(XXXTask_Handler); --无返回值
vTaskSuspend(XXXTask_Handler);--无返回值

//中断
	BaseType_t xYieldRequired;

    /* 恢复被挂起的任务 */ 
    xYieldRequired = xTaskResumeFromISR( XXXTask_Handler ); 

    if ( xYieldRequired == pdTRUE ) 
    { 
        /* 执行上下文切换, ISR 返回的时候将运行另外一个任务 */ 
        portYIELD_FROM_ISR(); 
    } 

6:任务实用函数(调试使用)

调试使用的函数目的:分析我们分配的堆栈空间和优先级是否符合

1:vTaskList

void vTaskList( char *pcWriteBuffer )

参数:

pcWriteBuffer   一个缓冲区, 上面提到的细节将以 ASCII 形式写入其中。假设此缓冲区 的大小足以容纳产生的报告。 大约为每个任务分配 40 字节的缓冲区就足够了。
FreeRTOS开发指南_第1张图片这一个函数基本就可以显示每个任务的基本信息了,我们一般关心的就只有Stack

X:表示运行态

你看下面的使用是很简单的,给足空间直接打印即可

FreeRTOS开发指南_第2张图片

2:vTaskGetRunTimeStats

统计运行时间和每一个任务函数运行的时间

7:队列模板使用与讲解

1:xQueueCreate

QueueHandle_t xQueue1 = NULL;
#define		QUEUE1_LENGTH	 	3
#define		QUEUE1_ITEMSIZE	 	sizeof(uint8_t)

void vATask( void *pvParameters )
{


    /* Create a queue capable of containing 10 unsigned long values. */
    xQueue1 = xQueueCreate( QUEUE1_LENGTH	 	, QUEUE1_ITEMSIZE	 	 );

    if( xQueue1 == NULL )
    {
        /* Queue was not created and must not be used. */
        vQueueDelete(xQueue1 );
        //创建失败,需要打印错误信息,一般因为空间不够而无法正确
    }

    
 }

2:xQueueSend

BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

它等同于 xQueueSendToBack()作用就是将信息送至队列(从尾部送入)

参数:

x队列  队列的句柄,数据项将发布到此队列。
pvItemToQueue  指向待入队数据项的指针。创建队列时定义了队列将保留的项的大小,因此固定数量的字节将从 pvItemToQueue 复制到队列存储区域。
xTicksToWait  如果队列已满,则任务应进入阻塞态等待队列上出现可用空间的最大时间。如果队列已满,并且 xTicksToWait 设置为0 ,调用将立即返回。时间在 tick 周期中定义,因此如果需要,应使用常量 portTICK_PERIOD_MS 转换为实时。

如果 INCLUDE_vTaskSuspend 设置为 “1” ,则将阻塞时间指定为 portMAX_DELAY 会导致任务无限期地阻塞(没有超时)。

Returns:如果成功发布,返回 pdTRUE,否则返回 errQUEUE_FULL

if( xQueueSend( xQueue1,
                       ( void * ) &ulVar,
                       ( TickType_t ) 10 ) != pdTURE )
        {
            /* Failed to post the message, even after 10 ticks. */
            //打印发送错误信息
        }

 如何学好FreeRTOS

学会看懂官网给的信息

This page describes the RTOS uxTaskPriorityGet() FreeRTOS API function which is part of the RTOS task control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers.

FreeRTOS开发指南_第3张图片

如果忘记了,重新看一遍就行,基础知识其实很少,忘记了就来查找就行

你可能感兴趣的:(FreeRTOS学习,c++,c语言,开发语言)