• TI BLE协议栈软件框架分析


    看源代码的时候,一般都是从整个代码的入口处開始,TI  BLE 协议栈源代码也不例外。它的入口main()函数就是整个程序的入口,由系统上电时自己主动调用。

    它主要做了以下几件事情:

    (一)底层硬件初始化配置

    (二)创建任务并初始化任务配置

    (三)检測并运行有效的任务事件

    Main() 函数源代码例如以下:


    一:底层硬件初始化设置

    75行。设置系统时钟。使能内存缓冲功能。

    78行。关中断,刚启动时。系统运行不稳定,通常会首先关中断。

    81行。硬件相关的I/O 口配置。

    84行。初始化mcu 内部的flash。

    92行,开中断,当系统运行到这里的时候。状态已经非常稳定,能够将中断打开。

    95行,I/O功能配置,及设置按键回调函数指针。

    98行。配置省电模式。

    二:创建任务并初始化任务配置

    89行,最基本的功能就是给创建全部的任务。

    三:检測并运行有效的任务事件

    102行,此函数是整个程序运行的核心。一旦进入,就循环运行全部的任务,永远不会结束。

    以下分别列出这3个部分的主要源代码,并以按键KEY的配置为线索进行分析:

    ===================================================================

    一:底层硬件初始化设置


    a.        HalDriverInit() 主要是硬件抽象层初始化。配置PIN脚的工作模式。

    比方ADC,UART,KEY。LCD等。

    147行。HalKeyInit()是按键I/O配置,以下以此举例说明:



    211-223行,将对应的PIN配置为GPIO,输入模式。

    226行。初始化按键回调函数指针pHalKeyProcessFunction为NULL。

    此回调函数在程序中的作用是,当driver层检測到按键中断后,仅仅须要调用回调函数指针就可以,至于函数运行什么功能则全然由用户层自己决定,这种做的优点是将用户层与driver层分离。提高代码的模块化及可操作特性。

    b.        InitBoard( OB_READY ),配置KEY  GPIO的中断功能


    126行。HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback)此函数中配置中断使能,设置按键回调函数指针pHalKeyProcessFunction为OnBoard_KeyCallback。

    OnBoard_KeyCallback()里面会继续调用函数OnBoard_SendKeys(),其功能是发送按键message给对应的任务。

    硬件配置好后。仅仅能说明硬件具备完毕对应功能的条件,可是怎样让它的功能实现。那就须要创建对应的应用程序来让硬件工作起来,这个程序就叫task。task是怎样创建的呢?

    以下接着分析,怎样创建task。

    二:创建任务并初始化任务配置

    前面讲过主函数main()89行osal_init_system(),主要功能是初始化系统设置,当中最重要的一个功能就是创建task,以下是创建task的源代码

     

    122行,申请tasksEvents内存空间

    123行。清零tasksEvents内存空间

    126行,链路层task初始化

    129行,硬件抽象层task初始化

    132行,主机控制接口层task初始化

    141行,逻辑链路控制及自适应协议层task初始化

    144-156行,通用属性配置文件层task初始化

    150行。安全管理层task初始化

    159行,客户应用层task初始化

    每一个task 初始化时都会分配一个taskID,并且是从0 递增。

    以Hal_Init(taskID++ )为例,从上面代码能够看出来。硬件抽象层的taskID值是1

     

    92行。将task_id形參赋值给Hal_TaskID,故初始化后Hal_TaskID等于1

    因为Hal_TaskID是定义为一个全局变量。因此。整个程序中,仅仅要是与Hal_TaskID有关系的事情,都会交给Hal 层的task处理。

    相同的道理。SimpleBLECentral_Init(taskID++)中会定义一个simpleBLETaskId,那么全部与simpleBLETaskId有关系的事情,也都会交给应用层任务函数处理。

    那各层的任务函数是在哪里定义的呢?

    在OSAL_simpleBLECentral.c文件里,定义了一个函数指针数组例如以下:


    87行,Hal_ProcessEvent即为Hal层的任务处理函数指针,它是数组的第2个元素tasksArr[1]。也就是说假设程序中要调用Hal层任务,直接写语句“tasksArr[1]();”

    函数Hal_ProcessEvent()就会被运行了。

    Task尽管被创建好了。可是task是要运行我们给它规定的功能的,那它是在哪里运行的呢?

    接下来具体分析task 的运行的问题。

     

    三:检測并运行有效的任务事件

     

    系统中task 的运行。是由事件(evnet)来驱动的,程序会循环检測全部的task。假设发现某个task有新的event未被处理。那么这个task就会被调用。

    osal_start_system()是整个程序的核心。里面是一个for死循环,不停调用函数osal_run_system(),它的实际功能就是不停检測是否有event产生。假设有event。就运行对应的task。请看源代码:


    1105行,定时器查询函数,它会检查全部的定时器。假设某个定时时间到达。就将对应的event 加入到tasksEvents[task_id]。这里task_id的值是加入定时器时设置好的,具体请看osal_set_event()函数代码。

    1110-1115行,检查全部任务。是否有须要运行的event发生,并记录这个event的索引idx。

    1117行。taskCnt 是系统加入的任务个数,也就是tasksArr[]数组中元素的个数。

    1123行。保存当前任务的将要运行的全部event。

    1124行,清除当前任务的全部event。

    1127行,保存当前任务的idx,供系统自己使用。

    1128行,依据当前任务索引idx。在指针数组tasksArr[]中寻址当前任务的函数指针。调用当前任务函数,处理当中一个event。处理完毕后,返回还未处理的event。

    1132行,将未处理的event恢复给当前任务事件变量保存。等待下一次再处理。直至处理问全部的event。

     

     

     

    总结:

     

    本节仅仅是解说了协议栈的主体框架,协议栈仅仅是一个基础平台,在不同的方案中,就有不同的应用功能,对应的就必须为应用加入不同的task来实现实际的功能。

    通过本节解说,加入一个task的基本过程例如以下:

    1.        在HAL层配置任务要用到的I/O 的属性(假设不涉及I/O操作,则可省略此步骤)

    2.        在数组tasksArr[]中加入任务(task)处理函数

    3.        在函数osalInitTasks()中初始化任务task

    依据上面的步骤我们能够非常easy创建一个task。

    可是,假设程序中没有产生task的事件(event),task永远都不会运行。

    这就有一个新的问题:event在什么情况下产生?它又是怎样产生?

    我们将在【事件和消息工作机制】一节中具体分解。

  • 相关阅读:
    Deployment of VC2008 apps without installing anything
    用MT.exe将exe中的manifest文件提取出来和将manifest文件放入exe中
    Golang快速入门
    8个优质的编程学习网站
    免费学编程!10个全球顶尖的编程在线自学网站
    7个在线学习C++编程的最佳途径
    为什么多数游戏服务端是用 C++ 来写
    学习游戏服务器开发必看,C++游戏服务器开发常用工具介绍
    Ambari——大数据平台的搭建利器(一)
    Python爬虫项目整理
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10939767.html
Copyright © 2020-2023  润新知