nRF5 SDK软件架构及softdevice工作原理
本文将介绍Nordic nRF5 SDK软件架构以及softdevice工作原理,以加深大家对Nordic产品开发的理解,这样开发过程中碰到问题时,大家也知道如何去调试。
如果你刚开始接触nRF5 SDK,建议先看一下这篇文章“Nordic nRF5 SDK和softdevice介绍”,以建立Nordic nRF5 SDK的一些基本知识。
首先说明一下,Nordic nRF5系列产品都是使用Flash存储器的,确切说,是嵌入式可执行代码的Flash存储器,也就是说,代码是可以直接在上面运行的,这个跟很多其他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不是以库的形式提供给大家,而是以二进制文件(hex文件)的形式提供给大家,这种方式可以带来很多好处。首先二进制形式可以保证蓝牙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,从而达到通知应用程序相关事件的目的。事件通知流程如下所示:
为了达到各个软件模块松耦合的目的,每个软件模块,比如广播模块,可以单独注册自己的BLE事件回调处理函数,然后在自己的事件回调处理函数里面只处理跟本模块有关的事件,与本模块无关的事件不进行处理而直接返回。这里需要注意两点:一虽然每个BLE事件回调处理函数只处理跟本模块有关的事件,但是它是可以捕获所有BLE事件的,你可以让整个应用程序只有一个BLE事件回调处理函数,但这样会让各个模块紧密地耦合在一起,因此Nordic SDK没有这么做,尤其是SDK14以后,各个模块都自己注册自己的蓝牙事件回调处理函数,完全跟用户代码切割开,同样如果用户代码需要捕获BLE事件的话,只需注册自己的BLE事件回调处理函数即可。二BLE事件是异步的,所以有时BLE事件回调处理函数会同时收到多个BLE事件,也就是BLE事件回调处理函数有可能在很短的时间内被调用多次(BLE事件回调处理函数每次只处理一个事件case,然后返回,所以短时间内会被调用多次),这个在开发的时候需要注意一下。
从上面nRF5 SDK软件架构的讲解过程中,我们可以看到,当我们开发Nordic平台的BLE应用时,主要需要做两件事:
- 第1件事:初始化。为了简化初始化工作,Nordic SDK所有模块初始化时,只需要将相应API输入结构体参数清0即可完成初始化工作,也就是说,只要你保证初始化参数为0,蓝牙协议栈就可以工作起来,这对很多Nordic初学者来说,大大减轻了开发工作量。
- 第2件事:写蓝牙事件回调处理函数。一般来说,你的应用逻辑都是放在蓝牙事件回调处理函数中,所以写好回调处理函数代码,你的开发工作就完成了大半了。
nRF5 SDK软件架构就写在这里,如果你对如何调试nRF5 SDK感到困惑的话,请参考下一篇文章:
如何调试nRF5 SDK
nRF5 SDK软件架构及softdevice工作原理的更多相关文章
- Nordic nRF5 SDK和softdevice介绍
SDK和Softdevice的区别是什么?怎么选择SDK和softdevice版本?芯片,SDK和softdevice有没有版本兼容问题?怎么理解SDK目录结构?SDK帮助文档在哪里?Softdevi ...
- 如何调试nRF5 SDK
本文将讲述Nordic nRF5 SDK的主要调试手段,以帮助大家快速定位问题,并解决问题.一般来说,你可以通过打log方式,IDE的debug模式,SDK自带的app_error_check函数,以 ...
- Web服务器的工作原理
Web服务器的工作原理 Web服务器工作原理概述 很多时候我们都想知道,web容器或web服务器(比如Tomcat或者jboss)是怎样工作的?它们是怎样处理来自全世界的http请求的?它们在幕后做了 ...
- keepalived工作原理和配置说明 腾讯云VPC内通过keepalived搭建高可用主备集群
keepalived工作原理和配置说明 腾讯云VPC内通过keepalived搭建高可用主备集群 内网路由都用mac地址 一个mac地址绑定多个ip一个网卡只能一个mac地址,而且mac地址无法改,但 ...
- web服务器工作原理
Web服务器工作原理概述 转载自http://www.importnew.com/15020.html 很多时候我们都想知道,web容器或web服务器(比如Tomcat或者jboss)是怎样工作的?它 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(一)
通过分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.我们先从update.zip包的制作开始,然后是Android系统的启动 ...
- Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)
一.引文 前篇博文<Makefile之Linux内核模块的Makefile写法分析>,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6 ...
- 初涉IPC,了解AIDL的工作原理及使用方法
初涉IPC,了解AIDL的工作原理及使用方法 今天来讲讲AIDL,这个神秘的AIDL,也是最近在学习的,看了某课大神的讲解写下的blog,希望结合自己的看法给各位同价通俗易懂的讲解 官方文档:http ...
- Appium简介及工作原理
一.什么是Appium Appium是一个开源.跨平台的测试框架,可以用来测试原生及混合的移动端应用.Appium支持IOS.Android及FirefoxOS平台.Appium使用WebDriver ...
随机推荐
- oracle入门(8)——实战:支持可变长参数、多种条件、多个参数排序、分页的存储过程查询组件
[本文介绍] 学了好几天,由于项目需要,忙活了两天,写出了个小组件,不过现在还只能支持单表操作.也没考虑算法上的优化,查询速度要比hibernate只快了一点点,可能是不涉及多表查询的缘故吧,多表的情 ...
- (2.5)Mysql之SQL基础——数据类型
(2.5)Mysql之SQL基础——数据类型 关键词:mysql数据类型 目录: 一.整数型 二.小数型(以下均不能使用无符号) 三.日期时间型 四.字符串型 一.整数型 额外参数示例: int [( ...
- Java基础—输入输出流
流的概念 在Java中,流是从源到目的地的字节的有序序列.Java中有两种基本的流——输入流(InputStream)和输出流(OutputStream). 根据流相对于程序的另一个端点的不同,分为节 ...
- java堆结构和垃圾回收
JVM内存结构和垃圾回收一.JVM垃圾收集算法1.引用计数算法 每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收. 此方法简单,无法解决对象互相循环引用的问题 ...
- JAVA math包
Math类: java.lang.Math 类中包含基本的数字操作,如指数.对数.平方根和三角函数. java.math是一个包,提供用于执行任意精度整数(BigInteger)算法和任意精度小数(B ...
- linux安装以及相关配置
计算机操作系统简介 操作系统是什么 操作系统的内核是什么 两种操作系统用户界面 安装Linux操作系统的准备工作 LINUX发行版(CENTOS.RHEL.FEDORA.UBUNTU.SUSE) RH ...
- 09 grep、正则表达式和sed
作业一:整理正则表达式博客 ^ 行首$ 行尾. 除了换行符以外的任意单个字符* 前导字符的零个或多个.* 所有字符[] 字符组内的任一字符[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)^ ...
- Springboot 日志管理配置logback-spring.xml
几种常见的日志 Log4j:是最早的日志框架,是apach旗下的,可以单独使用,也可配合日志框架JCL使用: Log4j2:apach旗下的关于log4j的升级版: Logback:是基于slf4j接 ...
- Jackson /常用注解/ annotation(转)
1.@JsonAutoDetect 自动检测,(作用在类上)来开启/禁止自动检测. fieldVisibility:字段的可见级别 ANY:任何级别的字段都可以自动识别 NONE:所有字段都不可以自动 ...
- ruby中的self
self,自己,在ruby中表示当前对象或默认对象.程序执行的任一时刻,有且仅有一个self. 1.谁成为self,在什么位置成为self? 要知道哪个对象是self,就必须知道当前的上下文.上下文主 ...