一张纸了解freertos的使用(1)

本文致力于精简的语言介绍,freertos的使用。对于其背后的原理,不做太多的解释。

只针对有一定基础的

只针对有一定基础的

只针对有一定基础的

任务创建与删除

第一节创建任务

创建任务时可以使用2个函数:动态分配内存、静态分配内存。

动态分配内存

	xTaskCreate(RTC_Task, "RTCTask", 128, NULL, osPriorityNormal, NULL);

静态分配内存

 

使用静态分配内存的函数如下:

TaskHandle_t xTaskCreateStatic (  
    TaskFunction_t pxTaskCode,   // 函数指针, 任务函数 
    const char * const pcName,   // 任务的名字 
    const uint32_t ulStackDepth, // 栈大小,单位为word,10表示40字节 
    void * const pvParameters,   // 调用任务函数时传入的参数 
    UBaseType_t uxPriority,      // 优先级 
    StackType_t * const puxStackBuffer, // 静态分配的栈,就是一个buffer 
    StaticTask_t * const pxTaskBuffer // 静态分配的任务结构体的指针,用它来操作这个任务 
);

 动态与静态区别

静态要其定义一个  

StackType_t * const puxStackBuffer, // 静态分配的栈,就是一个buffer 

 怎么写?

static uint8_t g_pusStackOfLightTask[128*4];
static StaticTask_t g_TCBofLightTask;

/*
其他的省略
*/
xTaskCreateStatic(函数,"任务名",128,NULL,优先级,g_pusStackOfLightTask,&g_TCBofLightTask);

第二节任务的删除 

void vTaskDelete( TaskHandle_t xTaskToDelete ); 

第三节任务优先级

使用uxTaskPriorityGet来获得任务的优先级:

UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); 
//使用参数xTask来指定任务,设置为NULL表示获取自己的优先级。

使用vTaskPrioritySet 来设置任务的优先级:

void vTaskPrioritySet( TaskHandle_t xTask, 
UBaseType_t uxNewPriority );
/*
使用参数xTask来指定任务,设置为NULL表示设置自己的优先级; 
参数uxNewPriority 表示新的优先级,取值范围是0~(configMAX_PRIORITIES – 1)。
*/

任务状态

我们可以把任务简单的分为:运行态 和 非运行态。

在非运行态可以分为:

  1. 阻塞状态(Blocked)
  2. 暂停状态(Suspended)
  3.  就绪状态(Ready)

 阻塞状态

核心是等待

  1. 等待一件事情发生(不如中断,写入队列,同步)
  2. 等待时间(等5s)

 暂停状态

进入暂停状态
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
参数xTaskToSuspend 表示要暂停的任务,如果为NULL,表示暂停自己。
退出暂停状态 

只能由别人来操作

只能由别人来操作

只能由别人来操作

  1. 别的任务调用:vTaskResume
  2. 中断程序调用:xTaskResumeFromISR

 就绪状态(Ready)

这个任务完全准备好了,随时可以运行:只是还轮不到它。这时,它就处于就绪态(Ready)

两个Delay 函数 

vTaskDelay

至少等待指定个数的Tick Interrupt才能变为就绪状态

void vTaskDelay( const TickType_t xTicksToDelay ); /* xTicksToDelay: 等待多少给Tick */

 示例:

vTaskDelay(500)

vTaskDelayUntil

等待到指定的绝对时刻,才能变为就绪态。

/* pxPreviousWakeTime: 上一次被唤醒的时间 
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime + xTimeIncrement) 
* 单位都是Tick Count 
*/ 
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, 
const TickType_t xTimeIncrement ); 


 示例:

TickType_t xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
//先获得当前时间

//执行的代码

vTaskDelayUntil( &xLastWakeTime, 1000);

同步互斥与通信

不想介绍概念了

实现同步互斥的内核方法

  1. 任务通知(task notification)
  2. 队列(queue)
  3. 事件组 (event group)
  4. 信号量(semaphoe)
  5. 互斥量(mutex)。

队列(queue)

大家应该都知道队列是啥吧?

我们直接开整!!!

队列函数

动态创建

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize ); 

 示例:

QueueHandle_t Test_Queue;
struct input_data
{
	uint32_t del;
	uint16_t  val;
	
};

/* 创建Test_Queue */
  Test_Queue = xQueueCreate(10,sizeof(struct input_data));
  if(NULL != Test_Queue)
    printf("创建Test_Queue消息队列成功!\r\n");

静态创建

QueueHandle_t xQueueCreateStatic( 
                           UBaseType_t uxQueueLength, 
                           UBaseType_t uxItemSize, 
                           uint8_t *pucQueueStorageBuffer, 
                           StaticQueue_t *pxQueueBuffer 
                       );

示例代码:

// 示例代码 
 #define QUEUE_LENGTH 10 
 #define ITEM_SIZE sizeof( uint32_t ) 
  
 // xQueueBuffer用来保存队列结构体 
 StaticQueue_t xQueueBuffer; 
  
 // ucQueueStorage 用来保存队列的数据 
 // 大小为:队列长度 * 数据大小 
 uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ]; 
  
 void vATask( void *pvParameters ) 
 { 
 QueueHandle_t xQueue1;
// 创建队列: 可以容纳QUEUE_LENGTH个数据,每个数据大小是ITEM_SIZE 
 xQueue1 = xQueueCreateStatic( QUEUE_LENGTH, 
        ITEM_SIZE, 
        ucQueueStorage, 
        &xQueueBuffer );  
 }

复位 

队列刚被创建时,里面没有数据;使用过程中可以调用xQueueReset()把队列恢复为 初始状态,此函数原型为:

/* pxQueue : 复位哪个队列; 
 * 返回值: pdPASS(必定成功) 
 */ 
BaseType_t xQueueReset( QueueHandle_t pxQueue); 

删除

删除队列的函数为vQueueDelete(),只能删除使用动态方法创建的队列,它会释放内 存。原型如下:

void vQueueDelete( QueueHandle_t xQueue ); 

写队列

可以把数据写到队列头部,也可以写到尾部,这些函数有两个版本:在任务中使用、在 ISR中使用。

往队列尾部写入数据

任务中使用
/*  
等同于xQueueSend
 * 往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait 
*/ 
BaseType_t xQueueSendToBack( 
                                QueueHandle_t    xQueue, 
                                const void       *pvItemToQueue, 
                                TickType_t       xTicksToWait 
                            ); 
中断中使用
/*  
 * 往队列尾部写入数据,此函数可以在中断函数中使用,不可阻塞 
 */ 
BaseType_t xQueueSendToBackFromISR( 
                                      QueueHandle_t xQueue, 
                                      const void *pvItemToQueue, 
                                      BaseType_t *pxHigherPriorityTaskWoken 
                                   ); 

往队列头部写入数据

任务中使用
*  
 * 往队列头部写入数据,如果没有空间,阻塞时间为xTicksToWait 
 */ 
BaseType_t xQueueSendToFront( 
                                QueueHandle_t    xQueue, 
                                const void       *pvItemToQueue, 
                                TickType_t       xTicksToWait 
                            );
中断中使用
/*  
 * 往队列头部写入数据,此函数可以在中断函数中使用,不可阻塞 
 */ 
BaseType_t xQueueSendToFrontFromISR( 
                                      QueueHandle_t xQueue, 
                                      const void *pvItemToQueue, 
                                      BaseType_t *pxHigherPriorityTaskWoken 
                                   );

示例:

extern QueueHandle_t Test_Queue;
struct input_data idata;
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
idata.dev=0;
idata.val=0;
xReturn=xQueueSend(Test_Queue,&idata,0);
if(pdPASS == xReturn)
        printf("消息send_data1发送成功!\n\n");

读队列 

使用xQueueReceive()函数读队列,读到一个数据后,队列中该数据会被移除。这个 函数有两个版本:在任务中使用、在ISR中使用。

在任务中使用

BaseType_t xQueueReceive( QueueHandle_t xQueue, 
                          void * const pvBuffer, 
                          TickType_t xTicksToWait ); 

在ISR中使用

BaseType_t xQueueReceiveFromISR( 
                                    QueueHandle_t    xQueue, 
                                    void             *pvBuffer, 
                                    BaseType_t       *pxTaskWoken 
                                );

示例:

 xReturn = xQueueReceive( Test_Queue,    /* 消息队列的句柄 */
                             &i_data,      /* 发送的消息内容 */
                             portMAX_DELAY); /* 等待时间 一直等 */
    if(pdTRUE == xReturn)
      printf("本次接收到的数据是%d\n\n",r_queue);
    else
      printf("数据接收出错,错误代码0x%lx\n",xReturn);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值