nRF5 SDK 入门(三、理解 nRF5 SDK 应用与协议栈分开烧录)

说明一下 Nordic nRF5 SDK 软件 应用程序 和 协议栈分开烧录的理解

前言

上一篇文章我们了解了 Nordic nRF5 SDK 目录结构,在那之前我们也已经搭建好了开发环境,实际上我们就已经可以进入我们的开发之旅了,但是如果刚接触 Nordic 蓝牙开发的小伙伴总是会有一些疑问:

1、Nordic 蓝牙开发应用程序和协议栈分开是什么意思?
2、分开了那工程开发,烧录岂不是相当复杂?

带着这些问题,本文我们就来了了解 nRF5 SDK 应用与协议栈分开烧录是怎么一回事。

Nordic nRF5 SDK 入门系列博文:
GCC + Vscode 搭建 nRF52xxx 开发环境
nRF5 SDK 入门(二、了解 nRF5 SDK 目录结构)
.
我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

一、 ARM 内核启动过程

我们的使用的 nRF52xxx 芯片是 M4 内核,在讨论本文标题的问题之前,我们得复习一下 M4 内核启动相关的知识点。

1.1 启动过程

CPU 复位后会从 0x00000000 处取得第一条指令开始运行 ,ARM Cortex-M/R 内核在复位后,也会从 0x0000 0000 处开始执行:它是从地址 0x0000_0000 处取出 MSP 的初始值;从地址 0x0000_0004 处取出 PC 的初始值,然后从这个值对应的地址处取指。事实上,地址 0x00000004 开始存放的就是默认中断向量表。

在这里插入图片描述

上图是 M3 内核,这一点和 M4 内核是一样的。所以我们想要程序正常运行,就得从 0x0000 0000 这个地址开始存放程序。

1.2 程序存放位置

STM32 的程序存放位置:

这里回忆一下熟悉的 STM32 ,我们一般而言,程序存放的位置为 0X0800 0000,那是因为 STM32 为了方便不同的方式启动,所以 把前面 0x0000 0000 开始的空间让出来了,为了实现存储重映射的功能。可以使得芯片从内部 Flash, 系统存储器,内部 SRAM 启动,不同的启动方式只需要把不同的地址重映射到 0x0000 0000 即可。

在 STM32 的工程中,在很多地方都能够直接体现程序存放的这个地址:

在这里插入图片描述

但是和大多数芯片一样的是 ,STM32 的程序也只需要烧录一次 。

Nordic 的芯片没有用到类似 STM32 的存储重映射的功能,所以因为 内核 需要从0x0000 0000 开始执行程序,所以它必然需要把程序从 0 地址开始存放。(官方的例程是这样,如果个人测试采用其他方式不算。)

到这里我们只是确定了 Nordic 的芯片的程序必须要从 0 开始存放 ,但是 Nordic 还做了另外的一种事情,就是把程序分成了两部分!

二、nRF5 SDK 程序存储方式

我们在上一篇文章说明了一个问题:

在这里插入图片描述
一个裸机程序,单独烧录至 0x26000 处程序不会运行,如果烧录至 0x0 位置处,可以正常运行,也正是说明 Nordic 的芯片是从 0x0 地址开始运行程序的,那么为什么官方的示例会把位置放在 0x26000 处,而不是 0x0 处,这就是 Nordic 与其他厂商处理不一样的地方。

2.1 nRF5 SDK 的区分存储

实际上,我们通常的思维会是:

反正都是程序,协议栈也是程序,都在一个工程里面,编译过后生成一个 hex ,直接放到 0x0 的地址上直接运行即可。

对于 nRF5 SDK 而言,它们是把 协议栈 和 应用程序 分开处理,对于这一点,有位 Nordic 中国区的 FAE 在某园上写过一篇文章:《 nRF5 SDK软件架构及softdevice工作原理 》(文章大家可以直接度娘搜索,因为涉及到外站竞争链接,所以这里就不放了)里面很好的说明了这个问题,以下说明取自这篇文章:

Nordic nRF5 SDK将芯片的存储器划分成如下格局:
在这里插入图片描述
上面推荐文章中,有详细的说明:

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)形式提供给大家的, 这一点我们通过 SDK 文件夹下的内容也能知道,如图:

在这里插入图片描述

所以我们开发中比较关心的问题,听起来分开处理感觉会变得麻烦很多,实际上协议栈我们并不需要编程,编译,直接有现成的,只需要知道如何烧录到对应位置即可。

2.2 MBR 是什么

在 nRF5 SDK 中,MBR 是 Master Boot Record(主引导记录),是一个独立的组件,位于 Flash 存储器的开头,通常在地址 0x0 处。

MBR 具有以下几个主要作用:

  1. 启动加载程序(Bootloader):
    MBR 包含一个启动加载程序,用于加载和启动 SoftDevice 和应用程序。这使得设备能够在启动时执行一些初始化步骤,例如加载蓝牙协议栈(SoftDevice)以及其他必要的固件。

  2. Flash 区域划分:
    MBR 也负责划分 Flash 存储器的不同区域,包括 SoftDevice 区域和用户应用程序区域。这有助于将不同功能的代码和数据存储在不同的 Flash 区域中,使得固件更新更加方便。

  3. 错误处理和恢复:
    MBR 包含错误处理和恢复的机制,以确保设备在出现问题时有一些自我修复的能力。这有助于提高设备的稳定性和可靠性。

至于 MBR Vector Table:

在 nRF5 SDK 中,MBR Vector Table 是 Master Boot Record(MBR)的 Vector Table,即 MBR 中用于处理中断和异常的 Vector Table。

Vector Table 是一个存储在特定地址的数据结构,其中包含处理器执行中断服务例程(Interrupt Service Routines,ISR)的地址。当处理器检测到中断或异常时,它会查找相应中断号或异常号在 Vector Table 中对应的地址,然后跳转到该地址执行相应的代码。

对于 MBR Vector Table,主要包含了一些基本的中断和异常处理例程,用于启动加载程序(Bootloader)的初始化、启动和错误处理。这确保了设备在启动时能够正确地执行必要的操作,例如加载 SoftDevice 和应用程序。

在 nRF5 SDK 中,MBR Vector Table 的地址通常是 0x0,即 Flash 存储器的起始地址。Vector Table 的结构和内容是由 ARM Cortex-M 架构定义的,具体实现和配置则由 Nordic 在 MBR 中进行。

总体来说,MBR 在 nRF5 SDK 中扮演着一个引导和初始化的角色,为设备启动时的操作提供了基本的结构和功能。在应用程序开发中,开发者通常不需要深入了解 MBR 的内部工作原理,因为 nRF5 SDK 提供了一些高层次的抽象,使得开发者可以方便地进行应用程序开发而不必关心底层的细节。

2.3 分开处理的好处

Nordic 这样分开处理好处,在上面大佬的文章也有详细的说明:

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

对于具体的 协议栈与应用 的细节大家可以自己查看上面推荐的文章《 nRF5 SDK软件架构及softdevice工作原理 》,或者等到后期随着我们的开发到了那一步,我也会详细的分析一下,在上面文章的结尾,有下面一段话,可以让大家对使用 Nordic nRF5 SDK 不那么刚到害怕:

从上面nRF5 SDK软件架构的讲解过程中,我们可以看到,当我们开发Nordic平台的BLE应用时,主要需要做两件事:
.
第1件事:初始化。为了简化初始化工作,Nordic SDK所有模块初始化时,只需要将相应API输入结构体参数清0即可完成初始化工作,也就是说,只要你保证初始化参数为0,蓝牙协议栈就可以工作起来,这对很多Nordic初学者来说,大大减轻了开发工作量。
.
第2件事:写蓝牙事件回调处理函数。一般来说,你的应用逻辑都是放在蓝牙事件回调处理函数中,所以写好回调处理函数代码,你的开发工作就完成了大半了。

三、 烧录说明

到这里,大家应该都能够理解与接受 Nordic nRF5 SDK 对于应用于协议栈分开处理的方式了,那么回到文章最开头的两个问题:

1、Nordic 蓝牙开发应用程序和协议栈分开是什么意思?
2、分开了那工程开发,烧录岂不是相当复杂?

第一个问题,我们在上文已经得到了答案,第二个问题其实我们也已经解决了一半,并不会更加复杂,因为我们还是只需要注重我们的应用程序即可。

本小节来讲一下烧录问题,首先我们的示例编译过后会生成一个 hex 文件,加上协议栈的 hex 文件,一共是两个 hex 文件。

这里我再次再次再次复习一个知识点:对于 .hex 文件来说,他包含了存放地址信息,可以直接烧录会根据链接文件存放至对应的地址。

就用我们的 J-Flash 工具来说,我们已经知道,示例编译过后拖动至 J-Flash ,它自动会显示需要存放在 flash 中的位置,应用程序如下图:

在这里插入图片描述

那同样的,我们也可以把协议栈 hex 文件用同样的方式烧录,我们拖动至 J-Flash ,如下图:

在这里插入图片描述

他们两个 hex 的存放位置是不一样的,我们可以直接按照正常步骤连接然后烧录 :

在这里插入图片描述

这样就好了! 并没有什么特别需要你注意的,不会存在什么覆盖啊,搞错之类的问题。

同样的,即便我们不用 J-Flash ,我们在我们搭建好的开发环境下面,使用命令烧录,大家可以查看一下 Makefile 最后的伪指令:

在这里插入图片描述

也只是需要我们敲两下命令即可,并没有过多的工作。

当然,大家用官方的 nRFgo Studo ,原理也是一样的,只要搞清楚程序存放的形式,就没那么难了。

但是这里有一点,对于使用 Keil 开发来说, 他的 hex 存放位置也是可以设置的:

在这里插入图片描述

上面是外设的裸机测试,如果是带协议栈的,那么在 keil 中是需要把上面地址修修改的,如下图:

在这里插入图片描述

在 Keil 中,如果要烧录协议栈,在工程中如下位置,选择协议栈,点击 LOAD 进行烧录:

在这里插入图片描述

或者借助第三方工具 nRFgo Studo 或者直接使用 J-Flash 进行协议栈烧录。

结语

本文我们主要了解了一下 Nordic nRF5 SDK 应用与协议栈分开处理的方式,通过文章我们应该明白了分开处理的是什么意思,分开的好处,以及对我们实际应用开发的影响。

详细大家都能够感受到,这种方式不仅不会让我们开发变得更加复杂,反而能够让我们专心与自己的应用程序,同时也跟让我们更好的定位开发过程中遇到的问题,相应付出的代价只不过是我们需要多烧录一次 hex而已。

好了,本文就到这里,谢谢大家!

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

矜辰所致

您们的鼓励是我奋斗的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值