目录

1. 命名前缀系统概述

2. 核心前缀详解

2.1 'v' 前缀 - 无返回值函数

2.2 'x' 前缀 - 返回 BaseType_t(通常是 pdTRUE/pdFALSE)

2.3 'pv' 前缀 - 返回指针 (pointer to void)

2.4 'ux' 前缀 - 返回无符号整数 (unsigned)

2.5 'pc' 前缀 - 返回字符指针 (pointer to character)

3. 函数名称中的其他关键部分

3.1 "FromISR" 后缀

3.2 "ToWait" 或 "Wait" 部分

3.3 "Give" 和 "Take" 操作

4. 返回值和错误处理模式

4.1 通用返回模式

4.2 特定函数的返回值

4.3 中断安全函数返回值

5. 实际应用示例

5.1 完整任务创建示例

5.2 队列操作完整示例

6. 前缀选择决策树

7. 最佳实践总结


1. 命名前缀系统概述

FreeRTOS 采用一套严格的命名前缀系统,通过前缀字母直接反映函数的返回类型和行为特征。这套系统遵循匈牙利命名法的思想,但专门为 FreeRTOS 进行了优化。

2. 核心前缀详解

2.1 'v' 前缀 - 无返回值函数

含义: void - 无返回值

特点:

  • 执行操作但不返回状态

  • 通常用于配置、初始化或简单操作

  • 不能用于条件判断

// 示例
void vTaskDelay( TickType_t xTicksToDelay );  // 任务延时
void vTaskStartScheduler( void );             // 启动调度器
void vTaskSuspend( TaskHandle_t xTaskToSuspend ); // 挂起任务

// 使用场景
vTaskDelay(pdMS_TO_TICKS(100));  // 延时100ms

2.2 'x' 前缀 - 返回 BaseType_t(通常是 pdTRUE/pdFALSE)

含义: 返回 BaseType_t 类型,表示操作成功/失败或布尔状态

返回类型BaseType_t

  • 通常定义为 long 或 int32_t

  • 宏定义值:pdTRUE (1) / pdFALSE (0) 或 pdPASS (1) / pdFAIL (0)

特点:

  • 用于需要返回成功/失败状态的操作

  • 可用于条件判断

  • 在 FreeRTOS 配置文件中可定义 BaseType_t 的具体类型

// 创建任务函数 - 返回是否成功
BaseType_t xTaskCreate( 
    TaskFunction_t pvTaskCode,
    const char * const pcName,
    uint16_t usStackDepth,
    void *pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t *pxCreatedTask
);

// 队列发送函数 - 返回是否成功
BaseType_t xQueueSend(
    QueueHandle_t xQueue,
    const void * pvItemToQueue,
    TickType_t xTicksToWait
);

// 使用示例
BaseType_t xReturn = xQueueSend(xQueue, &data, portMAX_DELAY);
if (xReturn == pdPASS) {
    // 发送成功
} else {
    // 发送失败
}

2.3 'pv' 前缀 - 返回指针 (pointer to void)

含义: 返回 void 指针或特定类型的指针

返回类型void * 或其他指针类型

特点:

  • 返回动态分配的内存地址

  • 需要进行类型转换后才能使用

  • 需要检查返回值是否为 NULL

// 内存分配 - 返回分配内存的指针
void *pvPortMalloc( size_t xSize );

// 获取任务存储指针
void *pvTaskGetThreadLocalStoragePointer( 
    TaskHandle_t xTaskToQuery, 
    BaseType_t xIndex 
);

// 使用示例
int *pxArray = (int *)pvPortMalloc(10 * sizeof(int));
if (pxArray != NULL) {
    // 内存分配成功
    pxArray[0] = 100;
    vPortFree(pxArray);  // 记得释放
}

2.4 'ux' 前缀 - 返回无符号整数 (unsigned)

含义: 返回无符号整数值,通常是计数值或大小

返回类型UBaseType_tuint32_t 或其他无符号整数

特点:

  • 返回计数、大小、优先级等非负数值

  • 不能用于失败判断(除非0有特殊含义)

// 获取队列中等待的项目数
UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );

// 获取系统任务数量
UBaseType_t uxTaskGetNumberOfTasks( void );

// 获取任务优先级
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );

// 使用示例
UBaseType_t uxMessages = uxQueueMessagesWaiting(xQueue);
if (uxMessages > 0) {
    // 队列中有数据
}

2.5 'pc' 前缀 - 返回字符指针 (pointer to character)

含义: 返回字符串(字符数组)指针

返回类型char *

特点:

  • 返回任务名称等字符串

  • 通常指向静态存储区,不应修改

  • 不需要释放内存

// 获取任务名称
char *pcTaskGetName( TaskHandle_t xTaskToQuery );

// 使用示例
TaskHandle_t xHandle;
char *pcName = pcTaskGetName(xHandle);
printf("Task name: %s\n", pcName);

3. 函数名称中的其他关键部分

3.1 "FromISR" 后缀

含义: 该函数可以在中断服务例程(ISR)中调用

特点:

  • 不会导致任务切换

  • 通常有一个 pxHigherPriorityTaskWoken 参数

  • 需要在ISR末尾根据返回值判断是否需要上下文切换

// 中断中发送队列数据
BaseType_t xQueueSendFromISR(
    QueueHandle_t xQueue,
    const void *pvItemToQueue,
    BaseType_t *pxHigherPriorityTaskWoken
);

// 使用示例
void vSerialISR(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    BaseType_t xResult;
    
    xResult = xQueueSendFromISR(xQueue, &data, &xHigherPriorityTaskWoken);
    
    if (xResult == pdPASS) {
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}

3.2 "ToWait" 或 "Wait" 部分

含义: 函数会阻塞等待,直到条件满足或超时

参数: 通常有 xTicksToWait 参数指定超时时间

BaseType_t xQueueReceive(
    QueueHandle_t xQueue,
    void *pvBuffer,
    TickType_t xTicksToWait  // 阻塞等待时间
);

3.3 "Give" 和 "Take" 操作

含义: 用于信号量、互斥锁等同步原语

// 获取信号量(阻塞)
BaseType_t xSemaphoreTake(
    SemaphoreHandle_t xSemaphore,
    TickType_t xTicksToWait
);

// 释放信号量
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);

4. 返回值和错误处理模式

4.1 通用返回模式

// x前缀函数通常的返回值模式
#define pdPASS     (1)   // 操作成功
#define pdFAIL     (0)   // 操作失败

// 用于布尔判断
#define pdTRUE     (1)   // 真
#define pdFALSE    (0)   // 假

4.2 特定函数的返回值

// 任务创建函数
BaseType_t xTaskCreate(...);
// 返回值:pdPASS - 创建成功,pdFAIL - 创建失败(通常内存不足)

// 队列操作
BaseType_t xQueueSend(...);
// 返回值:pdPASS - 发送成功,errQUEUE_FULL - 队列满(当阻塞时间为0时)

// 信号量操作
BaseType_t xSemaphoreTake(...);
// 返回值:pdTRUE - 获取成功,pdFALSE - 超时或失败

4.3 中断安全函数返回值

// FromISR 函数的特殊返回值
BaseType_t xQueueSendFromISR(...);
// 返回值:pdTRUE - 发送成功,errQUEUE_FULL - 队列满
// 注意:pxHigherPriorityTaskWoken 参数可能被设为 pdTRUE

// 在ISR中使用
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xStatus = xQueueSendFromISR(xQueue, &data, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
    portYIELD_FROM_ISR(pdTRUE);  // 执行上下文切换
}

5. 实际应用示例

5.1 完整任务创建示例

// 任务函数
void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 任务逻辑
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

// 创建任务
BaseType_t xTaskCreateExample(void) {
    TaskHandle_t xHandle = NULL;
    BaseType_t xReturn;
    
    xReturn = xTaskCreate(
        vTaskFunction,      // 任务函数
        "ExampleTask",      // 任务名称
        1024,               // 堆栈大小(字)
        NULL,               // 参数
        1,                  // 优先级
        &xHandle           // 任务句柄
    );
    
    if (xReturn == pdPASS) {
        printf("Task created successfully, handle: %p\n", xHandle);
        return pdTRUE;
    } else {
        printf("Failed to create task\n");
        return pdFALSE;
    }
}

5.2 队列操作完整示例

// 定义数据结构
typedef struct {
    uint32_t id;
    int32_t value;
} SensorData_t;

// 创建队列
QueueHandle_t xCreateDataQueue(void) {
    QueueHandle_t xQueue;
    
    xQueue = xQueueCreate(
        10,                     // 队列长度
        sizeof(SensorData_t)    // 每个项目大小
    );
    
    if (xQueue == NULL) {
        printf("Failed to create queue\n");
        return NULL;
    }
    
    return xQueue;
}

// 发送数据
BaseType_t xSendDataToQueue(QueueHandle_t xQueue, SensorData_t *pxData) {
    BaseType_t xReturn;
    
    // 等待最多100ms
    xReturn = xQueueSend(xQueue, pxData, pdMS_TO_TICKS(100));
    
    if (xReturn == pdPASS) {
        printf("Data sent successfully\n");
    } else {
        printf("Failed to send data (queue full or timeout)\n");
    }
    
    return xReturn;
}

// 接收数据
BaseType_t xReceiveDataFromQueue(QueueHandle_t xQueue, SensorData_t *pxBuffer) {
    BaseType_t xReturn;
    
    // 无限等待
    xReturn = xQueueReceive(xQueue, pxBuffer, portMAX_DELAY);
    
    if (xReturn == pdPASS) {
        printf("Received data: id=%lu, value=%ld\n", 
               pxBuffer->id, pxBuffer->value);
    }
    
    return xReturn;
}

6. 前缀选择决策树

需要创建函数?考虑:
├─ 返回任务/队列/信号量句柄?
│  └─ 函数名以创建对象类型开头,如 xTaskCreate, xQueueCreate
│
├─ 执行操作无返回?
│  └─ 使用 v 前缀,如 vTaskDelay
│
├─ 需要返回成功/失败?
│  └─ 使用 x 前缀,返回 BaseType_t
│
├─ 返回指针(内存/数据)?
│  ├─ 返回字符串? → pc 前缀
│  └─ 返回其他指针? → pv 前缀
│
└─ 返回计数值/大小?
   └─ 使用 ux 前缀,返回 UBaseType_t

7. 最佳实践总结

  1. 始终检查 x 前缀函数的返回值

    BaseType_t xResult = xFunctionCall();
    if (xResult != pdPASS) {
        // 错误处理
    }
  2. pv 前缀函数返回的指针必须检查 NULL

    void *pvBuffer = pvFunctionCall();
    if (pvBuffer == NULL) {
        // 内存分配失败处理
    }
  3. ux 前缀函数的返回值通常用于计算或判断,注意边界条件

  4. FromISR 函数只能在中断中使用,并正确处理 pxHigherPriorityTaskWoken

  5. pc 前缀返回的字符串通常是只读的,不要尝试修改

  6. v 前缀函数不返回值,不能用于条件判断

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐