持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
nRF52实践:SDK的了解。
本文结合开发的一点经验,记录一下SDK的了解情况,所用版本为 SDK 17.1。
softdevice
SDK 17 压缩包带有 softdevice,版本为 7.2。位置:components\softdevice\s132\doc
。
发布说明文件为:s132_nrf52_7.2.0_release-notes.pdf。
flash占用152KB,ram占用5.6KB,调用栈占用1.75KB。ID号为0x0101。
注:烧写 softdevice 后会获取到 ID号。带协议栈的Keil工程中,需要设置flash地址为0x260000。
SDK
开发环境使用 keil 5。
SDK有2套。
SDK,不再加新功能,但会修复bug,最新是2021年8月发布的17版本。52系列可用之。
新的为NCS(nRF Connect SDK),官方的nRF Connect,新的SDK,会加新功能。
nRF52832 两套 SDK 都可用。
下载
芯片:Nordic 官方出品 nRF5XXX 芯片。具体为 nRF52832。
SDK:版本越新越高,有新特性,但可能资源占用大,按需下载,按需升级。
Softdevice:Nordic蓝牙协议栈的名称,有不同版本。命名为 Sxyz。
- x 协议栈的类型,1为BLE协议栈,2为ANT协议栈,3为同时支持两者
- y BLE角色,1为从设备,2为主设备,3为同时支持两者
- z 芯片类型,0 为nRF51系列,2 为nRF52系列
ANT另外下载,需授权,有试用版,但不能商用。符合预研要求的:S132(支持BLE协议主从的nRF52系列)。
默认情况,选择 SDK 后,会自动勾选 SoftDevices,一般是全部下载,可按需下载,此处用S132。下载后文件名:
s132nrf52720.zip # nrf52的7.2.0版本
nRF5_SDK_17.1.0_ddde560.zip # sdk 17.1.0 版本
复制代码
下载截图(打勾表示要下载的):
注:关于softdevice的说明,SDK中也包含有了softdevice,会有多个,是否有必要再额外下载?额外下载的只有头文件。在SDK中有hex文件,目录nRF5_SDK_17.1.0_ddde560\components\softdevice\s132\hex
经研究,如果softdevice有新的版本,则下载之,压缩包有发布说明,里面有占用大小的说明。
SDK目录介绍
例程目录有不同类别的例子。目录示例:SDK版本/ examples /协议角色/例子名称/开发板型号/协议栈型号/工具链类型/具体工程
源码文件为main.c,目录下有pca10040 pca10040e pca10056 pca10056e pca10100e
不同的子目录,其下还有如s132 s112
的子目录,其下再有不同编译环境的子目录,似乎是配置文件。经分析,pca10040的s132是nRF52832使用的目录。
SDK 文档
官方有完备的在线文档,地址:infocenter.nordicsemi.com/index.jsp
左侧Software Development Kit,当前最新的版本为nRF5 SDK v17.1.0,可在Previous versions of nRF5 SDK查询历史版本。
在Examples中有不同类别的示例。如基本外设,和蓝牙有关的外设示例,等,按需查询。
52832芯片手册在线版:nRF52832 Product Specification 注:在线版查询会比较慢,可下载离线版备用。
离线版本在左侧可下载。
SDK不同版本变化大,看资料需看时间。
SDK 框架
内存分布
(来自谷雨实验文档)
无DFU情况,Flash 包括:
-
MB
0x00000000 - 0x00001000 为主引导程序(MBR)。
-
SoftDevice
0x00001000 - 0x00026000 为协议栈程序。
-
APP
RAM 分配:
- 协议栈 包括 MBR+SoftDevice。占用大小在 SoftDevice 发布文档中给出。实际中可能要添加,过小时,启动会有日志打印。
有DFU情况,Flash 包括:
-
MB
同前
-
SoftDevice
同前
-
APP
-
bootloader
DFU 蓝牙空中升级boot,地址根据DFU程序大小自行设置。
-
bootloader parameter
0x0007E000 - 0x00080000 DFU 蓝牙空中升级boot参数区,用于记录升级信息(升级过程断电的话,下次可以接着升级,相当与有断点续传功能),APP版本,BOOT版本,APP校验,参数区校验等信息。如果没有此分区,程序将无法正常运行。
启动流程
nRF52832上电后从固定位置0x0000 0000开始执行程序,flash 0x0000 0000–0x0002 6000存放Nordic的协议栈s132,协议栈s132前面4KB(0x0000-0x1000)为主引导程序(MBR),MBR根据地址0xFF8或者0x1000 1014中是否存在DFU程序起始地址决定跳转地址,如果地址0xFF8或者0x1000 1014中存在DFU程序起始地址则会跳转至DFU,DFU运行结束后程序会跳转0x0000 1000,然后协议栈根据协议栈大小跳转至协议栈结束地址也就是APP起始地址0x26000,至此开始执行APP程序。
SDK的一些规范(约定)
nRF 的源码自有一套规范,根据示例格式编写即可,初学者不需要造轮子,也不要另立门户。总结几点:
- SDK大版本不同,接口也不同,看资料需看所写日期或所用SDK版本。
- sdk_config.h 里面有非常多的宏定义,不同工程设置不同。一般不能通用。
- 模块使用宏定义编译,要使用需在sdk_config中开启宏定义。
- 工程依赖文件多,新工程最好在已有的相近的工程基础上建立,SDK有模板工程。
- SDK有旧外设接口、新外设接口,带BLE协议栈外设接口。
- 带BLE协议栈和程序需烧录有softdevice,不带的不能烧有softdevice,两者不兼容的。(注:仅笔者实践若干次的结论,未深究)
开发类概述
-
实例
GATT分服务端、客户端,使用
BLE_BAS_DEF
这类的宏进行实例化。其它如定时器、队列等亦然。 -
SDK使用观察者模式设计,大量使用回调事件/函数。SDK自身源码有一套事件定义,而反应到用户级也有对应的事件。示例:
- 空闲广播事件,SDK使用的是
BLE_ADV_MODE_IDLE
,用户注册的回调函数使用的是BLE_ADV_EVT_IDLE
。 - NUS服务端接收数据事件,SDK根据
BLE_GATTS_EVT_WRITE
事件的回调函数条件,赋值BLE_NUS_EVT_RX_DATA
,即为用户级可使用的事件。
- 空闲广播事件,SDK使用的是
sdk_config头文件说明
配置头文件为 sdk_config.h。主从机配置不同。一些模块或组件,根据sdk_config.h的宏来编译。比如NUS服务,从机设置:
#define BLE_NUS_ENABLED 1
复制代码
主机设置:
#define BLE_NUS_C_ENABLED 1
复制代码
对应的实现文件起始位置已经做了宏编译,如不添加,则无法编译相关的组件。
新旧API接口
一般地,nrf_xx
是旧的API接口,nrfx_xx
是新的接口。
在integration\nrfx\legacy
中使用宏定义来兼容旧API接口,如nrf_drv_timer.h
文件:
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_timer_init nrfx_timer_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_timer_uninit nrfx_timer_uninit
复制代码
目前在 SDK 17 版本中,很多示例代码还是混用新旧接口。
带BLE协议栈与否
以获取内部测试为例(仅为示意代码)。
不带 BLE 协议:
nrf_temp_init();
temp = (nrf_temp_read() / 4);
复制代码
带 BLE 协议:
sd_temp_get(&raw_temperature);
复制代码
注:带 BLE 协议需sd_xx
函数。不过,有的外设没有该类接口,可使用nrfx_xx
接口。原因是有的外设在协议栈情况下无法被访问(至于是哪些,暂未深究)。
模块实现
服务模块实现源码文件使用宏定义进行编译。需在 sdk_config 头文件中开启。
电池服务BAS sdk_config定义:
#define BLE_BAS_ENABLED 1
源码实现:
#if NRF_MODULE_ENABLED(BLE_BAS)
// 实现代码
#endif // NRF_MODULE_ENABLED(BLE_BAS)
客户端类似,宏为 BLE_BAS_C_ENABLED
复制代码
实例演示
以 keil 工程为例。
SDK 示例工程将源码按组分好,这是逻辑的分组。按需添加,比如外设在 nRF_Drivers,封装的外设接口在 nRF_Libraries 中,BLE 服务在 nRF_BLE_Services 中。
添加头文件:
..\..\..\..\..\..\components\libraries\uart
..\..\..\..\..\..\components\libraries\bsp
..\..\..\..\..\..\components\libraries\\timer
复制代码
添加源码文件:
components\libraries\timer
components\libraries\bsp
components\libraries\uart
modules\nrfx\drivers\src
复制代码
宏定义:
新驱动:
// <e> NRFX_TIMER_ENABLED - nrfx_timer - TIMER periperal driver
//==========================================================
#ifndef NRFX_TIMER_ENABLED
#define NRFX_TIMER_ENABLED 1
#endif
// <q> NRFX_TIMER0_ENABLED - Enable TIMER0 instance
#ifndef NRFX_TIMER0_ENABLED
#define NRFX_TIMER0_ENABLED 0
#endif
旧驱动:
// <e> TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver - legacy layer
//==========================================================
#ifndef TIMER_ENABLED
#define TIMER_ENABLED 1
#endif
#ifndef TIMER0_ENABLED
#define TIMER0_ENABLED 1
#endif
复制代码
类似的新旧驱动宏定义:
新:#define NRFX_SAADC_ENABLED 1
旧:#define SAADC_ENABLED 1
复制代码
参考
- Nordic nRF5 SDK和softdevice介绍
- Nordic nRF51/nRF52开发环境搭建
- Nordic nRF51/nRF52开发流程说明
- nRF5 SDK软件架构及softdevice工作原理
- 如何调试nRF5 SDK
- 开发你的第一个BLE应用程序—Blinky
- 低功耗蓝牙配对绑定解读和实践
- NRF52832开发日志——ANT和BLE协议栈加入
- 从零开始的nrf52832蓝牙开发(2)--蓝牙模板解析
和开发相关的地址:
- 自定义服务:github.com/NordicPlayg…
- pmu6050: github.com/edwios/nrf5…
- github.com/danlonngren…
- github.com/dllgxhy/ble…
- github.com/kevinpk/lib…
- 基于NUS修改的自定义服务:www.sunyouqun.com/2018/03/loo…
官方:
- nRF Toolbox App 下载:github.com/NordicSemic…
- nRF Connect 电脑端:www.nordicsemi.com/Products/De…
- nRF Connect App 下载:github.com/NordicSemic…
官方论坛:
- NUS大量数据发送问题:devzone.nordicsemi.com/f/nordic-q-…
- 在BLE事件中写Flash失败问题:devzone.nordicsemi.com/f/nordic-q-… -- 大意是不能在BLE中写,做标志在主循环中 已遇到并解决
- sd_ble_gatts_hvx发送数据讨论:devzone.nordicsemi.com/f/nordic-q-…