全球最低功耗蓝牙单芯片DA14580的软件体系 -RW内核和消息处理机制

上一篇文章《蓝牙单芯片DA14580的硬件架构和低功耗》阐述了DA14580的硬件架构和低功耗的工做原理。本文文章阐述该平台的软件体系,并着重分析消息事件的处理机制。编程

 

1、DA14580SOC硬件组成和软件体系组成数组

        DA14580芯片硬件架构包括三个部分:数据结构

        1)使用ARM公司的cortex M0做为CPUprocessor处理器。架构

        2)使用RivieraWaves公司的IP核做为BLEcore和基带、射频部分。函数

        3)集成时钟管理CMU、电源管理PMU、memory控制存储和其余外围模块控制器,如GPIO、UART、I2C、SPI和timer等等。ui

        相应地,DA14580平台SDK的软件组成也包括如下组成部分:blog

        1)ARMcortex M0平台相关的库文件,如启动、CMSIS(the cortex Microcontroller software interface standard)支持的寄存器访问、中断异常访问接口等。接口

        2)RW公司的BLE驱动、射频驱动,此外RW BLE还集成了系统的内核部分,其提供消息处理、定时器和任务调度等核心功能。因此DA14580平台SDK的开发是基于RW公司研发的内核,而不是DIALOG公司研发的。此部分大部分的代码都是固化在ROM里面。队列

        3)SOC集成的其余模块的驱动,由DIALOG公司提供,如UART驱动等,此外其调用RW内核的相关接口来完成消息循环和低功耗功能。事件

        4)应用程序,调用以上三个部分的接口来完成自定义功能。

    咱们重点分析2)中的RW内核机制和功能。

 

2、RW内核

        RW内核的指导文档为《RW-BT-KERNEL-SW-FS.pdf》。其主要包括如下三个部分:

        1)Message,消息处理机制。

        2)Taskand Schedule,任务和调度。

        3)Timer,定时器使用方法。

 

3、Task

RW在BLE协议栈层次的基础上抽象了多个任务task,每一个task完成一个软件层次的功能。因此说RW内核是支持多个任务task的,但本质上,RW内核也是一个单任务内核,因此各个task能够当作是可以完成特定功能的独立函数体或者函数集合。

每一个task都有一个task ID,其具备优先级功能,相似于UCOS的优先级。

RW内核和UCOS的区别是:UCOS是多任务内核,具备时间片轮流执行,并具备互斥同步。

 

4、Message

4.1 消息标识

一个消息就要区分它是属于哪一个task的,并且还要区分同一个task里面的不一样消息。因此一个Message包括两个部分:

TASK_TYPE便是task的ID。在调度时,优先级高的task的消息会先获得执行处理。

4.2  消息结构体元素

咱们只须要关注红色圈着的这五个元素,第一个元素能够看出消息结构体节点是以链表的形式来管理的。HCI相关的是指USB dongle这种应用形式,由PC主机控制蓝牙BLE,我们不讨论这种应用。

红色圈到的五个元素分别的是:

1)id,即第一点说到的消息标识。

2)消息由哪一个目标task处理。

3)发出消息的task

4)消息参数的长度

5)消息参数的结构体地址

消息参数结构体是能够自定义的,这里经过void*转换传入地址。

 

4.3  消息动态内存管理

       RW内核专门给消息处理提供动态内存管理机制,接口是:

       void*ke_msg_alloc(ke_msg_id_t const id, ke_task_id_t const dest_id,

                   ke_task_id_t const src_id,uint16_t const param_len);

       通常给应用提供一个宏,用于简化写法:

                     #defineKE_MSG_ALLOC(id, dest, src, param_str) \

   (struct param_str*) ke_msg_alloc(id, dest, src, sizeof(structparam_str))

       释放接口是:void ke_msg_free(struct ke_msg const *param);. 在调度机制里面会经过判断消息处理的返回值对消息进行相应的处理,如释放消息的内存。用户编程通常不用调用释放接口。

 

4.4    消息接口

       1)带参数的消息发送

       voidke_msg_send(void const *param_ptr); param_ptr须要经过ke_msg_alloc接口申请动态内存。

       通常的命令消息发送写法以下:

structgapm_set_dev_config_cmd* cmd = KE_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD,

                        TASK_GAPM, TASK_APP,gapm_set_dev_config_cmd);

   ke_msg_send(cmd);

       2)不带参数的消息发送

       voidke_msg_send_basic(ke_msg_id_t const id, ke_task_id_t const dest_id,ke_task_id_t const src_id)

 

5、TIMER

5.1 定时单位

10ms,RW内核提供一个定时器,其并非DA14580集成的TIMER1和TIMER3。对定时器的初始化等工做是在BLE初始化内部的,不须要用户编程设置。用户只须要调用RW内核的TIMER接口便可。

5.2    设置timer

voidke_timer_set(ke_msg_id_t const timer_id, ke_task_id_t const task, uint16_tconst delay);

timer_id是定时器消息,其属于一种不带参数的MESSAGE,delay是定时时间,10ms为单位,当时间到达时,RW内核会发送timer_id到目标task的消息队列。当内核schedule时即会执行定时器相应的回调。

 

6、Schedule

1.先取出最高优先级task的消息事件,该消息从消息队列中pop出来

2.根据task的状态和消息ID来获得对应的handler

3.执行该handler回调

4.根据回调的返回值对消息进行处理

    1)若是返回KE_MSG_CONSUMED,则内核free掉该消息。

    2)若是返回KE_MSG_NO_FREE,则内核不处理该消息,但该消息也不会从新放到消息队列,即内核不能再从消息队列中得到该消息。

    3)若是返回KE_MSG_SAVED,则内核不free该消息,而且将该消息从新入列。

7、基于状态机的RW内核消息处理机制

    Task数据结构以下:

 

 

RW内核是基于状态机对消息进行处理的。从ke_task_desc看来,一个task包括显式的状态处理state_handler和默认的状态处理default_handler。

state是task的状态机变量,task可能有多个状态,那么state_handler是状态处理集合,每一个状态可能会处理多个消息回调,例如上层task会发送消息来执行调用,或者下层task发送消息来执行回调。

default_handler处理的消息表明该task在任意状态时均可能受到的消息,例如底层task发出的断开链接消息。

咱们也能够得出,ke_state_handler表明一个状态下的多个消息处理。所以,state_handler是一个ke_state_handler数组,而default_handler则是ke_state_handler元素。

 

8、参考文献:

《UM-B-015_DA14580 Software architecture v4.0.pdf》、

《RW-BT-KERNEL-SW-FS.pdf》。