Zephyr物联网操作系统初识(一):硬件准备与开发环境配置

1.前言

19年 底实验室协助某公司完成磁控胶囊胃镜胶囊机器人的开发工作,我们主要负责图像压缩算法的设计与实现。其中算法运行载体为Nordic公司的nrf52840芯片。nrf52840传统的开发方式主要是基于Nordic公司发布的SDK以及相应协议栈进行开发,通常为裸机,较少搭载操作体统(仅个人见解)。之前有师兄在新思科技参与了zyphyr操作系统的设计与开发,我也是通过他分享的公众号文章了解到的这一操作系统。当前物联网技术正悄然无声地改变着我们的生活,从智能门锁到共享单车,从智能家居到智慧城市,其中都能看到蓝牙设备的身影。因此我也觉得在这个时代浪潮下,有必要了解一下蓝牙协议、物联网操作系统的相关知识。一点点小私心:我是一位自行车骑行爱好者,了解到诸多设备如码表、心率带、功率计等等都是基于Nordic公司的芯片开发的。我偶尔也在想这些设备是否能够通过某些技术手段进一步挖掘其价值以更好的服务我们的生活。关于华为LiteOS操作系统也会在文中有所提及。

参考文档:
Zephyr项目主页:https://www.zephyrproject.org/
Zephyr代码:https://github.com/zephyrproject-rtos/zephyr
nRF52840-MDK开发板文档:https://wiki.makerdiary.com/nrf52840-mdk/cn/
nRF52840-MDK代码:https://github.com/makerdiary/nrf52840-mdk

2.硬件准备

我选用的开发板是nRF52840-MDK,是Zephyr支持的众多开发板之一,你也可以选择其他的开发板进行学习,不过我个人建议选择一款成熟度高、资料丰富、应用广泛的开发板,这样在你后续的学习过程中可以避免很多“坑”。
nRF82840-MDK硬件

2.1 简介

nRF52840-MDK 是一个小巧而功能丰富、开箱即用的物联网开发套件,基于 Nordic 高端系统级芯片 nRF52840,可支持 Bluetooth 5、Bluetooth Mesh、Thread、IEEE 802.15.4、ANT 等无线协议,同时带有片上 Arm CryptoCell 加密子系统,是目前面向多协议无线物联网的理想解决方案。

nRF52840-MDK 集成了多功能调试器 Arm Mbed DAPLink,提供“拖放式”下载固件、USB CDC 虚拟串口、CMSIS-DAP 仿真等功能。

nRF52840-MDK 还板载了来自 Microchip 的两端口 USB 2.0 高速集线器,只需一个 USB 接口即可同时使用 DAPLink 和 nRF52840 的 USB 设备控制器。同时还搭载了 64Mbit 超低功耗 QSPI FLASH、可编程按键、RGB LED、晶片天线及外部天线连接器等硬件资源。

nRF52840-MDK 支持跨平台开发,可以玩转多种开源软件框架(如:nRF5 SDK, Mesh, OpenThread, ZigBee 3.0, Mbed OS 5, Zephyr, Mynewt, iBeacon, Eddystone, Web Bluetooth 等等),并且提供丰富的在线文档及示例,帮助你加速物联网应用开发。

2.2 硬件规格

  • Nordic 高端系统级芯片 nRF52840
    • ARM® Cortex®-M4F 内核
    • 1MB FLASH,256kB RAM
    • 支持 Bluetooth 5、Bluetooth Mesh、Thread、IEEE 802.15.4、ANT 等无线协议
    • 片上 NFC-A 标签
    • USB 2.0 设备控制器
    • ARM TrustZone® Cryptocell 310 加密子系统
  • 板载 Arm Mbed DAPLink 多功能调工具:
    • MSC - 支持“拖放式”下载固件
    • CDC - 提供虚拟串口工具
    • HID - 兼容 CMSIS-DAP 仿真功能
  • Microchip 两端口 USB 2.0 高速集线器
  • 板载 64Mbit 超低功耗 QSPI FLASH
  • 拥有 多达 24 个可编程 GPIO
  • IF Boot/Reset 按钮
  • 用户可编程按钮和 RGB LED
  • 板载 2.4G 晶片天线
  • U.FL 连接器可用于选择外部天线
  • 3.3V 稳压器,高效率、低静态电流、可输出 1A 峰值电流
  • VBUS & VIN 电源路径管理
  • 可正反面连接的 USB 3.1 Type-C 接口
  • 2.54mm 标准引脚间距,可直接安装在面包板上
  • 尺寸小巧 50mm x 23mm x 13mm (已焊排针)

2.3 引脚位置图

nRF52840-MDK引脚位置图

2.4 软件资源

nRF52840-MDK 支持多种软件框架及协议:

框架/协议简介
nRF5 SDKNordic 官方提供的 SDK
nRF5 SDK for MeshNordic 官方提供的低功耗蓝牙 Mesh 网络 SDK
OpenThreadNest 开源实现的 Thread® 网络协议
Arm Mbed OSArm 开源的物联网实时操作系统
ZephyrLinux 基金会开源的物联网实时操作系统
MynewtApache 开源模块化的实时操作系统,专门为内存和存储都极其有限而又要以极低功耗运行非常长时间的物联网设备设计
Arm Mbed DAPLinkArm Mbed 针对 Arm Cortex 系列 CPU 开源 CMSIS-DAP 多功能调试器
Web Bluetooth基于 Web 的低功耗蓝牙 API
iBeaconApple 实现的 Beacon 协议
EddystoneGoogle 开源的 Beacon 协议

可以看到这个开发板支持Zephyr框架。

2.5 硬件资源

版本设计文档
V1.0nRF52840-MDK V1.0 Pinout Diagram
nRF52840-MDK V1.0 Schematic
nRF52840-MDK V1.0 Board File
nRF52840-MDK V1.0 3D STEP

遗憾的是这些资料都是指PDF文档,PCB文件并没有开源。

3.初识Zephyr

3.1 简介

Zephyr OS 是专门为资源受限设备构建、针对低功耗、小型内存微处理器设备而进行优化的物联网嵌入式小型、可扩展的实时操作系统(RTOS),支持多种硬件架构及多种开发板(包括 ARM Cortex-M, Intel x86, ARC, NIOS II, Tensilica Xtensa, 以及 RISC-V),甚至可以在小至 8kB 内存的系统上运行。

Zephyr 内核相比其他实时操作系统内核具有许多优势:

  • 单一地址空间:应用程序代码和内核代码都在单个共享地址空间中执行
  • 高度可配置:允许应用程序只包含所需的功能,并指定它们的数量和大小。
  • 编译时资源定义:允许在编译时定义系统资源,从而减少代码大小并提高性能。
  • 最小的错误检查:提供最少的运行时错误检查,以减少代码大小并提高性能。提供了一个可选的错误检查基础结构来帮助在应用程序开发过程中进行调试。
  • 广泛的服务套件:为软件开发提供多种服务,如多线程服务、中断服务、线程间的同步服务、线程间的数据传递服务、电源管理服务。

了解更多细节,可以访问 Zephyr Project 官网。

3.2 快速入门

克隆Zephyr源码
Zephyr OS 源码已经托管在 GitHub 上,可以直接克隆使用:
$ git clone https://github.com/zephyrproject-rtos/zephyr.git

搭建开发环境
Zephyr 项目使用 CMake 工具管理和编译项目。 CMake 可以用来生成编译文件,然后使用 make 或 ninja 进行编译,这是比较常规的做法。

Windows环境搭建
参考zephyr官方文档进行安装,安装过程中的第三步,获取zephyr源码过程可能会很漫长,我这里进行了修改:

cd %HOMEPATH%
west init zephyrproject
cd zephyrproject
west update
--->
cd %HOMEPATH%
west init zephyrproject -w https://gitee.com/caizhi_969/zephyr.git
cd zephyrproject
west update

其中,gitee https是我复制的库,这样下载速度会有明显的提升,另外,开发板的HAL和一些lib是通过module的形式集成到zephyr中的,即zephyr源码中未包含这部分内容,需要使用west update这样的命令进行安装,我在windows中下载实际体验也是非常的慢。不过巧合的是 半夜在ubuntu环境下配置环境异常顺利,因此一些很难update的部分,直接将ubunut环境中的文件拷至windows相应目录下,已经测试可行。west update背后原理我还不是很清楚,不知道有没有其他更新module的方式。

3.3 编译运行第一个示例

cd %HOMEPATH%\zephyrproject\zephyr
west build -p auto -b <your-board-name> samples\basic\blinky

west build指令会在当前目录下创建build目录,编译过程文件和最终的可执行文件都会在这个目录下,<your-board-name>替换你的开发板名,如我的是nrf52840_mdk,你可以通过查看zephyr兼容的开发板确定自己的型号,如果这个参数你不太确定也没有关系,会有相应的错误提示的,你应该可以从zephyr\boards\目录下找到你开发板的名字。

第一个示例构建过程的小插曲:第一次构建过程由于写错的开发板名,导致构建过程中断。再次构建前请注意删除build目录以及zephyr.cache目录,否则会出现Assertion failed: The toolchain is unable to build a dummy C file. See CMakeError.log.这个错误,我在nordic社区上也找到别人反馈的同样的问题

3.4 其他例程编译与运行

基础例程

例程名硬件/接口描述
blink_ledPWM-LED变频率的LED闪烁
blinkyGPIO-LED恒频率LED闪烁
buttonGPIO中断按键灯,松键灯灭
fade_ledPWM-LEDPWM脉宽调制
minimal空main()测试zephyr内核最小大小,见下方输出
rgb_led3*PWM-LEDRGB LED颜色逐渐变化
servo_motorPWM舵机控制,板子上没有这个接口,暂时没有测试
threadsK_THREAD_DEFINE多线程、线程优先级、堆大小
F:\Zephyr>west build -p auto -b nrf52840_mdk zephyr\samples\basic\minimal
-- west build: making build dir F:\Zephyr\build pristine
-- west build: generating a build system
Including boilerplate (Zephyr base): F:/Zephyr/zephyr/cmake/app/boilerplate.cmake
-- Application: F:/Zephyr/zephyr/samples/basic/minimal
-- Zephyr version: 2.2.99 (F:/Zephyr/zephyr)
-- Found Python3: C:/Python38/python.exe (found suitable exact version "3.8.2") found components: Interpreter
-- Board: nrf52840_mdk
-- Found west: C:/Python38/Scripts/west.exe (found suitable version "0.7.2", minimum required is "0.7.1")
-- Found dtc: C:/ProgramData/chocolatey/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
-- Found toolchain: gnuarmemb (c:/gnuarmemb)
-- Found BOARD.dts: F:/Zephyr/zephyr/boards/arm/nrf52840_mdk/nrf52840_mdk.dts
-- Generated zephyr.dts: F:/Zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_unfixed.h: F:/Zephyr/build/zephyr/include/generated/devicetree_unfixed.h
Parsing F:/Zephyr/zephyr/Kconfig
Loaded configuration 'F:/Zephyr/zephyr/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig'
Configuration saved to 'F:/Zephyr/build/zephyr/.config'
Kconfig header saved to 'F:/Zephyr/build/zephyr/include/generated/autoconf.h'
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- The ASM compiler identification is GNU
-- Found assembler: C:/gnuarmemb/bin/arm-none-eabi-gcc.exe
-- Cache files will be written to: F:/Zephyr/zephyr/.cache
-- Configuring done
-- Generating done
-- Build files have been written to: F:/Zephyr/build
-- west build: building application
[120/125] Linking C executable zephyr\zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       12316 B         1 MB      1.17%
            SRAM:        3960 B       256 KB      1.51%
        IDT_LIST:          56 B         2 KB      2.73%
[125/125] Linking C executable zephyr\zephyr.elf

sample-board-nrf

例程名硬件/接口描述
batteryADC测量开发板供电电压,放电曲线估算时间,打印内容如下
mesh蓝牙未测试
nrfxGPIOTE DPPI演示zephyr中nrfx lib的使用,未测试,n91开发板
system_off功耗测试、deep sleep,没太看明白
[0:00:00.009]: 3362 mV; 8747 pptt
[0:00:04.981]: 3362 mV; 8747 pptt
[0:00:09.953]: 3362 mV; 8747 pptt
[0:00:14.923]: 3362 mV; 8747 pptt
[0:00:19.893]: 3361 mV; 8742 pptt

bluetooth

例程名硬件/接口描述
beacon2.4G RadioBLE广播
centralBLE中心点,根据信号强度自动建立连接,查看打印信息,在不停的连接与断开
central_hrBLE中心点,自动连接心率设备并读取心率值,尝试用心率带进行连接,但是没太看明白
central_ht体温传感器
handsfree免配置文件API接口使用,例程编译通过,但是运行时报错
peripheral学习重点!!BLE外设
peripheral_csc骑行速度与踏频GATT服务 ,暂时没有测试
peripheral_dis设备信息GATT服务
peripheral_esp环境感知GATT服务
peripheral_hids通用鼠标GATT服务
peripheral_hr心率GATT服务
peripheral_ht健康体温计GATT服务
peripheral_sc_only仅支持level4安全连接GATT服务
scan_advBLE Broadcaster & Observer role

手机app查阅beacon
在这里插入图片描述

运行时串口输出:

nf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.007,537] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
[00:00:00.007,568] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 2.2 Build 99
[00:00:00.008,117] <inf> bt_hci_core: Identity: dd:86:df:9c:db:cc (random)
[00:00:00.008,117] <inf> bt_hci_core: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
[00:00:00.008,148] <inf> bt_hci_core: LMP: version 5.2 (0x0b) subver 0xffff


beacon编译输出:

F:\Zephyr>west build -p auto -b nrf52840_mdk zephyr\samples\bluetooth\beacon
-- west build: making build dir F:\Zephyr\build pristine
-- west build: generating a build system
Including boilerplate (Zephyr base): F:/Zephyr/zephyr/cmake/app/boilerplate.cmake
-- Application: F:/Zephyr/zephyr/samples/bluetooth/beacon
-- Zephyr version: 2.2.99 (F:/Zephyr/zephyr)
-- Found Python3: C:/Python38/python.exe (found suitable exact version "3.8.2") found components: Interpreter
-- Board: nrf52840_mdk
-- Found west: C:/Python38/Scripts/west.exe (found suitable version "0.7.2", minimum required is "0.7.1")
-- Found dtc: C:/ProgramData/chocolatey/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
-- Found toolchain: gnuarmemb (c:/gnuarmemb)
-- Found BOARD.dts: F:/Zephyr/zephyr/boards/arm/nrf52840_mdk/nrf52840_mdk.dts
-- Generated zephyr.dts: F:/Zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_unfixed.h: F:/Zephyr/build/zephyr/include/generated/devicetree_unfixed.h
Parsing F:/Zephyr/zephyr/Kconfig
Loaded configuration 'F:/Zephyr/zephyr/boards/arm/nrf52840_mdk/nrf52840_mdk_defconfig'
Merged configuration 'F:/Zephyr/zephyr/samples/bluetooth/beacon/prj.conf'
Configuration saved to 'F:/Zephyr/build/zephyr/.config'
Kconfig header saved to 'F:/Zephyr/build/zephyr/include/generated/autoconf.h'
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- The ASM compiler identification is GNU
-- Found assembler: C:/gnuarmemb/bin/arm-none-eabi-gcc.exe
-- Cache files will be written to: F:/Zephyr/zephyr/.cache
-- Configuring done
-- Generating done
-- Build files have been written to: F:/Zephyr/build
-- west build: building application
[163/168] Linking C executable zephyr\zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       54964 B         1 MB      5.24%
            SRAM:       14355 B       256 KB      5.48%
        IDT_LIST:         120 B         2 KB      5.86%
[168/168] Linking C executable zephyr\zephyr.elf


central编译输出:

-- west build: building application
[173/178] Linking C executable zephyr\zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:      104452 B         1 MB      9.96%
            SRAM:       16508 B       256 KB      6.30%
        IDT_LIST:         120 B         2 KB      5.86%
[178/178] Linking C executable zephyr\zephyr.elf

drivers

例程名描述使用记录
spi_flash

spi_flash例程编译过程出现如下错误:

CMake Error at ../../../cmake/extensions.cmake:372 (add_library):
  No SOURCES given to target: drivers__spi
Call Stack (most recent call first):
  ../../../cmake/extensions.cmake:349 (zephyr_library_named)
  ../../../drivers/spi/CMakeLists.txt:3 (zephyr_library)


CMake Generate step failed.  Build files cannot be regenerated correctly.
FATAL ERROR: command exited with status 1: 'C:\Program Files\CMake\bin\cmake.EXE' '-BF:\Zephyr\build' '-SF:\Zephyr\zephyr\samples\drivers\spi_flash' -GNinja -DBOARD=nrf52840_mdk

查询nrf52840-mdk设备树文件nrf52840_mdk.dts,看不到qspi节点的配置。同一目录下的官方开发板nRF52840-DK设备树文件nrf52840-dk-nrf52840.dts却有qspi节点描述,其描述如下:

&qspi {
	status = "okay";
	sck-pin = <19>;
	io-pins = <20>, <21>, <22>, <23>;
	csn-pins = <17>;
	mx25r64: mx25r6435f@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		writeoc = "pp4io";
		readoc = "read4io";
		sck-frequency = <8000000>;
		label = "MX25R64";
		jedec-id = [c2 28 17];
		size = <67108864>;
		has-be32k;
		has-dpd;
		t-enter-dpd = <10000>;
		t-exit-dpd = <35000>;
	};
};

进行如下操作,验证一下是否是因为nrf52840_mdk设备树原因导致例程编译不通过:

原编译命令:
F:\Zephyr>west build -p auto -b nrf52840_mdk zephyr\samples\drivers\spi_flash

修改后的编译命令:
F:\Zephyr>west build -p auto -b nrf52840dk_nrf52840 zephyr\samples\drivers\spi_flash

果然,编译通过了,下面是编译该例程的输出:

F:\Zephyr>west build -p auto -b nrf52840dk_nrf52840 zephyr\samples\drivers\spi_flash
-- west build: generating a build system
Including boilerplate (Zephyr base): F:/Zephyr/zephyr/cmake/app/boilerplate.cmake
-- Application: F:/Zephyr/zephyr/samples/drivers/spi_flash
-- Zephyr version: 2.2.99 (F:/Zephyr/zephyr)
-- Found Python3: C:/Python38/python.exe (found suitable exact version "3.8.2") found components: Interpreter
-- Board: nrf52840dk_nrf52840
-- Found west: C:/Python38/Scripts/west.exe (found suitable version "0.7.2", minimum required is "0.7.1")
-- Found dtc: C:/ProgramData/chocolatey/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
-- Found toolchain: gnuarmemb (c:/gnuarmemb)
-- Found BOARD.dts: F:/Zephyr/zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts
-- Generated zephyr.dts: F:/Zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_unfixed.h: F:/Zephyr/build/zephyr/include/generated/devicetree_unfixed.h
Parsing F:/Zephyr/zephyr/Kconfig
Loaded configuration 'F:/Zephyr/zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig'
Merged configuration 'F:/Zephyr/zephyr/samples/drivers/spi_flash/prj.conf'
Merged configuration 'F:/Zephyr/zephyr/samples/drivers/spi_flash/boards/nrf52840dk_nrf52840.conf'
Configuration saved to 'F:/Zephyr/build/zephyr/.config'
Kconfig header saved to 'F:/Zephyr/build/zephyr/include/generated/autoconf.h'
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- The ASM compiler identification is GNU
-- Found assembler: C:/gnuarmemb/bin/arm-none-eabi-gcc.exe
-- Cache files will be written to: F:/Zephyr/zephyr/.cache
-- Configuring done
-- Generating done
-- Build files have been written to: F:/Zephyr/build
-- west build: building application
[134/139] Linking C executable zephyr\zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       23728 B         1 MB      2.26%
            SRAM:        5592 B       256 KB      2.13%
        IDT_LIST:         104 B         2 KB      5.08%
[139/139] Linking C executable zephyr\zephyr.elf

因此,我将zephyr\boards\arm\nrf52840_mdk目录下的设备树文件nrf52840_mdk.dts增加QSPI节点。那么如何根据开发板硬件连接情况修改设备树节点属性呢?
查阅Nordic文档可知nRF52840DK开发板的外部flash硬件连接关系如下图所示,GPIO点位与设备树中的sck-pin = <19>; io-pins = <20>, <21>, <22>, <23>; csn-pins = <17>;正好对应。
在这里插入图片描述
而我的开发板nrf52840_mdk的qspi接口是位于Port1的,设备树文件中,似乎没有进行端口(Port)属性配置。Port0端口拥有(0-31)共32个IO口,而nrf52840芯片共有48个GPIO Pin。
nrf52840_mdk QSPI接口引脚
此外,我在官方开发板nRF52840-DK设备树文件nrf52840-dk-nrf52840.dts看到了如下节点:

arduino_spi: &spi3 {
	status = "okay";
	sck-pin = <47>;
	miso-pin = <46>;
	mosi-pin = <45>;
	cs-gpios = <&arduino_header 16 0>; /* D10 */
};

查看官方开发板原理图,你可以看到D10对应P1.12;mosi-pin D11对应P1.13,设备树中IO值指定为<45>。可以推算出P1.X设备树的IO属性值为:32+X
在这里插入图片描述
在这里插入图片描述


综上,nrf52840_mdk的设备树QSPI节点属性设置如下:

&qspi {
	status = "okay";
	sck-pin = <35>;
	io-pins = <37>, <36>, <34>, <33>;
	csn-pins = <38>;
	mx25r64: mx25r6435f@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		writeoc = "pp4io";
		readoc = "read4io";
		sck-frequency = <8000000>;
		label = "MX25R64";
		jedec-id = [c2 28 17];
		size = <67108864>;
		has-be32k;
		has-dpd;
		t-enter-dpd = <10000>;
		t-exit-dpd = <35000>;
	};
};

重新编译:F:\Zephyr>west build -p auto -b nrf52840_mdk zephyr\samples\drivers\spi_flash:
仍然提示错误:CMake Generate step failed. Build files cannot be regenerated correctly. FATAL ERROR: command exited with status 1: 'C:\Program Files\CMake\bin\cmake.EXE' '-BF:\Zephyr\build' '-SF:\Zephyr\zephyr\samples\drivers\spi_flash' -GNinja -DBOARD=nrf52840_mdk,将build文件和.cache文件删除再重新编译。

仍然报错:
CMake Error at ../../../cmake/extensions.cmake:372 (add_library): No SOURCES given to target: drivers__spi
【待解决】
20200509 19:30继续死磕这个问题:

又跑去官网翻了一下文档(不知道为啥编译html/pdf文档时 cmake -GNinja总是报错,以后再去定位这个问题),从官网的文档可以看到工程构建过程如下图所示:
在这里插入图片描述
*.dts.pre.tmp文件中,qspi节点如下所示:

  qspi: qspi@40029000 {
   compatible = "nordic,nrf-qspi";
   #address-cells = <1>;
   #size-cells = <0>;
   reg = <0x40029000 0x1000>;
   interrupts = <41 1>;
   status = "disabled";
   label = "QSPI";
  };

devicetree_unfix文件中,qspi节点的相关宏定义如下所示:
两个节点命名分别为:DT_N_S_soc_S_qspi_40029000,
DT_N_S_soc_S_qspi_40029000_S_mx25r6435f_0

/*
 * Devicetree node: /soc/qspi@40029000
 *
 * Node's generated path identifier: DT_N_S_soc_S_qspi_40029000
 *
 * Binding (compatible = nordic,nrf-qspi):
 *   $ZEPHYR_BASE\dts\bindings\flash_controller\nordic,nrf-qspi.yaml
 *
 * Dependency Ordinal: 60
 *
 * Requires:
 *   5   /soc
 *   16  /soc/interrupt-controller@e000e100
 *
 * Supports:
 *   61  /soc/qspi@40029000/mx25r6435f@0
 *
 * Description:
 *   Properties defining the interface for the Nordic QSPI peripheral.
 */

/* Node parent (/soc) identifier: */
#define DT_N_S_soc_S_qspi_40029000_PARENT DT_N_S_soc
#define DT_N_S_soc_S_qspi_40029000_FOREACH_CHILD(fn) fn(DT_N_S_soc_S_qspi_40029000_S_mx25r6435f_0) 

/* Existence and alternate IDs: */
#define DT_N_S_soc_S_qspi_40029000_EXISTS 1
#define DT_N_ALIAS_qspi_0           DT_N_S_soc_S_qspi_40029000
#define DT_N_INST_0_nordic_nrf_qspi DT_N_S_soc_S_qspi_40029000
#define DT_N_NODELABEL_qspi         DT_N_S_soc_S_qspi_40029000

/* Special property macros: */
#define DT_N_S_soc_S_qspi_40029000_REG_NUM 1
#define DT_N_S_soc_S_qspi_40029000_REG_IDX_0_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_REG_IDX_0_VAL_ADDRESS 1073909760 /* 0x40029000 */
#define DT_N_S_soc_S_qspi_40029000_REG_IDX_0_VAL_SIZE 4096 /* 0x1000 */
#define DT_N_S_soc_S_qspi_40029000_IRQ_NUM 1
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_VAL_irq 41
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_VAL_irq_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_VAL_priority 1
#define DT_N_S_soc_S_qspi_40029000_IRQ_IDX_0_VAL_priority_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_COMPAT_MATCHES_nordic_nrf_qspi 1

/* Generic property macros: */
#define DT_N_S_soc_S_qspi_40029000_P_interrupts {41 /* 0x29 */, 1 /* 0x1 */}
#define DT_N_S_soc_S_qspi_40029000_P_interrupts_IDX_0 41
#define DT_N_S_soc_S_qspi_40029000_P_interrupts_IDX_1 1
#define DT_N_S_soc_S_qspi_40029000_P_interrupts_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_sck_pin 35
#define DT_N_S_soc_S_qspi_40029000_P_sck_pin_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_io_pins {37 /* 0x25 */, 36 /* 0x24 */, 34 /* 0x22 */, 33 /* 0x21 */}
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_IDX_0 37
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_IDX_1 36
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_IDX_2 34
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_IDX_3 33
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_LEN 4
#define DT_N_S_soc_S_qspi_40029000_P_io_pins_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_csn_pins {38 /* 0x26 */}
#define DT_N_S_soc_S_qspi_40029000_P_csn_pins_IDX_0 38
#define DT_N_S_soc_S_qspi_40029000_P_csn_pins_LEN 1
#define DT_N_S_soc_S_qspi_40029000_P_csn_pins_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_label "QSPI"
#define DT_N_S_soc_S_qspi_40029000_P_label_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_reg {1073909760 /* 0x40029000 */, 4096 /* 0x1000 */}
#define DT_N_S_soc_S_qspi_40029000_P_reg_IDX_0 1073909760
#define DT_N_S_soc_S_qspi_40029000_P_reg_IDX_1 4096
#define DT_N_S_soc_S_qspi_40029000_P_reg_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_status "okay"
#define DT_N_S_soc_S_qspi_40029000_P_status_ENUM_IDX 1
#define DT_N_S_soc_S_qspi_40029000_P_status_EXISTS 1
#define DT_N_S_soc_S_qspi_40029000_P_compatible {"nordic,nrf-qspi"}
#define DT_N_S_soc_S_qspi_40029000_P_compatible_IDX_0 "nordic,nrf-qspi"
#define DT_N_S_soc_S_qspi_40029000_P_compatible_LEN 1
#define DT_N_S_soc_S_qspi_40029000_P_compatible_EXISTS 1

可以从上述内容中看到,IO引脚等宏定义与我们修改的dts是一致的。
devicetree_fixup.h是一个空文件,unfix和fixup文件输出的devicetree.h文件在build目录下没有找到!!!这是什么原因?

例程drivers-spi_flash工程目录下的prj.conf内容如下:

CONFIG_STDOUT_CONSOLE=y
CONFIG_FLASH=y
CONFIG_SPI=y

编译目录下的.config文件内容如下:

...
# CONFIG_NRFX_QSPI is not set
# CONFIG_NRFX_SPI is not set
# CONFIG_NRFX_SPI0 is not set
# CONFIG_NRFX_SPI1 is not set
# CONFIG_NRFX_SPI2 is not set
...

[需要注意,上述没有完全列出两个文件的不同之处]这一点尤其可疑,因为编译错误提示为:CMake Error at ../../../cmake/extensions.cmake:372 (add_library): No SOURCES given to target: drivers__spi
官方文档中说:The output from Kconfig is an autoconf.h header with preprocessor assignments, and a .config file that acts both as a saved configuration and as configuration output (used by CMake).说得很清楚了,即.config文件会被CMake程序使用。

验证:
重新编译一下F:\Zephyr>west build -p auto -b nrf52840dk_nrf52840 zephyr\samples\drivers\spi_flash,查看目标板设置为nrf52840dk时编译输出的.config文件内容:

CONFIG_NRFX_QSPI=y
CONFIG_NRFX_SPI=y
# CONFIG_NRFX_SPI0 is not set
CONFIG_NRFX_SPI1=y
# CONFIG_NRFX_SPI2 is not set

通过这一对比,就可以看到.config中的nrfx drivers部分QSPI配置项不一致,明显可以看出,当编译目标板是nrf52840_mdk时,生成的.config文件不正确,导致cmake错误。那么是prj.conf、dts、Kconfig文件之中的哪个出现了错误呢?

直接对比文件,首先排除devicetree_unfixed.h,因为nrf52840_mdk编译输出的QSPI宏是存在的,与nrf52840dk的宏仅仅是引脚定义上有差别。

开发板Kconfig文件没有明显差别,然而开发板 bindings(.yaml)有较大差别。

通过west build -t guiconfig命令打开交互式内核配置程序,如下图所示:
在这里插入图片描述
在Modules->nrfx drivers可以看到nrf52840-dk使能了相关驱动,如下图所示:
在这里插入图片描述

The configuration can also be changed by editing zephyr/.config in the application build directory by hand. Using one of the configuration interfaces is often handier, as they correctly handle dependencies between configuration symbols.也可以通过在应用程序构建目录中手动编辑zephyr / .config来更改配置。使用配置界面之一通常更方便,因为它们可以正确处理配置符号之间的依赖关系。先要构建app,才能进入kernel配置。

搞了半天原来是这里的问题,例程源文件下boards目录添加了.conf配置文件,打开可以看到CONFIG_NORDIC_QSPI_NOR=Y,因此我们只需要依葫芦画瓢,添加nrf52840_mdk.conf,将nrf52840dk_nrf52840.conf文件内容复制一份即可。
在这里插入图片描述
更改之后,编译依旧报错,但是build目录下的.config文件中CONFIG_NRFX_QSPI=y,现在.config文件看起来是正确的。

摸爬滚打一小时,发现zephyr\samples\drivers\spi_flash工程目录下的prj.conf工程配置文件设置了CONFIG_SPI=y,然而nrf52840_mdk设备树没有包含任何spi节点,导致一直报错。注意报错信息一直都是说spi驱动源文件未找到,而我一直以为是qspi驱动存在问题!!!

CMake Error at …/…/…/cmake/extensions.cmake:372 (add_library):
No SOURCES given to target: drivers__spi
Call Stack (most recent call first):
…/…/…/cmake/extensions.cmake:349 (zephyr_library_named)
…/…/…/drivers/spi/CMakeLists.txt:3 (zephyr_library)

将工程目录下的prj.conf文件对应内容屏蔽后,顺利编译通过:

-- west build: building application
[126/131] Linking C executable zephyr\zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       18804 B         1 MB      1.79%
            SRAM:        4056 B       256 KB      1.55%
        IDT_LIST:          72 B         2 KB      3.52%
[131/131] Linking C executable zephyr\zephyr.elf

开心地把.hex文件下载到板上看看效果,串口中打印信息如下:

t 2: Flash write
Attempting to write 4 bytes
Data read matches data written. Good!!

发现部分打印内容在串口助手中看不到,怀疑是运行速度太快,导致如此。今天的工作到此告一段落。

总结

  1. Zephyr安装过程可能会遇到west速度太慢的问题,请与网速斗智斗勇,万事开头难,千万不要轻易放弃,往往你与成功只有一步之遥,时间允许的话一定要死磕,不装好不干别的事情。
  2. 通过zephyr的例程学习应用开发,我个人觉得是一个快速上手的方法,一方面会让你有一点小小的成就感,另一方面要认识到zephyr的复杂性,在没有任何基础的情况下直接去磕内核实现其实是不太必要的,要学会由浅至深。
  3. zephyr的构建过程我仍然不是很清楚,内核配置也不尽了解,后续在做应用开发的过程中逐渐加深了解。
  4. 后续我会基于zephyr按照项目需求逐渐实现其功能,主要是QSPI、2.4G Radio以及图像无损压缩算法部分。

最后,我的一点小期待,希望国内高校有志人士 能够投入到zephyr生态中来,完善相关文档与教程。

  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值