参数配置基础:配置文件格式、命名规范与值类型

做固件开发这些年,我见过太多因为参数配置不规范引发的惨案。有一次,一个同事把 JSON 里的布尔值写成了字符串 "true",结果解析器死活不认,整块板子启动到一半就挂了。排查了整整一个下午,最后发现就是多了一对引号。

所以这一章,咱们把参数配置的基础打牢。说白了,就是三件事:选对文件格式、起好参数名字、搞清楚值的类型和范围。

2.1 三种主流配置文件格式

嵌入式世界里,INI、JSON、DTB 是出场率最高的三位。我个人的习惯是:简单场景用 INI,复杂嵌套用 JSON,跟硬件打交道用 DTB。

2.1.1 INI 格式

INI 是最朴素的键值对存储方式。结构简单,人类可读性极好。你想想看,一个刚入行的工程师也能一眼看懂。

; boot_config.ini
[BOOT]
mode=normal
timeout=5
console=ttyS0

[NETWORK]
dhcp=1
ip_addr=192.168.1.100
netmask=255.255.255.0

INI 的缺点也很明显——不支持嵌套,没有类型系统。所有值都是字符串。我在项目中遇到过用 INI 存 MAC 地址列表的情况,最后不得不自己写解析器,挺折腾的。

我的建议:INI 适合存放少于 20 个参数的简单配置。如果参数之间有层级关系,趁早换 JSON。

2.1.2 JSON 格式

JSON 是目前最通用的配置格式。它原生支持嵌套、数组、多种数据类型。我做的自动化打包工具,核心配置全部用 JSON。

{
  "boot": {
    "mode": "normal",
    "timeout": 5,
    "console": "ttyS0",
    "fallback": ["recovery", "safe"]
  },
  "network": {
    "dhcp": true,
    "ip_addr": "192.168.1.100",
    "netmask": "255.255.255.0"
  }
}

注意看,这里的 timeout 是数字,dhcp 是布尔值,fallback 是数组。解析器能直接识别类型,不用你手动转换。

踩坑提醒:JSON 不允许注释。我曾经在配置文件里写了一大段说明,结果解析器直接报错。后来我改用字段名自解释,或者在打包脚本里加注释。

2.1.3 DTB 格式

DTB(Device Tree Blob)是 Linux 内核和 bootloader 之间的硬件描述语言。它不像 INI 和 JSON 那样是纯文本,而是编译后的二进制文件。

源文件是 DTS,编译后生成 DTB。我刚开始接触时觉得这东西很神秘,后来发现它本质上就是个树形结构的键值对数据库。

/dts-v1/;
/ {
    model = "MyBoard v2";
    compatible = "vendor,myboard-v2";

    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2";
    };

    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x10000000>;
    };
};

DTB 的优势在于:它跟内核代码解耦,改硬件配置不用重新编译内核。我在一个项目里,靠修改 DTB 里的内存映射,让同一套固件适配了三种不同容量的 Flash 芯片。

2.2 参数命名规范

命名这件事,看起来简单,做起来全是坑。我见过用中文拼音命名的,见过全大写加下划线的,也见过驼峰和蛇形混用的。每次接手这种项目,我都想骂人。

这里给出我多年总结的三条铁律:

  • 全小写 + 下划线:这是嵌入式领域最通用的风格。比如 boot_timeout、eth0_mac。
  • 命名即注释:参数名要能自解释。别用 t1、val 这种,用 uart_baudrate、flash_erase_count。
  • 统一前缀:同一模块的参数用相同前缀。比如网络相关都用 net_,存储相关都用 storage_。

反面教材(我真实见过):

a=115200        // 啥意思?
B=1             // 开还是关?
ccc=192.168.1.1 // 什么地址?

正确写法:

uart_baudrate=115200
dhcp_enable=1
ntp_server=192.168.1.1

2.3 参数值类型与范围

参数值类型搞错了,轻则配置不生效,重则系统崩溃。我见过最离谱的一次,有人把 timeout 设成了 -1,结果看门狗直接不工作了。

常见的参数值类型就这几种:

类型 示例 说明 常见坑
整数 timeout=5 无符号或有符号整型 溢出、负数、超出范围
布尔 dhcp=true true/false 或 1/0 字符串 "true" 不等于布尔 true
字符串 console="ttyS0" 固定长度或可变长度 编码问题、特殊字符转义
枚举 mode=normal 从预定义集合中取值 拼写错误、大小写不匹配
IP 地址 ip=192.168.1.1 点分十进制 格式校验、子网掩码匹配
MAC 地址 mac=AA:BB:CC:DD:EE:FF 6 字节十六进制 分隔符不一致、大小写

关于范围校验,我个人的做法是:在打包脚本里做一次,在固件启动时再做一次。双重保险,绝不信任任何输入。

实用技巧:在 JSON Schema 里定义每个参数的类型和范围,打包前自动校验。比如 timeout 的范围是 1-30,mode 只能是 normal/recovery/safe 三者之一。

2.4 知识体系总览

下面这张图,把本章的核心逻辑串起来了。你从左上角开始看,顺着箭头走一遍,就能明白参数配置的全貌。

参数配置知识体系 INI 格式 JSON 格式 DTB 格式 参数命名规范:全小写 + 下划线 | 命名即注释 | 统一前缀 整数 布尔 字符串 枚举 范围校验:打包脚本校验 + 固件启动校验(双重保险) 核心原则:选对格式 → 规范命名 → 明确类型 → 校验范围

2.5 实战中的选择策略

说了这么多,到底怎么选?我给出一个简单的决策流程:

  1. 参数少于 30 个,没有嵌套关系 → 用 INI。简单直接,解析代码也少。
  2. 参数有层级,需要数组或对象 → 用 JSON。灵活,工具链成熟。
  3. 描述硬件拓扑,给内核用 → 用 DTB。没得选,这是标准。
  4. 混合场景 → 我习惯用 JSON 做应用层配置,DTB 做硬件层配置,各管各的。
曾经踩过的坑:在一个项目里,我把网络配置写进了 DTB,结果每次改 IP 地址都要重新编译 DTB 并烧录。后来改成 JSON 配置文件挂载到 /config 分区,改配置只需要重启服务,省事多了。

嗯,这一章的内容就这些。记住:配置文件格式选对了,命名规范了,类型和范围搞清楚了,后面自动化打包才能跑得顺畅。别在这些基础问题上翻车,不值得。