赞
踩
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
我选用的开发板是nRF52840-MDK,是Zephyr支持的众多开发板之一,你也可以选择其他的开发板进行学习,不过我个人建议选择一款成熟度高、资料丰富、应用广泛的开发板,这样在你后续的学习过程中可以避免很多“坑”。
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 等等),并且提供丰富的在线文档及示例,帮助你加速物联网应用开发。
nRF52840-MDK 支持多种软件框架及协议:
框架/协议 | 简介 |
---|---|
nRF5 SDK | Nordic 官方提供的 SDK |
nRF5 SDK for Mesh | Nordic 官方提供的低功耗蓝牙 Mesh 网络 SDK |
OpenThread | Nest 开源实现的 Thread® 网络协议 |
Arm Mbed OS | Arm 开源的物联网实时操作系统 |
Zephyr | Linux 基金会开源的物联网实时操作系统 |
Mynewt | Apache 开源模块化的实时操作系统,专门为内存和存储都极其有限而又要以极低功耗运行非常长时间的物联网设备设计 |
Arm Mbed DAPLink | Arm Mbed 针对 Arm Cortex 系列 CPU 开源 CMSIS-DAP 多功能调试器 |
Web Bluetooth | 基于 Web 的低功耗蓝牙 API |
iBeacon | Apple 实现的 Beacon 协议 |
Eddystone | Google 开源的 Beacon 协议 |
可以看到这个开发板支持Zephyr框架。
版本 | 设计文档 |
---|---|
V1.0 | nRF52840-MDK V1.0 Pinout Diagram |
nRF52840-MDK V1.0 Schematic | |
nRF52840-MDK V1.0 Board File | |
nRF52840-MDK V1.0 3D STEP |
遗憾的是这些资料都是指PDF文档,PCB文件并没有开源。
Zephyr OS 是专门为资源受限设备构建、针对低功耗、小型内存微处理器设备而进行优化的物联网嵌入式小型、可扩展的实时操作系统(RTOS),支持多种硬件架构及多种开发板(包括 ARM Cortex-M, Intel x86, ARC, NIOS II, Tensilica Xtensa, 以及 RISC-V),甚至可以在小至 8kB 内存的系统上运行。
Zephyr 内核相比其他实时操作系统内核具有许多优势:
了解更多细节,可以访问 Zephyr Project 官网。
克隆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的方式。
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社区上也找到别人反馈的同样的问题。
例程名 | 硬件/接口 | 描述 |
---|---|---|
blink_led | PWM-LED | 变频率的LED闪烁 |
blinky | GPIO-LED | 恒频率LED闪烁 |
button | GPIO中断 | 按键灯,松键灯灭 |
fade_led | PWM-LED | PWM脉宽调制 |
minimal | 空main() | 测试zephyr内核最小大小,见下方输出 |
rgb_led | 3*PWM-LED | RGB LED颜色逐渐变化 |
servo_motor | PWM | 舵机控制,板子上没有这个接口,暂时没有测试 |
threads | K_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
例程名 | 硬件/接口 | 描述 |
---|---|---|
battery | ADC | 测量开发板供电电压,放电曲线估算时间,打印内容如下 |
mesh | 蓝牙 | 未测试 |
nrfx | GPIOTE 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
例程名 | 硬件/接口 | 描述 |
---|---|---|
beacon | 2.4G Radio | BLE广播 |
central | BLE中心点,根据信号强度自动建立连接,查看打印信息,在不停的连接与断开 | |
central_hr | BLE中心点,自动连接心率设备并读取心率值,尝试用心率带进行连接,但是没太看明白 | |
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_adv | BLE Broadcaster & Observer role |
运行时串口输出: 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
例程名 | 描述 | 使用记录 |
---|---|---|
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-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!!
发现部分打印内容在串口助手中看不到,怀疑是运行速度太快,导致如此。今天的工作到此告一段落。
最后,我的一点小期待,希望国内高校有志人士 能够投入到zephyr生态中来,完善相关文档与教程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。