Skip to content

QuecOpen 开发框架详解

QuecOpen 架构

QuecOpen 是移远为 RTOS 模组提供的嵌入式 C 开发框架,让开发者直接在模组内部运行自定义应用程序。

QuecOpen 软件架构:
  ┌─────────────────────────────────────────┐
  │           用户应用程序(C 代码)           │
  │  ql_app_main() 入口函数                  │
  ├─────────────────────────────────────────┤
  │           QuecOpen SDK                  │
  │  ┌──────────┐ ┌──────────┐ ┌─────────┐ │
  │  │ 网络 API  │ │ 外设 API  │ │ 系统 API│ │
  │  └──────────┘ └──────────┘ └─────────┘ │
  ├─────────────────────────────────────────┤
  │           RTOS 内核(ThreadX)           │
  │  任务调度 / 信号量 / 消息队列 / 定时器    │
  ├─────────────────────────────────────────┤
  │           基带固件                       │
  │  蜂窝协议栈 / AT 指令处理                │
  └─────────────────────────────────────────┘

开发环境搭建

工具链安装

bash
# Windows 开发环境
# 1. 下载移远 QuecOpen SDK(从开发者中心)
# 2. 安装 ARM GCC 工具链
#    下载:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain
# 3. 安装 CMake
# 4. 安装 Python 3(用于构建脚本)

# Linux 开发环境
sudo apt-get install gcc-arm-none-eabi cmake python3

# 验证工具链
arm-none-eabi-gcc --version

SDK 目录结构

QuecOpen_SDK/
├── components/         # 系统组件
│   ├── kernel/         # RTOS 内核
│   ├── net/            # 网络协议栈
│   └── drivers/        # 硬件驱动
├── include/            # 头文件
│   ├── ql_api_common.h
│   ├── ql_api_datacall.h
│   ├── ql_api_http.h
│   └── ...
├── lib/                # 预编译库
├── examples/           # 示例代码
│   ├── hello_world/
│   ├── tcp_client/
│   ├── mqtt_demo/
│   └── ...
└── tools/              # 编译和烧录工具
    ├── build.py
    └── flash.py

编译示例

bash
# 进入示例目录
cd QuecOpen_SDK/examples/mqtt_demo

# 编译
python3 ../../tools/build.py

# 输出文件
ls output/
# mqtt_demo.bin  # 应用程序固件

# 烧录到模组
python3 ../../tools/flash.py --port COM3 --file output/mqtt_demo.bin

任务(Task)管理

QuecOpen 基于 RTOS,支持多任务并发:

c
#include "ql_api_common.h"
#include "ql_rtos.h"

// 任务句柄
ql_task_t sensor_task_handle;
ql_task_t upload_task_handle;

// 共享数据(使用互斥锁保护)
ql_mutex_t data_mutex;
float g_temperature = 0.0f;

// 传感器采集任务
void sensor_task(void *param) {
    while (1) {
        // 读取传感器
        float temp = read_adc_temperature();
        
        // 加锁更新共享数据
        ql_rtos_mutex_lock(data_mutex, QL_WAIT_FOREVER);
        g_temperature = temp;
        ql_rtos_mutex_unlock(data_mutex);
        
        QL_APP_LOG("SENSOR", QL_LOG_LEVEL_INFO, "Temp: %.1f", temp);
        
        // 每5秒采集一次
        ql_rtos_task_sleep_ms(5000);
    }
}

// 数据上传任务
void upload_task(void *param) {
    // 等待网络连接
    wait_network_ready();
    
    while (1) {
        // 读取共享数据
        ql_rtos_mutex_lock(data_mutex, QL_WAIT_FOREVER);
        float temp = g_temperature;
        ql_rtos_mutex_unlock(data_mutex);
        
        // 上传数据
        upload_to_server(temp);
        
        // 每60秒上传一次
        ql_rtos_task_sleep_ms(60000);
    }
}

// 应用入口
void ql_app_main(void) {
    // 创建互斥锁
    ql_rtos_mutex_create(&data_mutex);
    
    // 创建任务
    ql_rtos_task_create(
        &sensor_task_handle,
        "sensor_task",
        sensor_task,
        NULL,
        4096,   // 栈大小(字节)
        5       // 优先级(数字越小优先级越高)
    );
    
    ql_rtos_task_create(
        &upload_task_handle,
        "upload_task",
        upload_task,
        NULL,
        8192,
        10
    );
}

消息队列

c
#include "ql_rtos.h"

// 消息类型定义
typedef struct {
    int type;
    float value;
    uint32_t timestamp;
} SensorMessage;

ql_queue_t msg_queue;

// 生产者:传感器任务
void sensor_producer(void *param) {
    while (1) {
        SensorMessage msg = {
            .type = 1,
            .value = read_temperature(),
            .timestamp = ql_rtos_get_tick()
        };
        
        // 发送消息到队列
        ql_rtos_queue_send(msg_queue, &msg, sizeof(msg), 0);
        
        ql_rtos_task_sleep_ms(1000);
    }
}

// 消费者:处理任务
void data_consumer(void *param) {
    SensorMessage msg;
    
    while (1) {
        // 等待消息(阻塞)
        if (ql_rtos_queue_recv(msg_queue, &msg, sizeof(msg), 
                               QL_WAIT_FOREVER) == QL_OSI_SUCCESS) {
            // 处理消息
            process_sensor_data(&msg);
        }
    }
}

void ql_app_main(void) {
    // 创建消息队列(最多 10 条消息)
    ql_rtos_queue_create(&msg_queue, sizeof(SensorMessage), 10);
    
    // 创建任务
    ql_rtos_task_create(&sensor_task, "sensor", sensor_producer, NULL, 4096, 5);
    ql_rtos_task_create(&consumer_task, "consumer", data_consumer, NULL, 8192, 10);
}

定时器

c
#include "ql_rtos.h"

ql_timer_t heartbeat_timer;

// 定时器回调(在 RTOS 定时器上下文中执行,不能阻塞)
void heartbeat_callback(void *param) {
    // 发送心跳包(通过消息队列通知任务)
    int msg = MSG_HEARTBEAT;
    ql_rtos_queue_send(cmd_queue, &msg, sizeof(msg), 0);
}

void ql_app_main(void) {
    // 创建周期定时器(每30秒触发一次)
    ql_rtos_timer_create(
        &heartbeat_timer,
        "heartbeat",
        heartbeat_callback,
        NULL,
        30000,          // 周期(毫秒)
        QL_TIMER_AUTO   // 自动重载
    );
    
    // 启动定时器
    ql_rtos_timer_start(heartbeat_timer);
}

文件系统操作

c
#include "ql_fs.h"

// 写入配置文件
void save_config(const char *key, const char *value) {
    int fd = ql_fopen("config.json", "w");
    if (fd < 0) return;
    
    char buf[256];
    snprintf(buf, sizeof(buf), "{\"%s\":\"%s\"}", key, value);
    ql_fwrite(buf, strlen(buf), 1, fd);
    ql_fclose(fd);
}

// 读取配置文件
int load_config(char *buf, int buf_size) {
    int fd = ql_fopen("config.json", "r");
    if (fd < 0) return -1;
    
    int n = ql_fread(buf, 1, buf_size - 1, fd);
    buf[n] = '\0';
    ql_fclose(fd);
    return n;
}

// 查看文件系统使用情况
void check_storage(void) {
    ql_fs_info_t info;
    ql_fs_statfs("/", &info);
    
    QL_APP_LOG("FS", QL_LOG_LEVEL_INFO,
               "Total: %d KB, Free: %d KB",
               info.total_size / 1024,
               info.free_size / 1024);
}

褚成志的笔记