Zephyr out of tree board

前言

  • 在Zephyr中使用west工具进行编译时,会从zephyr/boards目录下寻找用户输入的board,查找成功后再继续进行后续工作,但是在一些情况下,现存的board中存在的配置并不能满足需求,或是使能了一些不需要的功能,这种情况下我们通常需要根据硬件新建board。
  • 通常可以在zephyr/boards目录下新建board并添加设备树和kconfig文件,west运行后会根据board名称查找对应的文件夹,将其中的文件添加到编译系统中。
  • 这种方式虽然可以满足我们的需求,但是增加的文件位于内核源码树下,会引起内核源码变动,但是该变动通常不会进行提交,在多人协同开发时,所使用的内核源码与官方的保持一致,一般不会修改内核源码,如果想要所有人都能编译通过,就需要对内核源码添加补丁,后期如果更换内核版本,还需要添加新的补丁上去,因此该方法存在一定局限性。
  • 理想的方式是在app目录下可以添加board,然后通过提供的api将board到构建系统中,使其可以在不更改内核源码的情况下添加board。

自定义 board 目录

  • Zephyr 支持源码树外添加 board,可以参考 zephyr/doc/develop/application/index.rst 文件的 Custom Board, Devicetree and SOC Definitions 章节。

目录结构

	boards/
	soc/
	CMakeLists.txt
	prj.conf
	README.rst
	src/
  • soc 目录下保存了soc相关的代码,此处可以省略,我们所使用的soc是Zephyr中已经存在的SOC。
  • boards 目录下保存了自定义的开发板配置,目录结构如下:
   .
   ├── boards
   │   └── x86
   │       └── my_custom_board
   │           ├── doc
   │           │   └── img
   │           └── support
   └── src
  • my_custom_board 为自定义开发板的名称,doc和support可以省略,但是提交到Zephyr时必须要有。
  • boards 目录下首先需要有一个架构文件夹,可用的架构与内核源码树下 boards 文件夹下一致,需根据芯片所属架构进行添加,如果没有将自定义的板子放在对应的架构文件夹下会提示查找失败。
  • 下面是 my_custom_board 中的文件:
	my_custom_board_defconfig
    my_custom_board.dts
    my_custom_board.yaml
    board.cmake
    board.h
    CMakeLists.txt
    doc/
    Kconfig.board
    Kconfig.defconfig
    pinmux.c
    support/

添加目录至构建系统

  • 文件添加好之后需要将board的路径添加到编译系统中,在CMake中通过 BOARD_ROOT 变量来识别外部的board目录,该变量可以通过命令行传递参数,也可以通过在app中定义 BOARD_ROOT 进行设置,但是两种方式有所区别,通过命令行定义的变量可以是绝对路径和相对路径,而在app中的CMakeLists.txt中 定义的 BOARD_ROOT 变量必须是绝对路径。
  • 下面是 boards.cmake 从 BOARD_ROOT 查找板级目录的代码:
foreach(root ${BOARD_ROOT})
  # Check that the board root looks reasonable.
  if(NOT IS_DIRECTORY "${root}/boards")
    message(WARNING "BOARD_ROOT element without a 'boards' subdirectory:
${root}
Hints:
  - if your board directory is '/foo/bar/boards/<ARCH>/my_board' then add '/foo/bar' to BOARD_ROOT, not the entire board directory
  - if in doubt, use absolute paths")
  endif()

  # NB: find_path will return immediately if the output variable is
  # already set
  if (BOARD_ALIAS)
    find_path(BOARD_HIDDEN_DIR
      NAMES ${BOARD_ALIAS}_defconfig
      PATHS ${root}/boards/*/*
      NO_DEFAULT_PATH
      )
    if(BOARD_HIDDEN_DIR)
      message("Board alias ${BOARD_ALIAS} is hiding the real board of same name")
    endif()
  endif()
  if(BOARD_DIR AND NOT EXISTS ${BOARD_DIR}/${BOARD}_defconfig)
    message(WARNING "BOARD_DIR: ${BOARD_DIR} has been moved or deleted. "
                    "Trying to find new location."
    )
    set(BOARD_DIR BOARD_DIR-NOTFOUND CACHE PATH "Path to a file." FORCE)
  endif()
  find_path(BOARD_DIR
    NAMES ${BOARD}_defconfig
    PATHS ${root}/boards/*/*
    NO_DEFAULT_PATH
    )
  if(BOARD_DIR AND NOT (${root} STREQUAL ${ZEPHYR_BASE}))
    set(USING_OUT_OF_TREE_BOARD 1)
  endif()
endforeach()
  • 上面的代码会在 BOARD_ROOT 变量存在时从对应的目录下查找是否存在 boards 子目录,然后查找对应自定义板子的 defconfig 文件确定板级目录。
  • 查找到板级目录后会根据板级目录的路径确认板子所属架构,如果查找不到对应的架构,终止编译并报错:
/* BOARD_DIR 的上一级目录作为 arch 目录 */
cmake_path(GET BOARD_DIR PARENT_PATH board_arch_dir)
/* board_arch_dir 去掉前缀仅保留文件名作为芯片的架构  */
cmake_path(GET board_arch_dir FILENAME ARCH)

/* 查找该架构是否在支持的列表中 */
foreach(root ${ARCH_ROOT})
  if(EXISTS ${root}/arch/${ARCH}/CMakeLists.txt)
    set(ARCH_DIR ${root}/arch)
    break()
  endif()
endforeach()

/* 终止编译并报错 */
if(NOT ARCH_DIR)
  message(FATAL_ERROR "Could not find ARCH=${ARCH} for BOARD=${BOARD}, \
please check your installation. ARCH roots searched: \n\
${ARCH_ROOT}")
endif()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕咚.萌西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值