一、编写说明

对duBand源码的存储部分进行分析,本文档用于记录分析过程。

二、源码分析

1. 存储区域划分

在使用nRF Studio进入程序下载时,可以看出,存储区域分为三个Region,如下图所示,分别存在蓝牙协议栈、应用程序和Bootloader。

在APP中,程序存储区域再细分为APP、DATA和SWAP区,通过阅读源码,得知区域图详细划分如下图所示(注意:duBand的设计文档区域划分与源码的不同)。在Bootloader的源码中,APP DATA的大小为42KB,但在APP的源码中,设置着PAGE_NUM_FOR_DATA为32,而NRF51822的页大小为1024 B,因此APP DATA的大小实际为32 KB,还有10 KB的存储空间没有用到。

2. 代码分析

duBand的每一类型的参数存储占用各一个FLASH页面,如ALARM、USER PROFILE、TARGET等,都各占1 KB的存储空间,但实际上只用到少量。接下来以两个实例分析的方式分析存储和读取的代码,以save_alarm()与load_alarm()为例进行分析。

duBand中的数据存储与读取函数使用了一个比较灵活和高效的方法,就是利用memcmp()与memcpy()进行操作。当有数据需要保存时,先将数据从FLASH中读取出来,再通过memcmp()进行比较,如果数据不同,则有必要保存,否则没有更新,则不保存。存储的时候使用memcpy()将新数据复制至缓冲中,再写到FLASH中。

1) save_alarm()

以save_alarm()为例,其代码如下图所示。(1)先定义数据alarm_mem[],用于存放FLASH中读取出来的数据。(2)调用bd_flash_read_page()读取FLASH内容。(3)如果读取出来的闹钟数量与设置的闹钟数量相等,(4)则检测闹钟内容是否有更新,(5)如没有更新,则不需要重新存储,直接return。如有数据更新,则继续运行下去。(6)获取ALARM存储数据的绝对地址。(7)检测FLASH是否已檫除,(8)如未檫除则需要调用ble_flash_page_delay_erase()进行异步存储,这样做的原因是因为檫除操作比较耗时,如果同步去檫除时,会导影响蓝牙程序,因此这个做了一个异步操作,详细参与异步存储。(9)否则调用save_alarms_into_flash()保存ALARM数据。

save_alarms_into_flash()为具体的存储操作函数,如下图所示。(1)定义临时数据alarm_mem[],用于存在数据。(2)将当前ALARM数据复制至alarm_mem[]中。(3)将alarm_mem[]的数据写进FLASH中。

2) load_alarm()

读取参数的函数就比较简单了,因为不涉及长时间的操作,因此不用进行异步处理,如下图所示,(1)先定义存储读取出来的数据的临时数组alarm_mem[]。(2)读取相应FLASH数据至alarm_mem[]中。如果读取失败,则清空ALARM数据,(4)如果读取成功,则将数据复制至ALARM的全局变量中。

3. 异步存储

由于FLASH的擦除操作比较耗时,为了不影响系统的实时性并不影响蓝牙通讯,当需要对FLASH擦除时,存储系统使用了异步处理事件。通过ble_flash_page_delay_erase()将要删除的页面号写入删除队列flash_page_to_erase_Q[]。具体的操作在ble_flash_erase_data_page()中进行,此函数在ble_radio_notification_init()中注册为RADIO回调事件,并由ble_flash_on_radio_active_evt()异步调用。

先来分析ble_flash_page_delay_erase()函数,如下图所示。(1)先判断目标页面是否已经存在擦除队列中,如在,则不作任何处理。(2)判断目标页面是否在APP DATA区域内,否则返回错误。(3)如果RADIO不在工作中时,则马上进行页面擦除并返回。(4)判断擦除队列是否已满,是则返回错误。(5)将目标页面写入擦除队列中。在这个函数内,其实有个陷阱,如上面所描述的第(3)步,如果这里马上删除了的话,就不会调用异步写入(后面分析)的操作,但是这个操作是无伤大雅的,如果蓝牙断开/不工作,也没有存储的必要。

将目标擦除页写入了队列后,在RADIO的ACTIVE回调函数ble_flash_on_radio_active_evt()中,如下图所示,(1)会判断队列中是否有数据和其它一些条件(如RADIO是否正在工作、蓝牙状态),(2)如有数据,则判断是否已经调用异步擦除,(3如没有则进行异步调用。

最终的擦除和更新操作是在ble_flash_erase_data_page()中完成的,此函数由app_sched调度运行。如下图所示,(1)程序先判断蓝牙是否处于工作状态,(2)如果蓝牙空闲,则可以马上进行页面擦除,(3)并调用sync_data_to_flash()更新相应页面的数据。(4)再判断是否还有需要擦除的页面,有则调用app_sched继续调度ble_flash_erase_data_page()并返回。(5)如果蓝牙正在广播或保持长连接状态下,则需要判断inactive_last_time(此值在ble_flash_on_radio_active_evt()中赋值,估计主要是用于检测是否处于有校时间内)是否合法,合法才进行页面擦除并更新相应页面的数据。

数据更新函数sync_data_to_flash()的代码如下图所示,该函数实现比较简单,只是更新不同的页号去调用相应的数据存储函数。

4. 读写校验

读写的校验在底层的函数ble_flash_page_write()和ble_flash_page_read()中实现。由于这是NORDIC提供的操作库函数,因此这里不继续分析下去了,拿来就用就好了。

【NRF51822】百度手环开源源码分析--存储部分相关推荐

  1. 【NRF51822】百度手环开源源码分析--底层通讯部分

    一.编写说明 duBand源码中的通讯部分源码较多,但细细阅读发现其分层结构清晰,很值得借鉴.为了深入对duBand通讯源码的学习,并理解通讯分层设计的思想,决定对duBand源码的通讯部分进行分析, ...

  2. 【NRF51822】百度手环开源源码分析--框架部分

    1.Main函数(main.c) a) gpio_init(); //初始化全部IO口为初始状态(输入.关上拉.关复用) b) pre_init(); //初始化时钟与RTC0并进行待机,待RTC0中 ...

  3. 【NRF51822】百度手环开源源码分析--数据自动同步部分

    1.  void send_all_data(boolis_from_cb) 发送数据都是通过send_all_data()去上传的. 1)  static boolneed_send_sync_pr ...

  4. 2022全球20多款知名的Android刷机ROM镜像和Android系统开源源码(覆盖全球机型)

    推荐阅读 ​Android10系统定制|frida逆向分析实战课程 2022全球20多款知名的Android刷机ROM镜像和Android系统开源源码(覆盖全球机型) 因此,您拥有一台Android设 ...

  5. Android开源源码推荐(一)

    qianqianlianmeng Android开源源码推荐(一) 1.Android-ViewPagerIndicator http://www.akaifa.com/code/86/android ...

  6. 很火的仿soul交友盲盒1.0全开源源码

    简介: 目前很火的仿soul交友盲盒1.0全开源源码,2000块钱购买的一套仿soul盲盒交友开源源码 网盘下载地址: http://kekewl.org/UUqVYnPqS0t0 图片:

  7. 云蹦迪云广场舞软件开源源码

    云蹦迪广场舞 意:第2,3步只在第一次运行时需要配置 一定要按照顺序执行,执行顺序有错会报错 开播 在抖音找到自己的直播间,复制直播间号(绿色区域是直播间号)(只在第一次运行时需要) 在解压后的deb ...

  8. PHP抽奖小程序/微信红包封面抽奖小程序/抽奖小程序开源源码

    PHP抽奖小程序源码,微信红包封面抽奖小程序,全开源.带流量主(需要自行替换代码),独立后台,亲测完美可用. 下载 PHP抽奖小程序/微信红包封面抽奖小程序/抽奖小程序开源源码 亲测截图:

  9. Telegram Android开源源码运行

    TG-Android开源源码运行 源码地址 https://github.com/DrKLO/Telegram 环境介绍 Android Studio版本至少3.4,或者直接去官网下载最新的 手机最低 ...

最新文章

  1. mysql+keepalived必须要lvs吗_MySQL 双主热备 + LVS + Keepalived 高可用操作记录
  2. 「后端小伙伴来学前端了」CSS 做三角边框,必会的基础操作之一
  3. pipreqs生成python项目依赖清单
  4. 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数
  5. ASP.NET Session的七点认识(转)
  6. JAVA基础知识|lambda与stream
  7. iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断)...
  8. 加载执行预编译的Sql :prepareStatement
  9. 更换百度地图图标html,百度地图接口,自定义图标,点击切换图标
  10. php页面自分页刷新,详解PHP+AJAX无刷新分页实现方法
  11. yolov5继续训练_震惊! 它来了!YOLOv5它来了!
  12. Silverlight开发的15个最佳实践
  13. 归类问题:简单的代价函数和梯度下降----吴恩达机器学习
  14. Windows10原神二次元美化主题工具包分享
  15. Win32屏幕保护程序
  16. STM32入门指南(0)—配置开发环境
  17. Android编译报 Removing unused resources requires unused code shrinking to be turned on
  18. python中气泡图文字标签_Excel中制作气泡图及为气泡图的系列数据点添加文本数据标签...
  19. 【MAUI】条形码,二维码扫描功能
  20. FlinkCEP的底层理论:NFA-b Automaton原理介绍

热门文章

  1. Oracle运维必修内功:前瞻性运维理念
  2. DCIC2021数字中国创新大赛大数据赛道-城市管理大数据专题学习
  3. Sora —— 高性能可编程无线电系统
  4. Android SDK 完整版
  5. 02 区块链的安全和隐私
  6. 电改背景下,售电公司如何利用需求侧响应模式
  7. Genesis 社区答疑—第一期
  8. 【飞轮储能】基于simulink的飞轮储能发电系统的仿真
  9. Python面向对象,从农药到吃鸡 bilibili视频笔记
  10. 前端求职刷题(第一部分)