欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DA1458x BASS 初始化 -- Battery Service 分析(三)

程序员文章站 2024-03-15 15:07:59
...

Overview

BASS 分为两部分。一部分为Profile,另一部分为Application。
同样初始化也是分为两部分,一部分是BASS Profile初始化,另一部分是 BASS Application初始化。

BASS APP 初始化

在BASS Application不是单独的一个任务,它是APP_TASK这个任务中的一个APP。
类似的还有app_diss、app_findme、app_proxr、app_sec、app_custs等。可见\sdk\app_modules\src目录
DA1458x BASS 初始化 -- Battery Service 分析(三)

这些APP是系统自带的,可以通过宏控开启或者关闭。
从初始化的过程就可以看出来,当系统初始化时,将会调用void default_app_on_init(void)函数。

void default_app_on_init(void)
{
#if BLE_PROX_REPORTER
    app_proxr_init();
#endif

#if BLE_FINDME_LOCATOR
    app_findl_init();
#endif

#if BLE_BAS_SERVER
    app_batt_init();
#endif

#if BLE_DIS_SERVER
    app_dis_init();
#endif

#if BLE_SPOTA_RECEIVER
    app_spotar_init();
#endif

    // Initialize service access write permissions for all the included profiles
    prf_init_srv_perm();

    // Set sleep mode
    arch_set_sleep_mode(app_default_sleep_mode);
}

从中我们不难看出app_batt_init();就是在这时被调用的。

app_batt_init()

app_batt_init()函数主要是调用battery_get_lv();函数,得到开机时的电池电量。并没有什么实质上完成 battery service的初始化。

void app_batt_init(void)
{
    // called from app.c::app_init() when chip boots
#ifdef USED_BATTERY_TYPE
    cur_batt_level = battery_get_lvl(USED_BATTERY_TYPE);
#else
    cur_batt_level = battery_get_lvl(BATT_CR2032);
#endif
}

app_bass_create_db()

真正的初始化(DataBase初始化)是由app_bass_create_db()函数完成。
我们来看一下TASK_APP中关于DataBase初始化的过程。
DA1458x BASS 初始化 -- Battery Service 分析(三)

从图中我们可以看到user_prf_funcs[k++].db_create_func(); 这个函数就是callback app_bass_create_db()的家伙。
调用app_bass_create_db()函数之后,它就结束退出了。
而根源上这都是gapm_cmp_evt_handler函数的一个case。
gapm_cmp_evt_handler这个函数是一个比较底层的处理函数,我们不会去改动它。
当执行GAPM_SET_DEV_CONFIG这个case时就会去Create 各种DB。当然他只是开了一个头,很快就结束了。
后续通过内核消息,在TASK_APP中各个APP互相调用,最终会完成所有的DB的初始化。

注册app_bass_create_db()函数

我们来看下如何注册app_bass_create_db()函数的。同时一同注册还有一个很重要的函数app_bass_enable(),这个函数下面也会讲。
这两个函数是一起被注册到TASK_APP。具体见下面的结构体数组。
该结构体数组被定义在app.c文件中。

const struct prf_func_callbacks prf_funcs[] =
{
    #if BLE_PROX_REPORTER
    {TASK_PROXR,     app_proxr_create_db, app_proxr_enable},
    #endif

    #if BLE_BAS_SERVER
    {TASK_BASS,      app_bass_create_db, app_bass_enable},
    #endif

    #if BLE_FINDME_TARGET
    {TASK_FINDT,     NULL, app_findt_enable},
    #endif

    #if BLE_FINDME_LOCATOR
    {TASK_FINDL,     NULL, app_findl_enable},
    #endif

    #if BLE_DIS_SERVER
    {TASK_DISS,      app_diss_create_db, app_diss_enable},
    #endif

    #if BLE_SPOTA_RECEIVER
    {TASK_SPOTAR,    app_spotar_create_db, app_spotar_enable},
    #endif

    {TASK_NONE,    NULL, NULL},   // DO NOT MOVE. Must always be last
};

prf_funcs这个数组被谁调用呢?下面的函数揭晓答案:

/**
 ****************************************************************************************
 * @brief Initialize the database for all the included profiles.
 * @return true if succeeded, else false
 ****************************************************************************************
 */
static bool app_db_init_next(void)
{
    static uint8_t i __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY;
    static uint8_t k __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY;

    // initialise the databases for all the included profiles
    while( user_prf_funcs[k].task_id != TASK_NONE )
    {
        if ( user_prf_funcs[k].db_create_func != NULL )
        {
            user_prf_funcs[k++].db_create_func();
            return false;
        }
        else k++;
    }

    // initialise the databases for all the included profiles
    while( prf_funcs[i].task_id != TASK_NONE )
    {
        if (( prf_funcs[i].db_create_func != NULL )
            && (!app_task_in_user_app(prf_funcs[i].task_id)))    //case that the this task has an entry in the user_prf as well
        {
            prf_funcs[i++].db_create_func();
            return false;
        }
        else i++;
    }


    #if BLE_CUSTOM_SERVER
    {
        static uint8_t j __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY;
        while( cust_prf_funcs[j].task_id != TASK_NONE )
        {
            if( cust_prf_funcs[j].db_create_func != NULL )
            {
                cust_prf_funcs[j++].db_create_func();
                return false;
            }
            else j++;
        }
        j = 0;
    }
    #endif

    k = 0;

    i = 0;
    return true;
}

是不是俄儿妹贼应,像prf_funcs这么吊的还有两个。

user_prf_funcs、prf_funcs、cust_prf_funcs这三个从名字就可以很清晰的看出是依照书序一次调用和初始化的。

prf_funcs初始化的是DISS、BASS、FINDME、PORX、SPOTA这几个。CUST自然是由cust_prf_funcs来搞,其余的就是USER。

prf_funcs调用完就退出了,那是怎么循环完毕的呢?这就是我们下面研究的问题。各位看官请看下节。

APP DataBase初始化流程

上个小节中,我们看到app_db_init_next函数调用了一个callback就退出了,例如prf_funcs,那么他是怎么把所有APP Database全部初始化完的呢?
我们可以先看下app_db_init_next函数定义的两个奇怪的i和k

    static uint8_t i __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY;
    static uint8_t k __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY;

这两个变量不仅是静态的局部变量还是存放在retention_mem_area0端的。启动时会被初始化为0。

所以,函数中的循环遍历不是一次完成的而是这个函数被反复调用后完成的。

我们先看下图,这是我总结的以app_bass为例的database初始化流程图。

DA1458x BASS 初始化 -- Battery Service 分析(三)