CC2650 BLE4.2 应用程序框架

blog.csdn.net

CC2650 BLE4.2 应用程序框架

本文档摘自leconiot的博客。


从这个章节开始,我们将详细讲解CC2640R2F BLE5.0的应用程序框架,在之前我们希望已经按照我们学习线路图储备了CC2640R2F平台的软硬件架构知识。明白应用工程区分App和Stack工程管理。这里我们主要是讲解基于TI-RTOS的App应用程序框架。


这里介绍以 simple_peripheral Demo应用程序部分,包括以下内容:

  • Pre-main initialization
  • ICall
  • Simple Peripheral Task
  • Intertask Messages

注意: GAPRoleTask也是工程的一部分,但是我们将它放在协议栈部分进行讨论,其功能与协议栈密切相关。

Pre-main initialization

main函数包含在IDE Startup 文件夹的资源文件main.c中。作为程序的入口,其主要完成 全局中断禁止、外设驱动初始化、电源管理,TI-RTOS任务创建或构造,启用SYS / BIOS内核调度时完成全局中断使能。main函数不返回,将在整个项目生命周期内保留其资源;

基本main.c功能。

int main()
{
  /* Register Application callback to trap asserts raised in the Stack */
  RegisterAssertCback(AssertHandler);

  PIN_init(BoardGpioInitTable);

  #ifndef POWER_SAVING
    /* Set constraints for Standby, powerdown and idle mode */
    Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
  #endif // POWER_SAVING

  /* Initialize ICall module */
  ICall_init();

  /* Start tasks of external images - Priority 5 */
  ICall_createRemoteTasks();

  /* Kick off profile - Priority 3 */
  GAPRole_createTask();

  SimpleBLEPeripheral_createTask();

  /* enable interrupts and start SYS/BIOS */
  BIOS_start();

  return 0;
}

注意:以上代码ICALL消息模块必须由ICALL_init()完成初始化,并且通过ICall_createRemoteTasks()完成协议栈任务创建 。

ICALL

介绍

软件架构章节我们讲解了由于历史兼容原因将整个应用工程区分App和Stack两个工程管理,正是基于这样的两个工程设计,App和Stack之间的通信就需要重新考虑了,因为我们没有办法像常规API调用和全局变量方式完成消息传递。TI引入了ICALL消息机制完成App和Stack独立工程管理的彼此通信。以下我们着重理解原理和代码实现,因其占了我们程序很大部分。

Indirect Call Framework (ICall 消息框架)基于TI-RTOS提供服务(例如,同步线程、消息、事件)完成BLE协议栈和应用程序在两个工程的消息交互,保证了应用程序和协议栈在统一的TI-RTOS环境中完成高效运行、相互通信和资源共享。

ICall架构和的核心组件是其消息调度(dispatcher),其帮助程序在两个镜像/工程中完成BLE5-Stack协议栈以及库配置中的应用程序交互。尽管大多数ICall交互在BLE5-Stack API(例如GAP,HCI等)中已经被抽象化(已经被封装为消息原语函数),但是我们必须理解其在BLE-Stack和多线程RTOS环境中正常运行的基础架构。

ICALL源码在应用工程(例如我们这里的simple_peripheral)的 ICALL BLE/ICALL 文件夹路径。

图32. ICall 应用-协议栈 抽象

ICall BLE5协议栈服务端

如上图所示,ICALL实现包含一个客户端实体(例如,我们的应用程序)和一个服务器实体(即这里的BLE5.0协议栈)之间的通信。

注意 :正确区分ICALL框架的CS架构和GATT服务器和客户端的结构,后者主要由BLE协议栈所定义实现。

TI之所以这样设计,前面我们已经讲到:

  • 实现应用程序和BLE协议栈的独立管理和固件更新;
  • 从传统平台(即CC254x的OSAL)移植到CC2640R2F的TI-RTOS,保持API一致性;

ICall 作为 BLE5协议栈API的服务接口。当我们需要调用一些协议栈接口的时候,ICall模块会自动将命令分发(即调度)到BLE5协议栈,并将消息从BLE5协议栈结果回传到应用程序。

因为ICall消息模块本身就作为是应用程序工程的一部分,应用任务可以通过函数调用方式直接访问ICall。由于BLE协议栈任务总是以最高优先级执行,但是应用程序在没有数据返回时缺处于阻塞状态,必然有些API在会在协议栈任务立即响应,应用任务只有在消息通过ICALL分发时才能唤醒处理。另外一些API却只有等待应用任务通过ICAlL(事件更新)异步返回结果。

ICALL原语服务

ICALl包含一系列的原语服务都被抽象成基于RTOS相关的函数接口。由于共享资源和线程之间的通信,应用程序必须使用以下ICALL原语服务功能:

  • 消息传递和线程同步
  • 堆分配与管理

消息传递和线程同步

ICall同协议栈的消息传递和线程同步都是是基于TI-RTOS多线程。

ICall两个任务的消息传递发生在通过消息队列发送一个阻塞消息。发送方动态分分配一段内存,将消息的内容写入内存,然后将这段内存发送(即排队)到接收线程,然后再使用事件标志。接受任务在收到事件标志后唤醒,复制内存消息,并且处理,之后再并将这段内存块释放。

协议栈使用ICall通知和发送消息到应用程序。ICall传递这些服务消息,应用程序任务接收它然后处理。

堆分配与管理

ICall为应用提供了全局堆管理的API用以动态内存分配。其堆的大小通过宏HEAPMGR_SIZE 配置。有关管理动态内存的更多详细信息,请参阅动态内存分配。BLE 协议栈的ICall使用此堆管理进行所有消息相关的内存管理,同样我们建议应用程序也使用这些ICall API来分配动态内存。

ICALL初始化和注册

要实例化和初始化ICall服务,应用程序必须在启动TI-RTOS内核调度程序之前调用main()中的代码片段中的函数:

使用ICall的必需代码。

/* 初始化ICall模块 */ 
ICall _init ();

/* 启动协议栈任务 - 优先级 */ 
ICall _createRemoteTasks ();

调用ICall_init()初始化ICALL原语服务(例如,堆管理)和框架,调用 ICall _createRemoteTasks()创建但不启动BLE5-Stack任务。在使用ICall协议服务之前,服务器和客户端分别完成登记和注册。服务端在编译的时候就需要登记一个服务。登记函数使用一个全局的唯一标识符区分每个服务,也是作为后面通信地址。例如,BLE协议使用 ICALL_SERVICE_CLASS_BLE做些蓝牙协议栈ICALL的消息交互的标识。

对于服务端的登记,包含在osal_icall_ble.c文件

/ *ICALL服务端登记* / 
ICall _enrollService (ICALL _SERVICE_CLASS_BLE ,NULL ,&entity ,&syncHandle );   

客户端在ICALL调度程序发送和/或接收消息之前需要注册。

对于使用BLE5API的客户端(例如应用程序任务),客户端必须首先向ICall注册其任务 。该注册通常发生在应用程序的任务初始化功能中。下面的代码片段是 simple_peripheral_init simple_peripheral.c中注册。

//ICALL客户端注册
ICall _registerApp (&selfEntity ,&syncEvent ); 

ICall_enrollService(ICALL_SERVICE_CLASS_BLE, NULL, &entity, &sem);中主要的实现函

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值