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
中添加主代码:
#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.conf 与 overlay 文件。
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_LOG
和 CONFIG_USE_SEGGER_RTT
。
所以我们在新建的 prj.conf
文件中打开这两个宏:
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
与 sdk_config.h
文件不同的是,开关不是使用 1
和 0
,而是 y
和 n
。
配置完成之后,进行编译下载,运行,可以看到如下提示信息:
说明设置成功!当然,有可能默认设置这两个宏是打开的,不添加也可以正常输出。这个可以通过编译后生成的文件来确认,后面会说明。
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";
};
上面的内容表示我们使用 uart0,status
表示我们使用还是禁用,像 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 可以被设置为y
,n
或者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_SIM
和 GPS_USE_EXTERNA
中选择 GPS_USE_SIM
为 y
,也就是最终生成 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
if 与 C 中功能基本一致,用于条件判断,只有在 ACCEL_USE_SIM
为 y
的时候,if 和 endif 中的选项才会被配置。
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.overlay
和 file2.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 即可。
参考链接
以上是关于Zephyr RTOS -- 创建并编译一个新的工程的主要内容,如果未能解决你的问题,请参考以下文章