1.5.2 Softdevice协议栈介绍
Nordic Softdevice协议栈是以二进制文件(hex文件)的方式提供的,而不是库的方式,Softdevice协议栈的二进制文件可在开发或生产期间烧写到nRF系列芯片中,这种方式有以下优点:
(1)一致性。Softdevice协议栈是以二进制文件方式提供的,可以保证蓝牙BQB认证的协议栈版本与客户使用的版本完全一致,可避免在每次编译时都产生差异(使用库的方式会在编译时产生差异)。
(2)高效性。由于开发与调试时无须与应用代码一起编译及链接,可大大节省调试时间。
(3)安全性。Softdevice协议栈运行在固定的Flash空间中,使用固定的RAM空间,从而与所开发的应用代码完全隔离开,实现了真正物理上的区隔,当出现问题时,可以快速定位是协议栈的问题还是应用代码的问题。Softdevice协议栈还具备安全保护机制,应用代码不能对其进行直接访问,可确保Softdevice的安全性,防止应用代码误访问或者误擦除某些Softdevice区域。
(4)支持蓝牙规范版本持续升级。随着蓝牙新规范的发布,在硬件不变的情况下可以通过升级协议栈来支持新特性,使产品具备持续升级的能力。
(5)灵活性。采用DFU升级非常灵活,可以单独升级应用固件,或者单独升级Softdevice协议栈和Bootloader,或者同时升级应用固件、Softdevice协议栈和Bootloader。
在Nordic的SoC芯片中Flash放置了Softdevice协议栈(图1-54中的MBR也属于Softdevice协议栈的一部分)、Application应用和Bootloader引导程序(可选,需要进行空中升级时,才需要到Bootloader)。
图1-54
Softdevice协议栈占据了Flash的一个固定空间,起始地址为0,结束地址为APP_CODE_BASE。Softdevice协议栈同时还占用了RAM的一个固定空间,起始地址为0x20000000,结束地址为APP_RAM_BASE。Softdevice议栈占用的Flash空间是固定不变的,在运行时不可调节,也就是说APP_CODE_BASE是一个固定值,而Softdevice协议栈所占用的RAM空间是可以动态调整的,所需的RAM空间大小与Softdevice协议栈的配置,以及蓝牙服务的多少有直接关联,所以APP_RAM_BASE可以根据应用的实际情况进行调整。
注意:在某些情况下,当应用代码所需的RAM空间处于临界值,并且只需要增加少量的RAM空间就可满足需要时,可以通过调整ATTR属性表的大小向协议栈借用RAM空间。
Softdevice协议栈是通过应用程序接口(API)来调用应用代码的,API是一个标准的C语言函数集和数据类型,这些函数集和数据类型实现了完整的应用层编译接口和链接接口,与Softdevice协议栈相对独立。
应用程序(包括SDK代码)是通过Softdevice协议栈的API来与Softdevice协议栈进行交互的,Softdevice协议栈的API以sd_为前缀,如sd_softdevice_enable()、sd_ble_gap_adv_start()、sd_flash_write()、sd_ppi_channel_assign()。
Softdevice协议栈的API有两种类型:
(1)与BLE协议有关的API,如sd_ble_gap_connect()、sd_ble_gatts_hvx()等。
(2)与外设操作有关的API,如sd_flash_write()、sd_power_gpregret_set()等。由于Softdevice协议栈会使用某些外设,当与应用程序访问这些外设时,不能通过普通的外设驱动API来访问,必须通过Softdevice协议栈的API来访问。
注意:Softdevice协议栈的API说明一般都放在头文件中,而不是.c文件中,头文件中有该API详细说明和使用注意事项。
Softdevice协议栈是通过SVC中断和软中断与应用程序进行交互的。Softdevice协议栈的每一个API都对应一个SVC异常号(Softdevice协议栈的API是非阻塞的),也就是说,每当应用程序调用Softdevice协议栈的API时,都会先产生一个SVC异常,然后进入Softdevice协议栈,由Softdevice协议栈的SVC handler进行相应处理。示例代码如图1-55所示。
图1-55
Softdevice协议栈的API调用流程如图1-56所示。
图1-56
当Softdevice协议栈完成相关操作后,都会以事件的形式来通知应用程序。例如,当与手机连接成功时,Softdevice协议栈就会把BLE_GAP_EVT_CONNECTED事件告知应用程序。Softdevice协议栈是如何通知应用程序的呢?这是通过软中断来实现的。当Softdevice协议栈完成相关操作后,就会先把对应的事件放入一个队列中,然后触发一个软中断,重新回到应用程序中。应用程序在软中断handler中查询该队列,一旦发现有事件在队列中,就回调相关函数进行处理,如ble_evt_handler,从而达到通知应用程序的目的。事件通知流程如图1-57所示。
图1-57
Softdevice协议栈的名称代表该协议栈所能支持的主要特性,在这里简要介绍一下Softdevice协议栈的命名规则。
Softdevice一般包括两种底层协议栈(后续将支持更多底层协议栈):BLE和ANT,而BLE包括两种角色:主机(Central,又称为Master)和从机(Peripheral,又称为Slave),为此需要给这些不同类型的协议栈进行命名区分。
协议栈命名格式为Sxyz,其含义如表1-5所示。
表1-5
S110:只支持从机,以及nRF51系列芯片的BLE。
S130:既支持从机又支持主机,以及nRF51系列芯片的BLE。
S132:既支持从机又支持主机,以及nRF52系列芯片的BLE。
S212:支持nRF52系列芯片的ANT。
S332:支持nRF52系列芯片的BLE和ANT,BLE协议栈既支持从机又支持主机。
Softdevice协议栈还支持另一种命名规则,主要针对新推出的nRF系列芯片,支持更多的无线协议类型,表示该命名规则同表1-5大体相同,但协议栈编号最后2位和芯片型号相同,如S140,表示该协议栈专门用于nRF52840。由于nRF52840的Flash空间及资源比较丰富,没有必要做各种细分角色的协议栈。S140协议栈是一个大而全的协议栈,包含了低功耗蓝牙所有功能。
不同版本的Softdevice协议栈均有相应的规格书,如S140_SoftDevice Specification_v2.1,该规格书用来描述该版本Softdevice协议栈的工作原理、资源占用情况、性能参数、使用注意事项等。建议开发者下载及查阅Softdevice协议栈的规格书,确保正确使用该协议栈。每个版本的SDK都由相应版本的Softdevice协议栈与其相适配,不同的协议栈需要不同的存储空间和硬件资源。同一个版本的Softdevice协议栈需要的Flash空间是固定的,但所需的RAM空间会随具体应用而发生变化。Softdevice协议栈除了需要最小RAM空间,还会占用部分调用堆栈(Call Stack)空间,因此在规划RAM的空间时,需要把最极端情况下(Worst-case)所需增加的RAM空间考虑进去。
(1)各版本Softdevice协议栈所需的Flash和RAM空间如表1-6所示。
表1-6
(2)nRF52系列不同型号的芯片有不同的存储空间,如表1-7所示。除了nRF52832有两种不同的存储空间(以后缀-xxAA和-xxAB区分),其他型号芯片的存储空间都是固定的。在选择具体的芯片型号时,存储空间是一个非常重要的因素,将决定产品可以实现的复杂程度,以及低功耗蓝牙设备可充当的角色。
表1-7
(3)Softdevice协议栈支持的芯片类型。低功耗蓝牙5.x采用的是C/S架构,在正常的一对一通信中,其中一个低功耗蓝牙设备会充当主机,另一个低功耗蓝牙设备会充当从机。不同版本的协议栈可以支持的角色是不同的,如S112协议栈和S113协议栈只支持从机,S122协议栈只支持主机,S132协议栈和S140协议栈既支持主机也支持从机。
在选择协议栈时,可以根据芯片支持的协议栈版本,以及芯片充当的角色来选择合适的协议栈。如果芯片的存储空间充足,则可以选择同时支持主机和从机的协议栈;则如果芯片的存储空间紧张,在实际应用中该芯片只会充当主机或从机,则可以选择只支持一个角色的协议栈,从而节省一定的存储空间。芯片可以充当的角色、支持的协议栈版本如表1-8所示。
表1-8
(4)从协议栈借用RAM空间。当RAM空间处于临界值,并且只需要增加少量的RAM空间就可满足应用需要,而又不想更换芯片型号时,可以通过调整ATTR属性表的大小向协议栈借用RAM空间。
上面的语句定义了协议栈ATTR属性表的默认大小,可以尝试通过减小ATTR属性表的大小来借用(同时调整RAM_START)RAM空间。例如,HRS例程的RAM配置为:
将其改为:
相当于分配给协议栈的RAM空间少了16B,这时直接编译烧写HRS例程,会发现HRS例程跑不起来,系统提示RAM空间不足。只要通过下面的语句将ATTR属性表减小16B,HRS例程就可以正常运行,不会再报错。
在实际应用中,将ATTR属性表减小的值需要根据具体的应用来确定,可以通过反复尝试来找到合适的值。注意:在存储空间充足的情况下,不建议调整工程的默认配置。