nrf52832 学习笔记(二)SDK框架分析

个人对SDK框架的一些理解,如有错误欢迎斧正。

flash 分区


在不包含DFU的情况下,nrf52832 flash划分为:

  • MBR

    0x00000000 - 0x00001000 为主引导程序(MBR),包括中断向量表和主引导程序两部分,其中中断向量表用于处理派发中断回调函数,主引导程序主要用于判断是否存在DFU,判断跳转地址。

  • SoftDevice

    0x00001000 - 0x00026000 为协议栈程序

  • APP

    用户程序

    RAM分配

    • 协议栈占用RAM

      一般情况下把MBR+SoftDevice 统称为协议栈,协议栈占用RAM大小可以从协议栈配套文档获得。如果协议栈RAM过小,log信息会给出相应提示。

    • 用户APP使用RAM


在包含DFU的情况下,nrf52832 flash划分为:

  • MBR

    0x00000000 - 0x00001000 为主引导程序(MBR),包括中断向量表和主引导程序两部分,其中中断向量表用于处理派发中断回调函数,主引导程序主要用于判断是否存在DFU,判断跳转地址。

  • SoftDevice

    0x00001000 - 0x00026000 为协议栈程序

  • APP

    用户程序

  • bootLoader

    DFU 蓝牙空中升级boot,地址根据DFU程序大小自行设置。

  • bootLoader Parameter

    0x0007E000 - 0x00080000 DFU 蓝牙空中升级boot参数区,用于记录升级信息(升级过程断电的话,下次可以接着升级,相当与有断点续传功能),APP版本,BOOT版本,APP校验,参数区校验等信息。如果没有此分区,程序将无法正常运行。

nrf52832 启动流程

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程序。

用户app如何调用协议栈

#define SVCALL(number, return_type, signature) return_type __svc(number) signature

用户APP通过触发SVC中断的方式调用协议栈相关操作,将协议栈和用户程序完全分开,互不干预。协议栈相关函数声明都在ble.h中,以sd开头。以 sd_ble_enable 函数为例,用户在调用 sd_ble_enable 时,会触发SVC中断,协议栈中SVC中断服务函数根据 SVC服务号(SD_BLE_ENABLE)调用协议栈相应的函数进行处理,然后返回处理结果。

//SVC中断的等效代码,具体不是这样的
unsigned long svc_handler(int svc_num, void * param)
{switch(svc_num){case SD_BLE_ENABLE:{...//协议栈操作break;}...}
}

从上面代码可以看出SVC中断和其他中断服务函数不同,有参数和返回值,有参数是因为在进SVC中断前将参数入栈,中断服务函数从对应栈空间取参数。返回值则是在退出时将返回值存入R0寄存器中。具体可以看 《Cortex-M3权威指南》 第11章 使用异常系统

协议栈如何上报状态到用户观察者函数

当蓝牙事件产生时(比如扫描到广播包,连接主从机成功等),协议栈会通过软中断(SWI)将蓝牙事件分发给用户APP,用户在观察者回调函数中添加自己的处理代码。


nrf52832 flash中存在3个中断向量表,但是在APP仿真时发现SCB->VTOR为 0x00000000,因此只有MBR Vector才是真的中断向量表,发生中断时会进入MBR Vector,在MBR Vector 中调用 SoftDevice Vector 中的中断服务函数,然后在SoftDevice Vector 中的中断服务函数中再调用 app vector table。

由于中断服务函数多次跳转,相比其他单片机,nrf52832 用户中断服务函数的中断延时相对比较高。

#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used))#define NRF_SECTION_SET_ITEM_REGISTER(_name, _priority, _var)                                       \NRF_SECTION_ITEM_REGISTER(CONCAT_2(_name, _priority), _var)#define NRF_SDH_BLE_OBSERVER(_name, _prio, _handler, _context)                                      \
STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!");                                 \
STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable.");             \
NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name) =  \
{                                                                                                   \.handler   = _handler,                                                                          \.p_context = _context                                                                           \
}#define APP_BLE_OBSERVER_PRIO           3//注册观察者函数
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

在用户app中注册观察者函数,在观察者函数中处理蓝牙事件。注册观察者函数使用了一堆宏定义,这一大堆宏定义最终变成如下

static nrf_sdh_ble_evt_observer_t m_ble_observer __attribute__ ((section(sdh_ble_observers3))) __attribute__((used)) =
{.handler   =  ble_evt_handler,.p_context = NULL
}

其实就干了两件事:

  • 声明了一个静态变量
  • 将该静态变量存放在 sdh_ble_observers3 段中

    软件中断服务函数最终调用 app软件中断服务函数 SD_EVT_IRQHandler, 在 nrf_sdh_evts_poll 中遍历调用sdh_ble_observers0、sdh_ble_observers1等flash段中所有的观察者回调函数。

    因此nrf52832 sdk中蓝牙各个部分之间的耦合度非常小,每个部分都有自己的观察者回调函数。

nrf52832 学习笔记(二)SDK框架分析相关推荐

  1. motan学习笔记 二 motan架构分析

    motan学习笔记 一 微博轻量级RPC框架Motan motan学习笔记 二 motan架构分析 motan学习笔记 三 motan Demo 分析 motan学习笔记 四 motan Demo 之 ...

  2. Colly 学习笔记(二)——爬虫框架,抓取下载数据(上证A股数据下载)

    Colly 学习笔记(二)--爬虫框架,抓取下载数据(上证A股数据下载) Colly 学习笔记(一)--爬虫框架,抓取中金公司行业市盈率数据 Colly 学习笔记(二)--爬虫框架,抓取下载数据(上证 ...

  3. 【nRF51822学习教程】SDK框架分析

    本讲为框架介绍,不会牵涉到太多代码细节.51822的官方SDK其实是没有框架依耐性的.什么叫框架,比如TI的BLE SDK中就有一个操作系统抽象层(OSAL)他是一个轮训的调度.你需要按照他的方式去创 ...

  4. MonoRail学习笔记二:框架代码下载

    为了更好的学习MonoRail,我准备下载MonoRail的源代码看看. 先从http://www.castleproject.org/castle/download.html 下了一个源代码,结果编 ...

  5. motan学习笔记 三 motan Demo 分析

    motan学习笔记 一 微博轻量级RPC框架Motan motan学习笔记 二 motan架构分析 motan学习笔记 三 motan Demo 分析 motan学习笔记 四 motan Demo 之 ...

  6. Java学习笔记-Day64 Spring 框架(二)

    Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...

  7. Spring Boot 框架学习笔记(二)(配置文件与数据注入 yaml基本语法 JSR303数据验证 多环境切换 )

    Spring Boot 框架学习笔记(二) 六.appliaction.properties配置与数据注入 6.1 `@Value`注解 测试注入数据 读取输入流 6.2 读取配置文件数据注入 单文件 ...

  8. nrf52832 学习笔记(六)配对和绑定

    nrf52832 学习笔记(六)配对和绑定 配对绑定推荐博客低功耗蓝牙配对绑定解读和实践 蓝牙在配对之前都是明文通信的,也就是说主从机之间传输的数据包可以被第三方抓取分析逆向,而且如果没有配对,谁都可 ...

  9. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    Hadoop学习笔记-20.网站日志分析项目案例(一)项目介绍 网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edis ...

最新文章

  1. UIViewController生命周期
  2. 数据结构二叉树的所有基本功能实现。(C++版)
  3. OpenCV中SiftDescriptorExtractor
  4. ORA-29339错误解决办法
  5. Linux基础二(挂载、关机重启与系统等级)
  6. html如何将多个复选框组织成一组_[Selenium]18.如何处理一组元素
  7. Counting Bits
  8. 虚拟DOM Diff算法解析
  9. HTML文件属于void值吗,使用HTML :: TreeBuilder查找html文件中的值
  10. 国家计算机科学进展,计算机科学技术学院部署科研工作推进及国家自然科学基金申报工作...
  11. 同样版本的jstl,都是jstl1.2版本,有个有问题,另一个没有问题
  12. r语言矩阵运算_R中的矩阵运算
  13. 服务器系统win12可以安装CAD,技术员教你解决win10系统安装CAD2012的教程介绍
  14. 亚马逊kindle设置_亚马逊的新款Kindle Fire平板电脑:极客评论
  15. python答辩毕设ppt_毕设答辩ppt总结
  16. 专科低学历想做web前端开发拿10k、15k高薪,我建议你这样做
  17. GooglTest GoogleMock 实践感想三 死亡测试初步(1)
  18. iOS 判断机型是否为 iPhone X、XR、XS、XS Max 的方法
  19. android app防止锁屏_Android 禁止屏幕休眠和锁屏的方法
  20. day2和day3随堂笔记

热门文章

  1. python 机械臂控制_从零开始的ROS四轴机械臂控制-gazebo仿真控制
  2. 九州云重磅推出基于Rocky版本全新开源云管理平台
  3. c语言pta整数四则运算,练习2-9 整数四则运算
  4. python 抢购还是js抢购好_一句JS帮你秒杀,抢购
  5. Wink Hub:老牌家居商的智能中控平台
  6. python scrapy ,几行代码实现一个【搜狗图片】下载器
  7. Pytorch 目标检测和数据集
  8. java asynctask完成_使用 AsyncTask实现异步处理
  9. win7自带的绿化版的office2007怎么卸载
  10. 【自动化测试】接口测试之RESTful接口