本帖最后由 zhanzr21 于 2023-9-25 21:36 编辑
#有奖活动# #申请原创# 开发板开箱/硬件资源 在21ic上看到Nordic举办开发板评测活动,有幸参与,把自己的一些体会和经历记录下来,分享给大家。这是第一篇,板子的内容较多,后续内容会继续写。
首先不能免俗来个开箱照片吧。
开发板的资源较多, 主要的功能围绕三个芯片为核心:
- 一个nRF5340是调试器,烧写成Segger JLink,这个暂时不详细研究,只当做工具来使用;
- 一个nRF5340是主MCU,也就是开发板的主角,提供蓝牙\NFC等功能;
- 一个nRF7002,提供WiFi功能,这个芯片本身作为一个外设挂在主MCU上的。
所以开发板主要编程的对象是主MCU:nRF5340。
nRF5340芯片本身也是一个双核心的SoC,两个核心都是Cortex®-M33 :
主核心带DSP增强指令, FPU,Armv8-M安全扩展(如TrustZone),最高频率128 MHz,称为应用核(App Core);
次核心没有DSP/FPU,频率固定在64 MHz,称为网络核(Net Core)。
具体在该开发板子,应用核的资源如下:
Interface
| Controller
| Driver/Component
| ADC
| on-chip
| adc
| CLOCK
| on-chip
| clock_control
| FLASH
| on-chip
| flash
| GPIO
| on-chip
| gpio
| I2C(M)
| on-chip
| i2c
| MPU
| on-chip
| arch/arm
| NVIC
| on-chip
| arch/arm
| PWM
| on-chip
| pwm
| RTC
| on-chip
| system clock
| RTT
| Segger
| console
| RADIO
| nrf7002
| Wi-Fi 6 (802.11ax)
| QSPI
| on-chip
| qspi
| SPI(M/S)
| on-chip
| spi
| SPU
| on-chip
| system protection
| UARTE
| on-chip
| serial
| USB
| on-chip
| usb
| WDT
| on-chip
| watchdog
| 网络核的资源如下:
Interface
| Controller
| Driver/Component
| CLOCK
| on-chip
| clock_control
| FLASH
| on-chip
| flash
| GPIO
| on-chip
| gpio
| I2C(M)
| on-chip
| i2c
| MPU
| on-chip
| arch/arm
| NVIC
| on-chip
| arch/arm
| RADIO
| on-chip
| Bluetooth, ieee802154
| RTC
| on-chip
| system clock
| RTT
| Segger
| console
| QSPI
| on-chip
| qspi
| SPI(M/S)
| on-chip
| spi
| UARTE
| on-chip
| serial
| WDT
| on-chip
| watchdog
| 这种配置类似于桌面/移动处理器的大小核组合,两核通过共享内存或者IPC通信,核间通信的细节以后再详细写。
顺便提一句,该开发板开发环境配置支持多种操作系统(Win/MacOS/Linux),但是如同大多数嵌入式开发环境,最推荐使用Windows开发机器了,因为官方的教程大多都是以Windows为例子。把开发板子插到电脑上,驱动安装好之后(驱动安装相关内容在下一节),打开设备详情可以看到以下内容。
这里啰嗦一下子,为什么这个板载调试器叫做Segger J-Link?
是因为Segger公司收费后向Nordic授权了J-Link商标和软件的使用权。调试这个标准Cortex-M内核的芯片使用开源的DAP Link也可以,但是显而易见的是J-Link的功能/速度都远远超过开源的公版调试器。作为开发者而言, 很感激这种设计。
笔者本人有很多开发板,有些自费购买的,有些活动赠送的。相对而言,配置了好的板载调试器的板子使用起来效率高很多。某些开发板为了成本或者体积的考虑,不配置调试器,或者让开发者外面插线,或者用那种别扭的USB/串口来刷固件。非常影响开发和学习效率。
开发环境配置 如同上文所述,开发环境选择Windows机器。主要参考官方的一个视频教程合集:
https://www.youtube.com/watch?v= ... NordicSemiconductor
这个教程比较全面,看完之后就可以上手开发了。
但注意两点:
一、需要特殊的网络配置,
二、原文是英文,很多工程师可能更习惯有母语视频。
本人倒是有心自己做一个这样的视频教程放在便于访问的平台上,暂时时间有限,只做了个比较简短的。
安装nRF Command Line Tools
https://www.nordicsemi.com/Produ ... Line-Tools/Download
安装好后内容:
.
├── bin
│ ├── highlevelnrfjprog.dll
│ ├── jlinkarm_nrf_worker.exe
│ ├── jlinkarm_nrf51_nrfjprog.dll
│ ├── jlinkarm_nrf52_nrfjprog.dll
│ ├── jlinkarm_nrf53_nrfjprog.dll
│ ├── jlinkarm_nrf91_nrfjprog.dll
│ ├── jlinkarm_unknown_nrfjprog.dll
│ ├── mergehex.exe
│ ├── nrfdfu.dll
│ ├── nrfjprog.dll
│ └── nrfjprog.exe
├── include
│ ├── DllCommonDefinitions.h
│ ├── highlevelnrfjprogdll.h
│ ├── mergehex.h
│ ├── nrfdfu.h
│ ├── nrfjprog.h
│ └── nrfjprogdll.h
├── lib
│ ├── highlevelnrfjprog.lib
│ ├── jlinkarm_nrf51_nrfjprog.lib
│ ├── jlinkarm_nrf52_nrfjprog.lib
│ ├── jlinkarm_nrf53_nrfjprog.lib
│ ├── jlinkarm_nrf91_nrfjprog.lib
│ ├── jlinkarm_unknown_nrfjprog.lib
│ ├── nrfdfu.lib
│ └── nrfjprog.lib
├── LICENSE.rtf
├── LICENSE.txt
├── mergehex_release_notes.txt
├── nrfjprog_release_notes.txt
├── python
│ ├── __init__.py
│ ├── LICENSE
│ ├── MANIFEST.in
│ ├── pynrfjprog
│ │ ├── __init__.py
│ │ ├── API.py
│ │ ├── APIError.py
│ │ ├── config.toml
│ │ ├── docs
│ │ │ ├── __init__.py
│ │ │ ├── highlevelnrfjprogdll.h
│ │ │ ├── nrfdfu.h
│ │ │ ├── nrfjprog_release_notes.txt
│ │ │ └── nrfjprogdll.h
│ │ ├── examples
│ │ │ ├── __init__.py
│ │ │ ├── hex_files
│ │ │ │ ├── __init__.py
│ │ │ │ ├── nrf51_dk_blinky.hex
│ │ │ │ ├── nrf51_dk_rtt.hex
│ │ │ │ ├── nrf52_dk_blinky.hex
│ │ │ │ ├── nrf52_dk_rtt.hex
│ │ │ │ ├── nrf52840_dk_blinky.hex
│ │ │ │ ├── nrf53_dk_blinky.hex
│ │ │ │ ├── nrf53_dk_rtt.hex
│ │ │ │ ├── nrf91_dk_blinky.hex
│ │ │ │ ├── nrf91_dk_rtt.hex
│ │ │ │ └── nrf9160_pca20035_firmware_upgrade_app_0.1.0.hex
│ │ │ ├── highlevel_memory_read_write.py
│ │ │ ├── highlevel_program_hex.py
│ │ │ ├── memory_read_write.py
│ │ │ ├── nrf9160_pca20035_modem_upgrade_over_serial.py
│ │ │ ├── program_hex.py
│ │ │ ├── python_help.py
│ │ │ ├── rtt_asyncio.py
│ │ │ ├── rtt_callback.py
│ │ │ └── rtt_synchronous.py
│ │ ├── Hex.py
│ │ ├── HighLevel.py
│ │ ├── JLink.py
│ │ ├── lib_arm64
│ │ │ └── __init__.py
│ │ ├── lib_armhf
│ │ │ └── __init__.py
│ │ ├── lib_x64
│ │ │ ├── __init__.py
│ │ │ ├── highlevelnrfjprog.dll
│ │ │ ├── highlevelnrfjprog.lib
│ │ │ ├── jlinkarm_nrf_worker.exe
│ │ │ ├── nrfdfu.dll
│ │ │ ├── nrfdfu.lib
│ │ │ ├── nrfjprog.dll
│ │ │ └── nrfjprog.lib
│ │ ├── lib_x86
│ │ │ └── __init__.py
│ │ ├── LowLevel.py
│ │ ├── MultiAPI.py
│ │ ├── Parameters.py
│ │ ├── QspiDefault.ini
│ │ └── RTTAsyncIO.py
│ ├── pyproject.toml
│ └── README.md
└── share
├── config.toml
├── firmware
│ └── nrf9160_pca20035_firmware_upgrade_app_0.1.1.hex
├── NRFCommandLineTools
│ ├── NRFCommandLineToolsConfig.cmake
│ ├── NRFCommandLineToolsConfigVersion.cmake
│ ├── NRFCommandLineToolsTargets.cmake
│ └── NRFCommandLineToolsTargets-release.cmake
├── nrfjprog.ini
└── QspiDefault.ini
主要内容是烧写工具和驱动,HEX文件工具,烧写工具集成API. 安装好后会自动配置系统路径。
C:\Users\Lenovo>where nrfjprog.exe
D:\Nordic Semiconductor\nrf-command-line-tools\bin\nrfjprog.exe
如果不是手工进行自定义环境开发,这个工具就是安装好后面的工具可以通过PATH环境变量找到它,直接使用。开发者可以暂时不必关心。
安装nRF Connect for Desktop https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop/Download
这个工具相当于一个总体管理工具,后面的SDK/Programmer都通过这个工具来管理。
安装ToolChain Manager/Programmer 打开刚刚安装好nRF Connect for Desktop工具,按个人需要安装相关的组件,Toolchain manager和Programmer一般都需要。
安装nRF Connect SDK 打开刚刚安装好的Toolchain manager,选择最新的SDK,安装上。
这里对网络需求比较高,否则很容易安装不成功。关于这一点,21ic告知,Nordic厂家的工程师已经在做优化: 如Toolchain和SDK分开管理,将一些文件打包供整体下载等举措。可以预料的是不久的将来,相关软件安装的体验会极大增强。目前而言需要开发者多一点耐心。
Toolchains目录里面放着工具链, v开头的是SDK,downloads里面放着下载好的工具链安装包。
工具链与SDK之间有一定匹配规则,不是某版本的SDK可以与任意版本的工具链组合。据21ic透露,Nordic工程师也在考虑发布工具链和SDK的兼容矩阵表格,相信这样会提高开发者的效率。
安装VS Code/Extension 安装好了SDK后,点Open VS Code,会检测机器上的VS Code,如果机器上没有安装,会提示安装VS Code。
等安装好VS Code,再点这个按钮,如果还缺哪些Extensions,会提示相关的VS Code Extension,如果都安装好了可以直接启动VS Code。
到这里,需要下载安装的必要软件就都好了。
创建工程 创建工程/构建/下载整个过程本人录制了个小视频,供参考:
有两种工程类型:
- Freestanding:使用安装好的SDK,工程本身仅包含应用代码。
- Workspace:工程包含使用的SDK,占用的磁盘空间大,易于分享和发布。
可以简单理解: 如果是开发阶段,选Freestanding类型。如果代码到了生产环境,就应该使用workspace类型将SDK(最好是连同toolchain)版本一起固化起来。
这里选择一个blinky为应用模版,就是简单的LED闪烁。
默认使用板子上的LED1,在DeviceTree中是LED0。本文的例子中增加了另外一个LED一起闪烁,以验证整个操作流程。
构建配置 选择板子,构建配置。主要是选择使用的板子,如果板子为自定义的(比如自己画的)则需要创建一个开发板配置。官方发布的板子都有现成的开发板配置。
下载 直接点这里下载即可。
也可以自己打开Programmer工具手撸hex文件自行下载。
初始工程代码:
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
int main(void)
{
int ret;
if (!gpio_is_ready_dt(&led)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
int tmp_cnt = 0;
while (1) {
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
新增一个LED配置,修改后代码如下:
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 200
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
int main(void)
{
int ret;
if (!gpio_is_ready_dt(&led0)) {
return 0;
}
ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
if (!gpio_is_ready_dt(&led1)) {
return 0;
}
ret = gpio_pin_configure_dt(&led1, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
while (1) {
ret = gpio_pin_toggle_dt(&led0);
if (ret < 0) {
return 0;
}
k_msleep(SLEEP_TIME_MS);
ret = gpio_pin_toggle_dt(&led1);
if (ret < 0) {
return 0;
}
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
保存\再次构建后下载观察是否有两个LED闪烁,如果是则整个流程无误。
调试 调试的话,注意在build时带上debug 选项。其余操作与其他工具差距不大,不赘述。
工程之二-连接WiFi 工程模版选择sta即可。(注意:截止本文,SDK不支持AP模式)
查看使用的WiFi接入点的配置,主要是加密选项:
配置prj.conf中的WIFI名称和密码:
# Below configs need to be modified based on security
# CONFIG_STA_KEY_MGMT_NONE=y
CONFIG_STA_KEY_MGMT_WPA2=y
# CONFIG_STA_KEY_MGMT_WPA2_256=y
# CONFIG_STA_KEY_MGMT_WPA3=y
CONFIG_STA_SAMPLE_SSID="wssid_name"
CONFIG_STA_SAMPLE_PASSWORD="password"
配置默认的IP地址,假如DHCP失败的情况可以使用这个:
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.168.2.110"
CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0"
CONFIG_NET_CONFIG_MY_IPV4_GW="192.168.2.100"
之后构建下载,如果连接成功,LED会闪烁,且有串口输出。
[00:00:00.426,910] <inf> wifi_nrf: Firmware (v1.2.8.1) booted successfully
*** Booting Zephyr OS build v3.3.99-ncs1-1 ***
[00:00:00.582,183] <inf> net_config: Initializing network
[00:00:00.582,183] <inf> net_config: Waiting interface 1 (0x20001430) to be up...
[00:00:00.583,892] <inf> net_config: IPv4 address: 192.168.2.110
[00:00:00.583,953] <inf> net_config: Running dhcpv4 client...
[00:00:00.585,876] <inf> sta: Starting nrf7002dk_nrf5340_cpuapp with CPU frequency: 64 MHz
[00:00:01.585,937] <inf> sta: QSPI Encryption disabled
[00:00:01.586,029] <inf> sta: Static IP address (overridable): 192.168.2.110/255.255.255.0 -> 192.168.2.100
[00:00:03.130,706] <inf> sta: Connection requested
[00:00:03.430,877] <inf> sta: ==================
[00:00:03.430,908] <inf> sta: State: SCANNING
[00:00:03.731,018] <inf> sta: ==================
[00:00:07.449,859] <inf> wifi_nrf: wifi_nrf_wpa_supp_authenticate:Authentication request sent successfully
[00:00:07.632,873] <inf> sta: ==================
[00:00:07.632,904] <inf> sta: State: AUTHENTICATING
[00:00:07.722,320] <inf> wifi_nrf: wifi_nrf_wpa_supp_associate: Association request sent successfully
[00:00:07.805,023] <inf> sta: Connected
[00:00:07.946,563] <inf> sta: ==================
[00:00:07.946,594] <inf> sta: State: COMPLETED
[00:00:07.946,624] <inf> sta: Interface Mode: STATION
[00:00:07.946,624] <inf> sta: Link Mode: WIFI 4 (802.11n/HT)
[00:00:07.946,655] <inf> sta: SSID: ssid_name
[00:00:07.946,685] <inf> sta: BSSID: xx:xx:xx:xx:xx:xx
[00:00:07.946,716] <inf> sta: Band: 2.4GHz
[00:00:07.946,716] <inf> sta: Channel: 4
[00:00:07.946,746] <inf> sta: Security: WPA2-PSK
[00:00:07.946,777] <inf> sta: MFP: Optional
[00:00:07.946,777] <inf> sta: RSSI: -65
连接之后可以ping通:
C:\Users\Lenovo>ping 192.168.2.110
正在 Ping 192.168.2.110 具有 32 字节的数据:
来自 192.168.2.110 的回复: 字节=32 时间=38ms TTL=64
来自 192.168.2.110 的回复: 字节=32 时间=149ms TTL=64
来自 192.168.2.110 的回复: 字节=32 时间=161ms TTL=64
来自 192.168.2.110 的回复: 字节=32 时间=174ms TTL=64
192.168.2.110 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 38ms,最长 = 174ms,平均 = 130ms
不过本人这个示例中DHCP过程没有完成,只能使用默认配置的静态地址通信。原因应该是跟本人使用的路由器的兼容性问题,还在排查中。
示例工程之三-双核通信 工程模版:entroy_nrf53
如前所述,nRF5340芯片上有两个核心:AppCore和Net Core
IPC是两核心之间的一个通信手段。
这个例子中App Core通过IPC向NetCore请求熵值, NetCore这边使用随机数生成器生成熵值返回。这个示例有两个工程,会生成两个hex文件,可以分别烧写,也可以合并后一起烧写。两个核心的Flash空间不重合。AppCore以0x00000000起始,NetCore以0x01000000起始。
AppCore的IPC通道:
NetCore的IPC通道:
两个hex烧写后,App Core输出:
Init begin
Init done
*** Booting Zephyr OS build v3.3.99-ncs1-1 ***
Entropy sample started[APP Core].
Remote init send
0x68 0x44 0x62 0xcc 0x44 0x00 0x39 0xd5 0xfb 0x36
0x68 0x44 0x62 0xcc 0x44 0x00 0x39 0xd5 0xfb 0x36
Net Core输出:
Init begin
Init done
*** Booting Zephyr OS build v3.3.99-ncs1-1 ***
Entropy sample started[NET Core].
[00:00:00.518,524] <inf> sync_rtc: Updated timestamp to synchronized RTC by 8304 ticks (253417us)
小结 由于各种原因,本人对该开发板的特性还没有完全测试透,目前仅仅是把开发流程走通了。后续会继续测试、写贴。本人最感兴趣的还是该开发板的网络功能和双核架构。
今后的研究方向也会在这些方面,还有就是把教学视频做一个适合本土工程师的版本。
参考
官方文档首页
https://developer.nordicsemi.com ... h_nrf/nrf70/gs.html
官方视频教程频道
https://www.youtube.com/watch?v= ... NordicSemiconductor
本人做的简短操作流程视频
https://v.youku.com/v_show/id_XNjAwMzkyMDcxMg==.html
|
@zhyrq :做了一些测试 没有整理出来 如果大伙对哪部分有感兴趣的 可以整理一下
后续有吗?