这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
cc2640r2f:application_architecture [2017/09/02 11:39] long |
cc2640r2f:application_architecture [2021/06/22 23:14] (当前版本) |
||
---|---|---|---|
行 3: | 行 3: | ||
# 应用程序 # | # 应用程序 # | ||
- | 本章节将详细讲解 CC2640R2F BLE5.0 的应用程序框架,我们希望您已经按照学习线路图储备了< | + | 本章节将详细讲解 CC2640R2F BLE5.0 的应用程序框架,我们希望您已经按照学习线路图储备了< |
- | 本章主要内容是围绕 TI-RTOS 的 App 应用程序框架。 | + | 本章主要内容是围绕基于 |
![](http:// | ![](http:// | ||
+ | |||
+ | 图1. 应用程序框架图 | ||
以 simple_peripheral Demo 应用程序部分为例,包括以下内容: | 以 simple_peripheral Demo 应用程序部分为例,包括以下内容: | ||
行 68: | 行 70: | ||
** ICALL **源码在应用工程(例如本文的 simple_peripheral )的 ICALL BLE/ICALL 文件夹路径。 | ** ICALL **源码在应用工程(例如本文的 simple_peripheral )的 ICALL BLE/ICALL 文件夹路径。 | ||
- | ![ICall 应用-协议栈 抽象](http:// | + | ![](http:// |
+ | |||
+ | 图2. ICall 应用-协议栈 抽象 | ||
### ICall BLE5 协议栈服务端 ### | ### ICall BLE5 协议栈服务端 ### | ||
- | 如上图所示,** ICALL **实现包含一个客户端实体(例如我们的应用程序)和一个服务器实体(即这里的 BLE5.0 协议栈)之间的通信。 | + | 如图 |
> **注意** :正确区分** ICALL **框架的 CS 架构以及 GATT 服务器和客户端的架构,后者主要由 BLE 协议栈所定义实现。 | > **注意** :正确区分** ICALL **框架的 CS 架构以及 GATT 服务器和客户端的架构,后者主要由 BLE 协议栈所定义实现。 | ||
行 172: | 行 176: | ||
### 示例 ICall 用法 ### | ### 示例 ICall 用法 ### | ||
- | 下图显示了一个通过 ICall 框架从应用程序发送到 BLE5-Stack 的示例命令,并将相应的返回值传回给应用程序。 | + | 图 3 显示了一个通过 ICall 框架从应用程序发送到 BLE5-Stack 的示例命令,并将相应的返回值传回给应用程序。 |
ICall _init()完成初始化 ICall 模块实例,ICall_createRemoteTasks()使用已知地址的入口函数为协议栈创建任务。 | ICall _init()完成初始化 ICall 模块实例,ICall_createRemoteTasks()使用已知地址的入口函数为协议栈创建任务。 | ||
行 182: | 行 186: | ||
协议命令不在应用程序的线程中执行,而是封装在ICall消息中执行,是由 ICall 框架发送到 BLE5-Stack 任务。该命令被发送到 ICALL 调度程序,它在 BLE5-Stack 上下文中调度和执行;同时应用程序线程阻塞,直到接收到相应的命令状态消息;BLE5-Stack 完成执行命令,然后通过 ICall 将命令状态消息响应发送回应用程序线程。这种交换的示例图如下所示。 | 协议命令不在应用程序的线程中执行,而是封装在ICall消息中执行,是由 ICall 框架发送到 BLE5-Stack 任务。该命令被发送到 ICALL 调度程序,它在 BLE5-Stack 上下文中调度和执行;同时应用程序线程阻塞,直到接收到相应的命令状态消息;BLE5-Stack 完成执行命令,然后通过 ICall 将命令状态消息响应发送回应用程序线程。这种交换的示例图如下所示。 | ||
- | ![ ICall 消息传递示例](http:// | + | ![](http:// |
- | 通过以上理论知识储备,我们实际出发思考并解决以下问题: | + | 图3. ICall 消息传递示例 |
+ | |||
+ | 有了以上理论知识储备,我们尝试解决以下问题: | ||
### BLE-Stack 工程是如何作为 App 中 TI-RTOS 的一个任务运行的 ### | ### BLE-Stack 工程是如何作为 App 中 TI-RTOS 的一个任务运行的 ### | ||
行 343: | 行 349: | ||
### 如何调试协议栈任务 ### | ### 如何调试协议栈任务 ### | ||
- | 因为协议栈任务分布在另外一个工程,所以没有向原来那样直接加断点调试。经过前面的学习,我们已经了解协议栈是如何作为一个任务在应用工程中启动的,找到协议任务入口地址就是调试协议栈任务的关键。 | + | 因为协议栈任务分布在另外一个工程,所以没有向原来那样直接加断点调试。已经了解协议栈是如何作为一个任务在应用工程中启动的,那么调试协议栈任务的关键是找到协议任务入口地址。 |
在调试协议栈任务之前,建议将分别设置协议栈和应用工程优化等级 Project -> Opitons -> C/C++ Compiler Optimizations -> Level -> None 为无,这对正常调试协议栈任务至关重要。 | 在调试协议栈任务之前,建议将分别设置协议栈和应用工程优化等级 Project -> Opitons -> C/C++ Compiler Optimizations -> Level -> None 为无,这对正常调试协议栈任务至关重要。 | ||
![](http:// | ![](http:// | ||
+ | |||
+ | 图4 .设置优化等级 | ||
`FlashROM` 编译选项的协议栈任务入口地址在 `iar_boundary.xcl` 中给出,对于 `FlashROM_StackLibrary` 编译选项,可以通过编译生成的 *.map 文件查找`startup_entry` 符号从而找到入口地址。 | `FlashROM` 编译选项的协议栈任务入口地址在 `iar_boundary.xcl` 中给出,对于 `FlashROM_StackLibrary` 编译选项,可以通过编译生成的 *.map 文件查找`startup_entry` 符号从而找到入口地址。 | ||
行 352: | 行 360: | ||
![](http:// | ![](http:// | ||
![](http:// | ![](http:// | ||
+ | |||
+ | 图5 .找到入口地址 | ||
拿到协议栈任务的入口地址后,就可以在汇编窗口 View -> Disassembly 直接输入该地址,然后加上断点,等待协议栈任务创建后运行,从而跳转到协议栈工程进行调试。 | 拿到协议栈任务的入口地址后,就可以在汇编窗口 View -> Disassembly 直接输入该地址,然后加上断点,等待协议栈任务创建后运行,从而跳转到协议栈工程进行调试。 | ||
![](http:// | ![](http:// | ||
+ | |||
+ | 图6 .如何用协议栈工程进行调试 | ||
如果不知道协议栈任务的入口地址,则直接通过创建协议栈任务的任务实体入口,跳转到 `ICall_taskEntry` -> `entryfn` ,然后按** F11 **进入协议栈任务调试。 | 如果不知道协议栈任务的入口地址,则直接通过创建协议栈任务的任务实体入口,跳转到 `ICall_taskEntry` -> `entryfn` ,然后按** F11 **进入协议栈任务调试。 | ||
![](http:// | ![](http:// | ||
+ | |||
+ | 图7 .如何进入协议栈任务调试 | ||
> | > | ||
行 370: | 行 384: | ||
### 应用程序初始化功能 ### | ### 应用程序初始化功能 ### | ||
- | <a href=" | + | <a href=" |
simple_peripheral 任务函数伪代码 | simple_peripheral 任务函数伪代码 | ||
行 467: | 行 481: | ||
当为一个事件选择一个事件值的时候,该值对于给定的任务必须是唯一的,并且必须是 2 的幂(只有 1 bit 被设置为 1 )。这样做的原因是 `pEvt-> | 当为一个事件选择一个事件值的时候,该值对于给定的任务必须是唯一的,并且必须是 2 的幂(只有 1 bit 被设置为 1 )。这样做的原因是 `pEvt-> | ||
- | 清单49. BLE OSAL事件在 bcomdef.h 中定义。 | + | 清单1. BLE OSAL事件在 bcomdef.h 中定义。 |
```C | ```C |