找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3188

积分

1

好友

430

主题
发表于 11 小时前 | 查看: 1| 回复: 0

在物联网设备与传感器网络中,序列化技术是设备间数据传输与通信的基石。Zephyr RTOS 为开发者提供了多种数据序列化子系统,方便在通信过程中对结构化数据进行编码与解码。你可以根据项目需求选择最合适的格式,从而有效提升开发效率和系统性能。

Zephyr 主要支持以下三种序列化工具:

  • CBOR (Concise Binary Object Representation):一种高效的二进制数据序列化格式,特别适合资源受限的物联网设备,以其高效率和简洁性著称。
  • JSON (JavaScript Object Notation):广为人知的轻量级数据交换格式,易于阅读和编写,在网络通信中应用广泛。
  • Nanopb:专为嵌入式系统设计的轻量级 Protocol Buffers 实现,支持高效的二进制数据编码和解码。

CBOR 和 Nanopb 在 Zephyr 中作为第三方模块集成,而自带的 JSON API 使用也相对简单。因此,本文将重点解析这些模块在 Zephyr 中的整合配置原理与方法,具体的 API 使用细节,你可以直接参考 Zephyr 源码中的示例代码。

序列化工具对比

在选择工具前,一个清晰的对比能帮助你快速决策。下表详细列出了 Zephyr 支持的三种序列化工具的核心特性:

维度 JSON CBOR Nanopb (Protobuf for MCU)
序列化类型 文本 (Text) 二进制 (Binary) 二进制 (Binary)
是否自描述 是 (字段名) 是 (字段类型 + 键) 否 (依赖 .proto)
可读性 极好 较差 极差
数据体积 100% ~50–70% ~20–40%
编解码性能 1x 3x 5–10x
内存占用 极低
是否需要 Schema 否 (可选) 是 (必须)
代码复杂度 最低
Zephyr module 否 (内置,Intel) 是 (zcbor,Nordic) 是 (nanopb,Google)
典型应用 Web / API IoT / CoAP MCU / RTOS

CBOR

CBOR 的使用示例可以参考 Zephyr 源码中的 zephyr/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c 文件。

配置与编译控制

CBOR 的代码由 west 工具管理,位于 modules/lib/zcbor 目录下。要启用 zcbor 功能,你需要在项目配置中开启:

CONFIG_ZCBOR=y

Zephyr 通过 zephyr/modules/zcbor/CMakeLists.txt 文件控制编译过程。该文件会根据上述配置添加相应的源文件,并将 Zephyr 的 Kconfig 配置项映射为 ZCBOR 的宏定义:

if(CONFIG_ZCBOR)
  zephyr_include_directories(
    ${ZEPHYR_ZCBOR_MODULE_DIR}/include
  )

  zephyr_library()
  zephyr_library_sources(
    ${ZEPHYR_ZCBOR_MODULE_DIR}/src/zcbor_common.c
    ${ZEPHYR_ZCBOR_MODULE_DIR}/src/zcbor_decode.c
    ${ZEPHYR_ZCBOR_MODULE_DIR}/src/zcbor_encode.c
    ${ZEPHYR_ZCBOR_MODULE_DIR}/src/zcbor_print.c
  )

  zephyr_library_compile_definitions(_POSIX_C_SOURCE=200809L)

  zephyr_compile_definitions_ifdef(CONFIG_ZCBOR_CANONICAL ZCBOR_CANONICAL)
  zephyr_compile_definitions_ifdef(CONFIG_ZCBOR_STOP_ON_ERROR ZCBOR_STOP_ON_ERROR)
  zephyr_compile_definitions_ifdef(CONFIG_ZCBOR_VERBOSE ZCBOR_VERBOSE)
  zephyr_compile_definitions_ifdef(CONFIG_ZCBOR_ASSERT ZCBOR_ASSERTS)
  zephyr_compile_definitions_ifdef(CONFIG_ZCBOR_BIG_ENDIAN ZCBOR_BIG_ENDIAN)
endif()

Kconfig 配置选项

zcbor 的配置选项定义在 zephyr/modules/zcbor/Kconfig 中,主要包括:

  • ZCBOR_CANONICAL: 启用规范化 CBOR 编码,禁止不定长的 list/map,并在解码时强制校验 canonical 规则。
  • ZCBOR_STOP_ON_ERROR: 允许在发生错误时立即中止执行。
  • ZCBOR_VERBOSE: 允许 zcbor 通过 printf 输出调试或日志信息。
  • ZCBOR_ASSERT: 启用 zcbor 内部的断言检查。
  • ZCBOR_BIG_ENDIAN: 指示目标平台为大端字节序。
  • ZCBOR_MAX_STR_LEN: 为 zcbor_tstr_put_term() 函数提供默认的最大字符串长度(默认为 256,但不推荐直接使用此默认值)。

JSON

配置与实现

JSON 功能由 Zephyr 原生提供,代码由 Intel 贡献,相关文件位于 zephyr/include/zephyr/data/json.hzephyr/lib/utils/json.c。配置 CONFIG_JSON_LIBRARY=y 后,json.c 会被加入构建。如果项目需要序列化浮点数,则还需额外配置 CONFIG_JSON_LIBRARY_FP_SUPPORT=y

使用方法

Zephyr 原生 JSON 库的使用遵循三个基本步骤:

  1. 定义数据结构:从 json.h 头文件中选取合适的宏来生成数据结构的描述符。
  2. 编码:根据描述符的类型,调用相应的编码函数进行序列化。
  3. 解码:根据描述符的类型,调用相应的解码函数进行反序列化。

zephyr/include/zephyr/data/json.h 中每个 API 都有详细的描述和简短示例。更全面的使用范例可以参考 zephyr/tests/lib/json/src/main.c,它几乎涵盖了所有可能的使用场景。

Nanopb

Nanopb 是 Google Protocol Buffers 的 C语言 实现,专为高效的数据序列化与反序列化设计,尤其适合资源受限的嵌入式系统环境。

其 API 的使用方法可以参考 zephyr/samples/modules/nanopb 示例,下文将重点介绍在 Zephyr 项目中的配置方法。

配置

安装依赖:在 Ubuntu 系统下,需要安装 protocol buffer 编译器:

sudo apt install protobuf-compiler

Zephyr 在编译 .proto 文件时使用 Python 脚本,会优先调用 grpcio-tools 包进行处理。如果找不到该包,则会回退使用系统中安装的 protoc 程序。通常,按照官方步骤搭建 Zephyr 开发环境时,grpcio-tools 已被包含,因此一般无需额外安装。

要启用 Nanopb,必须在配置中设置 CONFIG_NANOPB=y。配置生效后,zephyr/modules/nanopb/CMakeLists.txt 中的编译逻辑才会执行。

编译配置

配置生效后,上述 CMakeLists.txt 会将 Nanopb 的源代码加入编译,并根据 Zephyr 的 Kconfig 选项生成对应的 Nanopb 宏定义:

if(CONFIG_NANOPB)
  set(NANOPB_DIR ${ZEPHYR_CURRENT_MODULE_DIR})

  zephyr_library()
  zephyr_library_sources(
    ${NANOPB_DIR}/pb_common.c
    ${NANOPB_DIR}/pb_encode.c
    ${NANOPB_DIR}/pb_decode.c
  )

  zephyr_include_directories(${NANOPB_DIR})

  zephyr_compile_definitions(
    PB_MAX_REQUIRED_FIELDS=${CONFIG_NANOPB_MAX_REQUIRED_FIELDS})

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_ENABLE_MALLOC
    PB_ENABLE_MALLOC
  )

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_NO_ERRMSG
    PB_NO_ERRMSG
  )

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_BUFFER_ONLY
    PB_BUFFER_ONLY
  )

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_WITHOUT_64BIT
    PB_WITHOUT_64BIT
  )

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_ENCODE_ARRAYS_UNPACKED
    PB_ENCODE_ARRAYS_UNPACKED
  )

  zephyr_compile_definitions_ifdef(
    CONFIG_NANOPB_VALIDATE_UTF8
    PB_VALIDATE_UTF8
  )
endif()

Kconfig 配置选项

Zephyr 为 Nanopb 提供了 6 个布尔配置项,它们与 Nanopb 原生宏的对应关系如下:

  • CONFIG_NANOPB_ENABLE_MALLOC : PB_ENABLE_MALLOC - 启用解码时的动态内存分配(malloc)支持。适用于字段长度不固定的场景,但会增加内存碎片风险和代码体积。
  • CONFIG_NANOPB_NO_ERRMSG : PB_NO_ERRMSG - 关闭详细的错误字符串输出,仅返回成功/失败的布尔值。可以显著减少代码体积,适合资源极度受限且不需要详细错误信息的场合。
  • CONFIG_NANOPB_BUFFER_ONLY : PB_BUFFER_ONLY - 只支持内存 buffer 的编码/解码,禁用自定义流(如UART、文件流)。以此换取更快的速度和更小的代码体积
  • CONFIG_NANOPB_WITHOUT_64BIT : PB_WITHOUT_64BIT - 禁用 int64 / uint64 / fixed64 等 64 位字段的支持,以节省代码空间。
  • CONFIG_NANOPB_ENCODE_ARRAYS_UNPACKED : PB_ENCODE_ARRAYS_UNPACKED - 将标量数组编码为非 packed 格式(会占用更多字节)。仅在对端解码器不支持 packed arrays(例如某些旧版本的 protobuf.js)时才需要使用。
  • CONFIG_NANOPB_VALIDATE_UTF8 : PB_VALIDATE_UTF8 - 对接收到的 string 类型字段进行 UTF-8 合法性校验,提高数据安全性,但会引入少量的 CPU 和代码体积开销。

值配置项

  • CONFIG_NANOPB_MAX_REQUIRED_FIELDS : PB_MAX_REQUIRED_FIELDS - 设置 proto2 语法中 required 字段的最大检查数量。用于解码后校验是否所有必填字段都已出现。数值越大,占用的 RAM 越多(默认/最小值为 64)。

Nanopb 配置方法

在应用层使用 Nanopb 需要以下步骤:

  1. 导入 CMake 模块:在你的应用 CMakeLists.txt 文件中添加以下内容:

    list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb)
    include(nanopb)
  2. 添加 proto 文件:使用 zephyr_nanopb_sources() 函数来添加你的 .proto 文件。这能确保生成的头文件和源文件在构建目标之前被正确创建:

    zephyr_nanopb_sources(app src/simple.proto)
  3. 配置生成选项:Nanopb 允许通过生成选项来配置消息或字段,例如设置固定大小或跳过某些字段。这可以通过 .options.in 文件和 CMake 变量来完成。

示例 proto 文件 (simple.proto):

syntax = "proto3";

message SimpleMessage {
int32 lucky_number = 1;
bytes buffer = 2;
int32 unlucky_number = 3;
}

假设你想控制 buffer 字段的最大大小,并选择性地跳过 unlucky_number 字段,可以创建一个 simple.options.in 文件。其配置方式与标准 Nanopb 一致,Zephyr 的 CMake 脚本会负责解析它:

SimpleMessage.buffer max_size:@CONFIG_SAMPLE_BUFFER_SIZE@ fixed_length:true
SimpleMessage.unlucky_number type:@unlucky_number_type@

注意其中使用了 @Keyword@ 的引用格式:

  • @CONFIG_SAMPLE_BUFFER_SIZE@
  • @unlucky_number_type@

这里的 CONFIG_SAMPLE_BUFFER_SIZE 是直接引用 Kconfig 中的整数值,例如:

config SAMPLE_BUFFER_SIZE
    int "Simple message buffer size"
    default 8
    help
        Configure the simple message buffer field's size.

@unlucky_number_type@ 则需要通过 CMake 变量来设置,它在 CMakeLists.txt 中定义:

if(CONFIG_SAMPLE_UNLUCKY_NUMBER)
  set(unlucky_number_type "FT_DEFAULT")
else()
  set(unlucky_number_type "FT_IGNORE")
endif()

总结

在 Zephyr 技术栈中,JSON、CBOR 和 Nanopb 这三种序列化工具各有千秋。JSON 最适合需要高可读性或与 Web 服务交互的场景;CBOR 在二进制效率与一定自描述性之间取得了平衡,是许多 IoT 协议的选择;而 Nanopb 则提供了最高的编码效率和最小的数据体积,非常适合 MCU 间或对带宽、功耗有极致要求的通信。

选择哪种工具,取决于你的具体需求:是追求开发便利,还是极致的性能与资源利用。希望本文的对比与配置指南能帮助你在 Zephyr 项目中做出更合适的技术选型。如果你想深入探讨更多嵌入式系统设计或 RTOS 相关话题,欢迎访问云栈社区进行交流。

参考




上一篇:Go、Rust、Node.js 性能对决:百万请求下,为何最快语言反输在尾延迟?
下一篇:Linux系统加固实战配置与安全策略详解(CentOS/Rocky Linux 8)
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-7 19:22 , Processed in 0.338410 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表