Zephyr v3.4.0 release中新增加了snippet功能,以此来简化原来对overlay配置文件和设备树的用法。
原来的overlay
Zephyr提供了对配置的文件和设备树的overlay,用于添加额外的配置选项,通常用于:
- 灵活的开启调试和释放版本
- 指定不同应用的配置选项
 例如一般情况下编译应用zephyr_sample为释放版本:1 west build -b esp32c3_zgp zephyr_sample/ 
它会引用zephyr_sample/prj.conf作为配置项,引用esp32c3_zgp的board下的设备树。
当我们想开启debug模式的时候,可以建立debug.conf和debug.overlay,开启debug mode并将串口重定位到uart2上1
2
3# debug.conf
CONFIG_SHELL=y
CONFIG_DEBUG=y
| 1 | debug.overlay | 
再采用如下方式重新编译就可以编译出debug版本的image1
west build -b esp32c3_zgp zephyr_sample/ -- -DDTC_OVERLAY_FILE="debug.overlay" -DOVERLAY_CONFIG="debug.conf"
这样做可以不用来回修改prj.conf和board下面设备,但当有多应用功能时就会略显麻烦,例如:
- 使用wifi: wifi.conf, wifi.overlay
- 使用eth: eth.conf, eth.overlay
- 使用大尺寸flash: size.conf, size.overlay
 如果全部开启就会变为1 west build -b esp32c3_zgp zephyr_sample/ -- -DDTC_OVERLAY_FILE="wifi.overlay" -DDTC_OVERLAY_FILE="eth.overlay" -DDTC_OVERLAY_FILE="size.overlay" -DOVERLAY_CONFIG="wifi.conf" -DOVERLAY_CONFIG="eth.conf" -DOVERLAY_CONFIG="size.conf" 
有两个问题(我是深有体会):
- 输入的命令太长
- 时间长了连命令都不记得了
snippet
zephyr v3.4.0引入了snippet可以简化overlay, 可以将snippet理解为替代overlay,一个snippet对应一组.conf和.overlay, 我们先看一组简单的使用方式:zephyr提供内置的cdc-acm-console snippet,放置在zephyr/snippets/cdc-acm-console下,提供了配置:1
2
3
4
5
6
7
8CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample"
CONFIG_USB_DEVICE_PID=0x0004
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_LINE_CTRL=y
设备树的overlay1
2
3
4
5
6
7
8
9
10
11/ {
	chosen {
		zephyr,console = &snippet_cdc_acm_console_uart;
	};
};
&zephyr_udc0 {
	snippet_cdc_acm_console_uart: snippet_cdc_acm_console_uart {
		compatible = "zephyr,cdc-acm-uart";
	};
};
当要overlay这两个文件时只用执行1
west build -b mm_swiftio -S cdc-acm-console ./zephyr_sample
是不是比下面要简洁一些:1
west build -b mm_swiftio zephyr_sample/ -- -DDTC_OVERLAY_FILE="cdc-acm-console.overlay" -DOVERLAY_CONFIG="cdc-acm-console.conf"
如何使用
snippet放置位置
在zephyr/snippets下可以增加新的snippet, 但这样会污染zephyr的主目录,同时如果只是为我们自己开发的应用使用也不方便代码管理,有两种方式
- 在app的CMakeList.txt中指定 - SNIPPET_ROOT- 1 
 2- # west构建时会从/path1和/path2去查找snippet,也可以指定一个或者更多的路径 
 set(SNIPPET_ROOT "/path1;/path2")
- 在app下建立snippets文件夹,并放置snippet - 1 
 2
 3
 4
 5
 6
 7
 8- └── zephyr_sample 
 ├── CMakeLists.txt
 ├── Kconfig
 ├── boards
 ├── prj.conf
 ├── snippets
 ├── src
 └── west.yml
- 在外部module的module.yml中添加snippet_root - 1 
 2- settings: 
 snippet_root: .
对于应用来说通常我们用第二种方法
演示
例如我们要为zephyr_sample建立一个remap-uart的snippet,当使用改snippet时调试串口会指向到uart1
- 建立zephyr_sample的snippets文件夹 - 1 
 2- └── zephyr_sample 
 ├── snippets
- 建立remap-uart文件 - 1 
 2
 3
 4- └── remap-uart 
 ├── remap-uart.conf
 ├── remap-uart.overlay
 └── snippet.yml
- 在snippet.yml中对snippet进行描述 - 1 
 2
 3
 4
 5
 6- name: remap-uart 
 boards:
 esp32c3_zgp:
 append:
 EXTRA_CONF_FILE: remap-uart.conf
 EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay- name: snippet的名字
- boards: 对esp32c3_zgp这种开发板生效
- EXTRA_CONF_FILE: 配置文件
- EXTRA_DTC_OVERLAY_FILE: 设备树文件
 
- EXTRA_CONF_FILE/EXTRA_DTC_OVERLAY_FILE文件内容 - 1 
 2
 3- # remap-uart.conf 
 # 启用kernel shell
 SHELL_KERNEL=y
| 1 | /* remap-uart.overlay */ | 
5 使用
构建时加上-S remap-uart后console和shell都通过uart输出1
west build -b esp32c2_zgp -S remap-uart ./zephyr_sampe
指定board
前面示例看到可以通过boards指定不同的board生效的不同的snippet,例如1
2
3
4
5
6
7
8
9
10name: remap-uart
boards:
  esp32c3_zgp:
    append:
      EXTRA_CONF_FILE: remap-uart.conf
      EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
  esp32c3_devkit:
    append:
      EXTRA_CONF_FILE: remap-uart-kit.conf
      EXTRA_DTC_OVERLAY_FILE: remap-uart-kit.overlay
也可以使用正则表达式指定同类的board生效相同的snippet,例如1
2
3
4
5
6name: remap-uart
boards:
  /esp32c3_*/:
    append:
      EXTRA_CONF_FILE: remap-uart.conf
      EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
还可以不指定board,对所有board都生效相同的snippet,例如1
2
3
4name: remap-uart
    append:
      EXTRA_CONF_FILE: remap-uart.conf
      EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
多snippet
当我们制作了多个snippet,例如最前面的有wifi,eth,debug,那么构建的时候就使用1
west build -b mm_swiftio -S wifi -S eth -s debug ./zephyr_sampe
实现分析指引
zephyr/scripts/west_commands/build.py 收集-S参数加入到-DSNIPPET中zephyr/cmake/modules/zephyr_default.cmake 使用list(APPEND zephyr_cmake_modules snippets) 加载zephyr\cmake\modules\snippets.cmake执行zephyr_process_snippetszephyr_process_snippets查找SNIPPET_ROOT并根据-DSNIPPET生成requested_snippet_argszephyr_process_snippets调用zephyr/scripts/snippets.py将requested_snippet_args转化为build\zephyr\snippets_generated.cmakesnippets_generated.cmake中设置EXTRA_CONF_FILE和EXTRA_DTC_OVERLAY_FILEzephyr/cmake/modules/kconfig.cmake引用EXTRA_CONF_FILEzephyr/cmake/modules/dts.cmake引用EXTRA_DTC_OVERLAY_FILE
例如remap-uart例子中生成的snippets_generated.cmake如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17set(SNIPPET_NAMES "cdc-acm-console" "remap-uart")
# The paths to all the snippet.yml files. One snippet
# can have multiple snippet.yml files.
set(SNIPPET_PATHS "/mnt/e/book/sample/zephyr/snippets/cdc-acm-console/snippet.yml" "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/snippet.yml")
# Create variable scope for snippets build variables
zephyr_create_scope(snippets)
###############################################################################
# Snippet 'remap-uart'
# Common variable appends.
# Appends for board 'esp32c3_zgp'
if("${BOARD}" STREQUAL "esp32c3_zgp")
  zephyr_set(EXTRA_CONF_FILE "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/remap-uart.conf" SCOPE snippets APPEND)
  zephyr_set(EXTRA_DTC_OVERLAY_FILE "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/remap-uart.overlay" SCOPE snippets APPEND)
endif()
参考
https://docs.zephyrproject.org/latest/build/snippets/index.html
