nRF5 SDK软件架构及softdevice工作原理

本文将介绍Nordic nRF5 SDK软件架构以及softdevice工作原理,以加深大家对Nordic产品开发的理解,这样开发过程中碰到问题时,大家也知道如何去调试。

如果你刚开始接触Nordic nRF5 SDK,建议先看一下这篇文章“Nordic nRF5 SDK和softdevice介绍”,以建立nRF5 SDK的一些基本知识。

首先说明一下,Nordic nRF5系列产品都是使用Flash存储器的,确切说,是eFlash存储器,也就是说,代码是可以直接在上面运行的,这个跟很多其他BLE厂商是不一样的(他们使用的是nand Flash,代码是不能直接在nand Flash中运行的,必须先装载到RAM中才能跑,所以你会发现这些厂商的RAM都非常大)。Nordic Flash是带cache机制的,以保证大部分代码执行速度可以达到64MHz,在cache失败的时候,等待周期也只有1个cycle,可以说Flash的执行速度和效率都是非常不错的。另外,Nordic芯片是纯Flash产品,里面没有其他NVM,所有非易失性数据都放在Flash中,包括蓝牙协议栈,这也是为什么Nordic蓝牙协议栈也可以OTA的根本原因所在。

Nordic nRF5 SDK将芯片的存储器划分成如下格局:

 

           Flash结构图                                                        RAM结构图

从上图可知,Flash存储器最下面放的是softdevice(softdevice就是蓝牙协议栈,图中的MBR也属于softdevice的一部分),中间是application,最上面是bootloader(可选,只有需要OTA的时候,才需要下载bootloader)。这里需要特别指出的是,softdevice是以二进制形式提供给大家的,它占据了Flash的一块固定空间,起始地址为0,结束地址为APP_CODE_BASE。softdevice同时占用了RAM的一块固定空间,起始地址为0x20000000,结束地址为APP_RAM_BASE。Softdevice占用的Flash空间是固定不变的,运行时不可调节,也就是说APP_CODE_BASE是一个固定值,而softdevice占用的RAM空间是动态可调的,跟softdevice配置和蓝牙服务的多少有直接关联,所以APP_RAM_BASE一定要根据应用的实际情况进行调整。

这里说明一下, Softdevice不是以库的形式提供给大家,而是以二进制文件的形式提供给大家,这种方式可以带来很多好处。首先二进制形式可以保证蓝牙BQB认证的版本和发布给客户的版本一模一样(因为库形式的版本每次编译都会产生少许差异!)。其次softdevice不需要跟你的应用一起编译或者链接,大大节省调试时间,更主要的是,Softdevice运行在固定的Flash空间中,使用固定的RAM空间,从而与你的应用完全隔离开,实现了真正的模块分离,从而出现问题时,可以迅速定位是协议栈的问题还是应用的问题。再次二进制形式的 Softdevice开启了保护机制,应用代码是不能对其进行访问的,以保证Softdevice的安全性,防止应用代码误访问或者误擦除某些softdevice区域。最后这种多bin形式使得OTA变得非常灵活,你可以只OTA应用,也可以OTA协议栈和bootloader,或者三者同时OTA。

上面是站在芯片存储器角度来看nRF5 SDK的结构划分。如果站在软件架构角度,nRF5 SDK可以划分成如下结构图:

 

由上图可知,最下面是芯片本身,然后是ARM公司的CMSIS库,再往上就是协议栈softdevice和设备驱动,最后就是application和标准的蓝牙service了。softdevice是以二进制文件形式提供给大家的,除此之外,其他所有的SDK代码(少数库除外)都是开源的,以方便大家开发。应用程序,包括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是以二进制文件形式提供给大家的,那么应用是如何做到可以成功调用softdevice API的?其实,softdevice是通过SVC中断和软中断来实现与应用程序交互的。每一个softdevice API对应一个SVC异常号(softdevice API是非阻塞的),也就是说,每当应用程序调用softdevice API,其实是产生一个SVC异常,然后进入到softdevice协议栈,由softdevice的SVC handler进行相应处理。示例代码如下所示:

Softdevice API调用流程如下所示:

 

每当softdevice完成相关重要操作,都会以事件形式通知应用程序的,比如与手机连接成功,softdevice就会把BLE_GAP_EVT_CONNECTED事件告知应用程序,那softdevice是如何把相关事件告知给应用程序的?这个是通过软中断来实现的。每当softdevice完成相关操作,就会把对应的事件放入一个队列中,然后触发一个软中断,以重新回到应用程序环境中,应用程序在相关软中断handler中查询该队列,一旦发现有事件在里面,就回调相关函数,比如ble_evt_handler,从而达到通知应用程序相关事件的目的。事件通知流程如下所示:

 

猜你喜欢

转载自www.cnblogs.com/iini/p/9332463.html
nrf