12 Variable Unified Management

一、Table of content (TOC)

简单的类比,TOC是一个存储了集团所有客户电话号码的号码薄,不同的分公司使用统一的注册机制,将客户电话写到该电话簿上,集团商务部门可以以一定频率通过遍历号码薄,与所有客户逐个通信,为客户推送信息或接受客户反馈.

在该工程中TOC是一张烧录在flash连续空间上的地址表,地址表内存储了来自不同源文件需要监控的变量名字、类型和地址(组成一个结构体).Crazyflie有两个TOC,PARAM 和 LOG,用于承载不同的功能.上位机通过获取TOC,获取全部已经注册的变量(名字、类型和地址),使用CRTP协议通过该变量地址实时查看或修改对应变量值.

The aim of the logging and parameter framework is to easily be able to log data from the Crazyflie and to set variables during runtime. Logging and parameter frameworksarrow-up-right

二、 PARAM_GROUP

  1. 把变量加入PARAM_GROUP,方便从外部进行修改(支持设置读写权限),大大加速调试过程(该机制仅写到ram,重启后变成默认值).

  2. 支持使用{组名.变量名}访问变量:if you would like to set the effect variable in the ring group it's accessed using ring.effect.

  3. 可以在任意时刻访问和修改变量 The reading or writing of a parameter can be done at any time once you are connected to the Crazyflie.

  4. 读写没有线程安全保护:There's no thread protection on reading/writing. Since the architecture is 32bit and the largest parameter you can have is 32bit it's safe to write one variable. But if you write a group of variables that should be used together (like PID parameters) you might end up in trouble.

  5. 在访问运行期变化的变量时,推荐使用LOG_GROUP:Only use the parameter framework to read variables that are set during start-up. If variables change during runtime then use the logging framework.

1. 宏定义

/* Macros */
#define PARAM_ADD(TYPE, NAME, ADDRESS) \
   { .type = TYPE, .name = #NAME, .address = (void*)(ADDRESS), },

#define PARAM_ADD_GROUP(TYPE, NAME, ADDRESS) \
   { \
  .type = TYPE, .name = #NAME, .address = (void*)(ADDRESS), },

#define PARAM_GROUP_START(NAME)  \
  static const struct param_s __params_##NAME[] __attribute__((section(".param." #NAME), used)) = { \
  PARAM_ADD_GROUP(PARAM_GROUP | PARAM_START, NAME, 0x0)

#define PARAM_GROUP_STOP(NAME) \
  PARAM_ADD_GROUP(PARAM_GROUP | PARAM_STOP, stop_##NAME, 0x0) \
  };

2. 源文件中,将全局变量添加到PARAM TOC的方法

按照宏定义展开:

相当于创建了一个结构体(param_s)数组,该数组包含4个成员,其中第1个和第4个用于标记该组变量的头和尾,每个结构体有三个成员(type、name、address)

使用__attribute__((section(".param.stabilizer"), used)) 将该数组放在指定名为".param.stabilizer"的段.

3. 把源文件".param."##NAME 段映射到地址连续区域

3.1 esp_idf链接脚本生成器

esp_idf从v3.3开始,支持在component层级控制最后的链接阶段,使用Linker Script Generationarrow-up-right机制,在component里添加一个xx.lf文件.

在编译系统中使用xx.lf

按照规定的语法填写内容:

脚本生成器将xx.lf转换成gcc任何的链接片段: 该链接片段将被添加到链接文件,形成当前工程的链接规则.

3.2 直接修改框架的链接脚本

ESPlane2.0版本基于release/v3.3分支编写,该分支下链接脚本生成机制 1. 不支持添加一个地址的引用(添加一个入口)? 2. 不支持添加对齐指令? 因此临时跳过了使用链接脚本工具生成链接脚本,而是直接修改默认的链接脚本(不推荐,需要后期调整),(位置在/components/esp32/ld/esp32.project.ld.in)修改如下:

KEEP(*(.param)) KEEP(*(.param.*))可以将所有带有.param的分段,统一映射到drom0_0_seg的.flash.rodata

3.3 链接脚本修改效果

map

查看编译输出的.map文件可以找到.param.stabilizer,为第2部分宏定义添加的结构体数组,该数组包含4个元素,每个元素大小为12,占用大小为0x30字节

3.4 程序如何遍历该变量地址表

读取:

写入:写入到ram,掉电不保存

三、 LOG_GROUP

  1. 把变量加入LOG_GROUP,可以从上位机监控变量的变化:The logging framework is used to log variables from the Crazyflie at a specific interval.

  2. 上位机下载TOC并完成设置,将收到Crazyflie主动push的数据:Instead of triggering a reading of the variables at certain intervals, the framework is used to set up a logging configuration to that will push data from the Crazyflie to the host.

  3. The interval for a logging configuration is specified in 10th of milliseconds.

1. 源文件中,将全局变量添加到LOG TOC的方法

四、 通过上位机读取TOC并监视变量

获取TOC
监视变量

最后更新于