Zephyr RTOS -- 创建并编译一个新的工程

Posted 搬砖-工人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zephyr RTOS -- 创建并编译一个新的工程相关的知识,希望对你有一定的参考价值。

前言

本人正在学习 Zephyr,一个可移植性较强,可以兼容多种开发板及物联网设备的操作系统,如果你感兴趣,可以点此查看我的 学习笔记总述 进行了解!

 

摘要

前面已经介绍了如何搭建 Zephyr 开发环境 以及 nRF Connect SDK 开发环境 。现在来介绍一下如何创建一个新的工程。

 

1. 工程目录结构简介

在开始创建工程之前,需要先了解一下 Zephyr 项目工程的基本目录结构。

Zephyr 内核的基本目录包括内核源代码、配置选项以及内核的一些预定义编译选项。
位于应用程序目录中的文件包括应用程序的预定义(例如应用程序相关的配置选项)和应用程序的源代码,最简单形式的应用程序具有以下内容:

工程文件
├── CMakeLists.txt
├── prj.conf
└── src
         └── main.c

  • CMakeLists.txt:此文件告诉构建系统在哪里可以找到其他应用程序文件,并将应用程序目录与Zephyr 的 CMake 构建系统链接。该链接提供了 Zephyr 的构建系统支持的功能,例如特定于电路板的内核配置文件,在真实或仿真硬件上运行和调试已编译二进制文件的功能,以及更多功能。
  • 内核配置文件:应用程序通常提供一个 Kconfig 配置文件(通常称为 prj.conf),用于指定一个或多个内核配置后选项相关的值。这些应用程序设置与特定于主板的设置合并以生成内核配置。如果被忽略,则将会使用应用程序已存在的内核配置选项值;如果应用程序没有该选项值,则将会使用内核的默认配置值。
  • 应用程序源代码文件:应用程序通常会提供一个或多个由 C 或者汇编语言编写的应用程序相关的文件。这些文件通常位于一个叫做 src 的子目录中。

当然,还有关于硬件的配置文件 .overlay 文件,当需要进行相应的硬件配置时,需要用到这个文件进行修改,这样我们的目录结构就变成了下面这样:

工程文件
├── CMakeLists.txt
├── prj.conf
├── <boards>.overlay
└── src
         └── main.c

其中的 .overlay 文件的命名是根据你使用的开发板类型来的,本次使用的是 nrf52dk_nrf52832,所以 .overlay 文件的名字命名为 nrf52dk_nrf52832.overlay。当然,名称可以自定义设置,也可以添加多个 .overlay 文件,具体操作后面会进行介绍。

 

2. 创建工程文件

本次使用的是 nrf52dk_nrf52832,后续编译以此为例。

 

2.1 创建工程目录及源文件

首先,找个位置,创建你的工程文件夹。在此,我在 F 盘目录下新建一个名为 zephyr_prj 的工程文件夹。然后在该文件夹下创建一个 src 的文件夹,再在 src 的文件夹下新建一个 main.c 来存放此次的主逻辑代码:

主逻辑main.c

main.c 中添加主代码:

#include <zephyr.h>
#include <sys/printk.h>

void main(void)
{
	printk("zephyr_prj test start !!!");
}

 

2.2 创建 CMakeLists.txt 文件

src 的同级目录下新建一个 CMakeLists.txt 的文件:

工程文件夹

然后在创建的 CMakeLists.txt 的文件中添加如下内容:

cmake_minimum_required(VERSION 3.13.1)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(zephyr_prj)

target_sources(app PRIVATE src/main.c)
zephyr_include_directories(src)

上面的第一行限制了 CMake 的最低版本,第二行引入 Zephyr 编译系统,第三行创建了名字为 zephyr_prj 的工程。倒数第二行是把 src/main.c 文件加载到项目中,本次只有一个这样的源文件,如果有多个,也是通过这样的方式添加。最后一行是添加头文件(.h),如果有多个头文件目录,也是通过这样的方式添加。

至此,最小的一个项目工程就建好了,这个工程就可以进行编译下载,正常运行了。

编译运行
 

但是,这完成的是最基础,最简单的一句提示信息输出功能。

实际开发中不可能只有这么简单的需求,我们需要添加更多的功能与库,这就是到了后续的 prj.confoverlay 文件。

 

prj.conf 文件 和 .overlay 文件的作用可以理解为类似于 nRF52 系列的 sdk_config.h 文件,只是 prj.conf 文件是负责软件配置,是通过一系列的宏定义来控制某些库或者驱动的设置;而 .overlay 文件是负责硬件配置,定义你使用到的硬件及其引脚,如 UART,I2C 等。

 

2.3 创建 prj.conf 文件

CMakeLists.txt 的同级目录下新建一个 prj.conf 的文件,在该文件中进行相应的配置,这个是可选的,由于目前的工程比较简单,不需要用到额外的配置,所以可以忽略。

现在为了演示其功能,我们将 main.c 中的内容替换为如下:

#include <zephyr.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(main, 3);

void main(void)
{
	LOG_INF("zephyr_prj test start !!!");
}

该部分功能是通过 JLink 的 RTT viewer 的窗口来输出提示信息,需要打开两个宏:CONFIG_LOGCONFIG_USE_SEGGER_RTT

所以我们在新建的 prj.conf 文件中打开这两个宏:

CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y

sdk_config.h 文件不同的是,开关不是使用 10,而是 yn

配置完成之后,进行编译下载,运行,可以看到如下提示信息:

提示信息
说明设置成功!当然,有可能默认设置这两个宏是打开的,不添加也可以正常输出。这个可以通过编译后生成的文件来确认,后面会说明。

 

2.4 创建 overlay 文件

在实际项目中,系统默认板子上面的 dts 文件 (默认的硬件设置) 定义与实际应用存在差异,我们需要手动去定义使用到的硬件配置,这些是通过 .overlay 文件来实现的。

本例中没有用到 .overlay 文件,这里介绍下文件结构,假设我们要使用到 Uart,我们可以添加如下内容:

&uart0 {
	status = "okay";
	current-speed = <9600>;
	tx-pin = <25>;
	rx-pin = <24>;
};

&uart1 {
    status = "disabled";
};
&uart2 {
    status = "disabled";
};

上面的内容表示我们使用 uart0status 表示我们使用还是禁用,像 uart1 和 uart2 就是被禁用了,一般未被用到的我们最好是禁用掉,避免产生额外的功耗;current-speed 表示设置的串口波特率;下面就是一些使用的引脚设置了。
 

若在本例中,我们使用上面的 .overlay 文件,会编译不通过,报错,为什么呢?

因为本例中使用的是 nrf52dk_nrf52832,而 nrf52dk_nrf52832 上面是没有 uart1 和 uart2 的,所以我们要把这部分内容去掉。

 

2.5 创建 Konfig 文件

Kconfig 的作用是用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个 Kconfig 文件,生成配置界面供开发人员配置内核,最后生成配置文件 .config。在编译以后,配置信息会在 autoconf.h 中生成。

其实 Kconfig 来源于 Linux 系统,NCS 或者 Zephyr 对其进行了继承和定制,基本上每个模块都有自己的 Kconfig 文件,也就是说:Kconfig 文件是自带的。模块为每一个选项都设了一个默认值,如果想修改这个默认值,一般是通过 prj.conf 文件来修改 Kconfig 文件。

当然,你自己的项目模块也可以定义自己的Kconfig 文件,如何定义呢?依葫芦画瓢,可以参考其他的 Kconfig 文件来定义。这里简单介绍一下:

方法和创建 prj.conf 文件一样,也是在 CMakeLists.txt 的同级目录下新建一个 Kconfig 的文件。

 

1. config

config 表示一个配置项的开始,紧跟着的 options 为配置项名字,需要注意的是,在 Kconfig 文件中省略了前缀 CONFIG_

config EXAMPLE
	bool "help information"
	depends on EXAMPLE_ENABLE
	select  EXAMPLE_SELECT
	default y

以上面为例,介绍一下常用的一些使用方法及参数。上面代码创建了一个叫做 EXAMPLE 的配置项,类型为 bool,默认值为 y,在编译以后的代码中,最终会在 autoconf.h 中创建一个 CONFIG_EXAMPLE=y 的宏。
 

常用的值类型有:

  • bool 布尔类型,表示该 CONFIG 宏只能选择 y 或者 n
  • trisate 表示该 CONFIG 可以被设置为 yn 或者 m (编译为模块)
  • string 字符串类型,表示该 CONFIG 宏可以被设置为字符串
  • hex 十六机制,表示该宏可以被设置为十六进制数
  • int 整型,表示该宏可以被设置为一个整数
     

常见参数类型有:

  • default y 表示该宏默认值为 y,注意默认值的类型要与定义的值类型匹配,上面值类型为 bool 所以默认值可以为 y 或者 n
  • help 帮助提示信息 “help information” 就是帮助信息
  • depends on 依赖项,表示该宏依赖于另一个宏,只有在另一个宏打开的前提下,才能配置这个宏,上述代码表示,只有在 EXAMPLE_ENABLE 宏设置为 y 的时候,EXAMPLE 宏才被设置为 y
  • select 反依赖项,与 depends on 刚好相反,表示当前宏设置为 y 以后,则会自动设置另一个宏为 y,上面代码表示,在 EXAMPLE 设置为 y 的时候,EXAMPLE_SELECT 也会自动被设置为 y
  • range 设置用户输入的数据范围,如 range 0 100 表示用户数据只能为 0~100 之间。

 

2. choice

choice 定义了一组选择项,可以简单理解为一个多选一的选项,需要注意,choice 中的参数类型只能是 bool 或者 trisate

choice
	prompt "GPS device"
	default GPS_USE_SIM
	help
	  Select from which device GPS data will be fetched.

config GPS_USE_SIM
	bool "Use GPS simulator"
	help
	  Use simulated GPS data.

config GPS_USE_EXTERNAL
	bool "User provided GPS device"
	help
	  Provide a GPS device that location data will be fetched from and
	  sent to nRF CloudSAMPLE

endchoice

上述代码表示在 GPS_USE_SIMGPS_USE_EXTERNA 中选择 GPS_USE_SIMy,也就是最终生成 CONFIG_GPS_USE_SIM=y 的宏。

 

3. menu

menu 用于定义一个菜单,所有的在 “menu” … “endmenu” 之间都是 “menu sample” 的子菜单。所有的子菜单选项都继承了父菜单的依赖关系,比如,“MENU_SAMPLE” 的依赖关系就被加到了配置选项 MENU_CONFIG 的依赖列表中。

menu "menu sample"   
depends MENU_SAMPLE
config MENU_CONFIG
	bool "help information"
	default y
...
endmenu

 

4. if

if TEST_USE_SIM
config MY_DEV_NAME
	string
	default SENSOR_DEV_NAME
config ACC_TRIGGER
	bool
	default SENSOR_TRIGGER
endif

ifC 中功能基本一致,用于条件判断,只有在 ACCEL_USE_SIMy 的时候,ifendif 中的选项才会被配置。

 

5. source

source 用于读取另一个 Kconfig 文件,例如添加其他的 Kconfig 文件到当前项目中:

source "Kconfig.zephyr"

source "Kconfig.mcux"

 

3. 编译工程文件

工程配置完成之后,就可以进行接下来的步骤了:编译,烧录,运行。

编译和烧录使用的都是 west 工具。在 CMakeLists.txt 文件的同级目录下打开 cmd.exe 进行编译。

编译命令:

west build -b <board> -d <build_directory> -p

  • -b 指定开发板类型,可以通过 west boards 命令来查看支持的板类型
  • -d 指定编译目录,若不带该参数,默认存放于 build 文件夹下
  • --build-dir-d 作用一样,指定编译目录
  • -p 指示清除之前的生成文件

本次我们使用的是 nrf52dk_nrf52832,所以,使用的编译命令为:

west build -b nrf52dk_nrf52832

这个命令生成 build 文件,编译后的文件存放于其中。

 

如果我们想要使用 GUI 图形化界面来配置宏定义,我们可以再添加一个参数 -t,后面跟参数 guiconfig 或者 menuconfig。两者的区别是:menuconfig 只能通过键盘来操作,而 guiconfig 可以使用鼠标来操作。

west build -t guiconfig

如果是第一次编译的话,需要使用下面的命令,因为该命令的作用是改变工程文件生成的 build/zephyr 目录下的 .config 文件,而第一次编译时没有生成该文件,会由于找不到该文件而出错。

west build -b nrf52dk_nrf52832 -t guiconfig

执行之后还需再进行编译

west build -b nrf52dk_nrf52832

需要注意的是:
使用这种界面进行的配置只有当次编译有效,下次编译还需要重新进行配置,所以,一般建议使用 prj.conf 来永久保存配置。

 

4. 烧录工程文件

在当前的目录文件下烧录的命令为:

west flash

或者

west flash --erase

若是在别的文件夹下,需要指定烧录的文件路径:

west flash --build-dir=<build_directory>

例如在当前文件夹下指定 build 文件夹为路径:

west flash --build-dir=build

 

5. 自定义文件名

前面说过可以自定义命名 .overlay 文件,也可以添加多个 .overlay 文件。怎么实现的呢?

需要在 CMakeLists.txt 的文件中设置 DTC_OVERLAY_FILE 的变量。

例如,我们添加两个 .overlay 文件,名称分别为:file1.overlayfile2.overlay,则需要在 CMakeLists.txt 文件中设置 DTC_OVERLAY_FILE 变量:

set(
    DTC_OVERLAY_FILE
    "${CMAKE_CURRENT_SOURCE_DIR}/file1.overlay"
    "${CMAKE_CURRENT_SOURCE_DIR}/file2.overlay"
)

也可以以下面这种方式实现:

set(DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/file1.overlay")
list(APPEND DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/file2.overlay")

注意:
设置 DTC_OVERLAY_FILE 变量的设置必须放置在 find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 之前,否则不会生效!

 

当然,还有 prj.conf 文件,也可以自定义命名并添加多个 prj.conf 文件,方法和上面的添加 .overlay 文件的设置类似,只是设置的变量改为 CONFIG_FILE 即可。

 

参考链接

https://www.cnblogs.com/iini/p/14174427.html?wework_cfm_code=Nxk5htfocc87I6i8cO8pytRjq%2bkCBrRrzCeKqjs9JDP4kKdqvPCZEvnFn5xwd64UIjliDFc7qPr8XLn76T1QJRAchAacdoO/8szGgUsxdFRU

以上是关于Zephyr RTOS -- 创建并编译一个新的工程的主要内容,如果未能解决你的问题,请参考以下文章

Zephyr RTOS -- 创建并编译一个新的工程

Zephyr RTOS -- 创建并编译一个新的工程

Zephyr RTOS -- 源树结构及软硬件配置过程简介

Zephyr RTOS -- 源树结构及软硬件配置过程简介

Zephyr RTOS -- 源树结构及软硬件配置过程简介

Zephyr RTOS -- 源树结构及软硬件配置过程简介