cruelfox 发表于 2021-6-8 23:00

关于RSL10 SDK中Event Kernel部分的代码分析(上)

<p>  本人在一个多月以前就开始分析官方给的工程范例了,然而对其中的函数回调用法没有看懂,自己的项目实验也就因此卡住了,拖到了现在。估计有许多网友也遇到了同样的问题,所以在此把这段时间的学习分析心得总结出来,希望对大家开发RSL10程序有帮助。</p>

<p>&nbsp;</p>

<p>  RSL10 的 BLE 程序要依赖于&nbsp;Event Kernel, 这个 Kernel 是个啥?<br />
  随便找 BLE 应用的若干例子,在其 app.c 中可以见到,主函数到了最后是一个循环,里面都含有这三个调用:<br />
<strong>&nbsp; &nbsp; &nbsp; &nbsp; Kernel_Schedule();<br />
&nbsp; &nbsp; &nbsp; &nbsp; Sys_Watchdog_Refresh();<br />
&nbsp; &nbsp; &nbsp; &nbsp; SYS_WAIT_FOR_EVENT;</strong><br />
第二个是刷新WDT, 第三个是使用 ARM 的 WFE 指令进入低功耗模式,等待硬件唤醒,然后再次执行 <strong>Kernel_Schedule()</strong>. 明显,这是一个 RTOS 吗?这个和FreeRTOS的调度器不一样。关键的是,代码其它地方也看不到多任务系统的特征&mdash;&mdash;每个任务独立的堆栈。所以,大胆猜测:这个调度器,是根据事件去调用若干函数而已。<br />
&nbsp;</p>

<p>  在 ble_peripheral_server_hrp 这个例子里面,在 main() 开始就调用的 <strong>Device_Initialize()</strong> 函数中,执行了一条</p>

<pre>
<code class="language-cpp">    ke_task_create(TASK_APP, &amp;TASK_DESC_APP);</code></pre>

<p>乍一看,像是一个 RTOS 创建了一个任务呢,可是这个调用的参数又很诡异,不像。在 ON 的文档《RSL10 Firmware Reference》中,竟然没有对这个函数的说明。纵观整个代码,除了创建这个 TASK_APP 也没有创建别的&ldquo;任务&rdquo;了。这当然不对,如果是支持多任务的话,多个任务(线程)函数总要有吧。<br />
  因为 <strong>ke_task_create()</strong> 没有提供源代码,从头文件给出的定义来看:</p>

<pre>
<code class="language-cpp">/****************************************************************************************
* @brief Create a task.
*
* @paramtask_type       Task type.
* @paramp_task_desc   Pointer to task descriptor.
*
* @return Status
***************************************************************************************/
uint8_t ke_task_create(uint8_t task_type, struct ke_task_desc const * p_task_desc);
</code></pre>

<p>第一个参数是 8-bit 的 task 类型, 第二个参数指向一个 task descriptor (ke_task_desc结构体). 那么就看看这个结构体的定义:</p>

<pre>
<code class="language-cpp">/// Task descriptor grouping all information required by the kernel for the scheduling.
struct ke_task_desc
{
    /// Pointer to the state handler table (one element for each state).
    const struct ke_state_handler* state_handler;
    /// Pointer to the default state handler (element parsed after the current state).
    const struct ke_state_handler* default_handler;
    /// Pointer to the state table (one element for each instance).
    ke_state_t* state;
    /// Maximum number of states in the task.
    uint16_t state_max;
    /// Maximum index of supported instances of the task.
    uint16_t idx_max;
};</code></pre>

<p>  推测,一个 task 可以有多种状态,每个状态可以有不同的 handler 函数(用途是处理消息)。一个 task 类型可以有多个实例。</p>

<p>&nbsp;</p>

<p>  在 ble_peripheral_server_hrp 中,<strong>ke_task_create()</strong> 使用的 TASK_DESC_APP 这个结构常量定义为:</p>

<pre>
<code class="language-cpp">static const struct ke_task_desc TASK_DESC_APP = {
    .state_handler = NULL,
    .default_handler = &amp;appm_default_handler,
    .state = appm_state,
    .state_max = 0,
    .idx_max = APP_IDX_MAX
};</code></pre>

<p>其中 state_handler 是空指针,不起作用。默认的 handler 是 appm_default_handler, 这是 ke_state_handler 结构类型:</p>

<pre>
<code class="language-cpp">struct ke_state_handler
{
    /// Pointer to the message handler table of this state.
    const struct ke_msg_handler *msg_table;
    /// Number of messages handled in this state.
    uint16_t msg_cnt;
};</code></pre>

<p>其中包含一个指针和一个16-bit数,指针是指向 ke_msg_handler 结构类型。</p>

<pre>
<code class="language-cpp">struct ke_msg_handler
{
    /// Id of the handled message.
    ke_msg_id_t id;
    /// Pointer to the handler function for the msgid above.
    ke_msg_func_t func;
};</code></pre>

<p>&nbsp;</p>

<p>  在这个例子中,appm_default_handler 定义是:</p>

<pre>
<code class="language-cpp">static const struct ke_state_handler appm_default_handler
    = KE_STATE_HANDLER(appm_default_state);

static const struct ke_msg_handler appm_default_state[] =
{
    { KE_MSG_DEFAULT_HANDLER, (ke_msg_func_t)MsgHandler_Notify }
};</code></pre>

<p>KE_STATE_HANDLER 这个宏定义是&nbsp;</p>

<pre>
<code class="language-cpp">#define KE_STATE_HANDLER(hdl) {hdl, sizeof(hdl)/sizeof(struct ke_msg_handler)}</code></pre>

<p>&nbsp;</p>

<p>  代码看着不明显,我总结成个图:</p>

<p>  ble_peripheral_server_hrp 中 appm_default_state 这个表很简单,只有一项,handler 函数是 MsgHandler_Notify(), 这个函数是 SDK 中提供的,有源代码。但并不是说只用一个 handler 函数就足够。另外看一个例子:peripheral_server 中,appm_default_state[]&nbsp;表有5项:</p>

<pre>
<code class="language-cpp">const struct ke_msg_handler appm_default_state[] =
{
    /* Note: Put the default handler on top as this is used for handling any
   *       messages without a defined handler */
    { KE_MSG_DEFAULT_HANDLER, (ke_msg_func_t)Msg_Handler },
    BLE_MESSAGE_HANDLER_LIST,
    BASS_MESSAGE_HANDLER_LIST,
    CS_MESSAGE_HANDLER_LIST,
    APP_MESSAGE_HANDLER_LIST
};</code></pre>

<p>  这么看来,表的用法还不清楚,每个 handler 函数各自的作用也不清楚。</p>

<p>&nbsp;</p>

<p>  我用 GDB 调试了 ble_peripheral_server_hrp 的执行,在 <strong>ke_task_create()</strong> 函数入口设置断点,发现在 <strong>BLE_InitNoTL()</strong> 中调用了很多次 <strong>ke_task_create()</strong>. 其中 task type 为 0x0A 到 0x31 的调用,第二个参数指向的地址位于 SRAM 中 prf_env 全局变量内,值为全0。其它的调用,第二个参数指向的是 flash 的地址,是程序中的只读常量,有:</p>

<p>TASK_DESC_GAPM<br />
TASK_DESC_GAPC<br />
TASK_DESC_GATTM<br />
TASK_DESC_GATTC<br />
TASK_DESC_L2CC<br />
TASK_DESC_LLD<br />
TASK_DESC_LLC<br />
TASK_DESC_LLM<br />
  这些常量来自于二进制库,可以在 GDB 下查看,如,查看 TASK_DESC_GAPC 这个任务描述结构</p>

<p><span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) print *(struct ke_task_desc *)TASK_DESC_GAPC<br />
$2 = {state_handler = 0x0, default_handler = 0x124afc &lt;gapc_default_handler&gt;,<br />
&nbsp; state = 0x200020b0 &lt;gapc_state&gt; &quot;????????&quot;, state_max = 64, idx_max = 8}</span></span></p>

<p><span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) print *(struct ke_state_handler *)gapc_default_handler<br />
$4 = {msg_table = 0x124b04 &lt;gapc_default_state&gt;, msg_cnt = 38}</span></span></p>

<p><span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) print *(struct ke_msg_handler *)gapc_default_state<br />
$5 = {id = 65535, func = 0x118f73 &lt;gapc_default_msg_handler+1&gt;}</span></span></p>

<p>  gapc_default_state&nbsp;表有38项,第一项的 handler 是 gapc_default_msg_handler<br />
  要看最后一项,可以这样<br />
<span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) print ((struct ke_msg_handler *)gapc_default_state)<br />
$25 = {id = 3639,<br />
&nbsp; func = 0x119a0d &lt;gapc_set_max_rx_size_and_time_cmd_handler+1&gt;}</span></span></p>

<p>  直接地,还可以写成<br />
<span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) print ((struct ke_task_desc *)TASK_DESC_GAPC)-&gt;default_handler-&gt;msg_table</span></span></p>

<p>这样可以发现很多的 handler 函数了,它们又是怎样被使用的呢?<br />
&nbsp;</p>

<p>  现在来看下 handler 函数的类型定义:</p>

<pre>
<code class="language-cpp">/// Format of a task message handler function
typedef int (*ke_msg_func_t)(ke_msg_id_t const msgid, void const *param,
                           ke_task_id_t const dest_id, ke_task_id_t const src_id);</code></pre>

<p>  当一个 handler 被调用的时候,会传给它 4 个参数。这正好是一个消息要包含的内容。在手册里给出了描述:</p>

<p></p>

<p>  在 ke_msg.h 头文件中定义了</p>

<pre>
<code class="language-cpp">/// Message structure.
struct ke_msg
{
    struct co_list_hdr hdr;   ///&lt; List header for chaining

    ke_msg_id_t   id;         ///&lt; Message id.
    ke_task_id_t    dest_id;    ///&lt; Destination kernel identifier.
    ke_task_id_t    src_id;   ///&lt; Source kernel identifier.
    uint16_t      param_len;///&lt; Parameter embedded struct length.
    uint32_t      param;   ///&lt; Parameter embedded struct. Must be word-aligned.
};</code></pre>

<p>其中的 struct co_list_hdr 类型成员是用来构造链表的,暂且不管。后面有三个字段较为关键:消息的ID, 消息目标(task)的id, 和消息来源(task)的id. 剩下的是消息带的数据(payload)。</p>

<p>&nbsp;</p>

<p>  前面已经说过 task 类型,那么 task id 又是啥?</p>

<p>  根据定义</p>

<pre>
<code class="language-cpp">/// Task Identifier. Composed by the task type and the task index.
typedef uint16_t ke_task_id_t;

/// Builds the task identifier from the type and the index of that task.
#define KE_BUILD_ID(type, index) ( (ke_task_id_t)(((index) &lt;&lt; 8)|(type)) )</code></pre>

<p>知道了 task id 是一个16-bit数据,低8位是 task 类型,高8位是 &quot;task index&quot; &mdash;&mdash;如何用?我假设是实例的索引(一个task类型可以有多个实例)。</p>

<p>&nbsp;</p>

<p>  消息的 ID&nbsp;也是个16-bit数据, 在头文件中写了注释</p>

<pre>
<code class="language-cpp">/// Message Identifier. The number of messages is limited to 0xFFFF.
/// The message ID is divided in two parts:
/// bits: task index (no more than 255 tasks support)
/// bits: message index(no more than 255 messages per task)
typedef uint16_t ke_msg_id_t;</code></pre>

<p>  这样一来,消息 ID&nbsp;包含 task index 和 message index 两部分。但是不清楚了,此 task 又对应接收方还是发送方,还是可能有其它?</p>

<p>  注释的说明和手册有所不同:</p>

<p>  按照手册说的,一个 task 的第一个消息 ID, 高8位就是 task 类型。task type 和 task index 必然不是同一个东西,不然 task id 就不会包含两者了。晕了!</p>

<p>&nbsp;</p>

<p>  还是找代码来验证吧。</p>

<p>  使用了 TASK_FIRST_MSG 宏的地方,例如:</p>

<pre>
<code class="language-cpp">/// Messages for Battery Server
enum bass_msg_id
{
    /// Start the Battery Server - at connection used to restore bond data
    BASS_ENABLE_REQ = TASK_FIRST_MSG(TASK_ID_BASS),
    /// Confirmation of the Battery Server start
    BASS_ENABLE_RSP,
    /// Battery Level Value Update Request
    BASS_BATT_LEVEL_UPD_REQ,
    /// Inform APP if Battery Level value has been notified or not
    BASS_BATT_LEVEL_UPD_RSP,
    /// Inform APP that Battery Level Notification Configuration has been changed - use to update bond data
    BASS_BATT_LEVEL_NTF_CFG_IND,
};</code></pre>

<p>定义这些消息ID的高8位是 TASK_ID_BASS, 低8位则从0开始计数。<br />
  再查找 TASK_ID_BASS 的定义,在 rwip_task.h 当中:</p>

<pre>
<code class="language-cpp">/// Tasks types definition, this value shall be in range
enum TASK_API_ID
{
    // Link Layer Tasks
    TASK_ID_LLM          = 0,
    TASK_ID_LLC          = 1,
    TASK_ID_LLD          = 2,
    TASK_ID_DBG          = 3,

    // BT Controller Tasks
    TASK_ID_LM         = 4,
    TASK_ID_LC         = 5,
    TASK_ID_LB         = 6,
    TASK_ID_LD         = 7,

    TASK_ID_HCI          = 8,
    TASK_ID_DISPLAY      = 9,

    // -----------------------------------------------------------------------------------
    // --------------------- BLE HL TASK API Identifiers ---------------------------------
    // -----------------------------------------------------------------------------------

    TASK_ID_L2CC         = 10,   // L2CAP Controller Task
    TASK_ID_GATTM      = 11,   // Generic Attribute Profile Manager Task
    TASK_ID_GATTC      = 12,   // Generic Attribute Profile Controller Task
    TASK_ID_GAPM         = 13,   // Generic Access Profile Manager
    TASK_ID_GAPC         = 14,   // Generic Access Profile Controller

    TASK_ID_APP          = 15,   // Application API
    TASK_ID_AHI          = 16,   // Application Host Interface

    // -----------------------------------------------------------------------------------
    // --------------------- BLE Profile TASK API Identifiers ----------------------------
    // -----------------------------------------------------------------------------------
    TASK_ID_DISS         = 20,   // Device Information Service Server Task
    TASK_ID_DISC         = 21,   // Device Information Service Client Task

    TASK_ID_PROXM      = 22,   // Proximity Monitor Task
    TASK_ID_PROXR      = 23,   // Proximity Reporter Task

    TASK_ID_FINDL      = 24,   // Find Me Locator Task
    TASK_ID_FINDT      = 25,   // Find Me Target Task

    TASK_ID_HTPC         = 26,   // Health Thermometer Collector Task
    TASK_ID_HTPT         = 27,   // Health Thermometer Sensor Task

    TASK_ID_BLPS         = 28,   // Blood Pressure Sensor Task
    TASK_ID_BLPC         = 29,   // Blood Pressure Collector Task

    TASK_ID_HRPS         = 30,   // Heart Rate Sensor Task
    TASK_ID_HRPC         = 31,   // Heart Rate Collector Task

    TASK_ID_TIPS         = 32,   // Time Server Task
    TASK_ID_TIPC         = 33,   // Time Client Task

    TASK_ID_SCPPS      = 34,   // Scan Parameter Profile Server Task
    TASK_ID_SCPPC      = 35,   // Scan Parameter Profile Client Task

    TASK_ID_BASS         = 36,   // Battery Service Server Task
    TASK_ID_BASC         = 37,   // Battery Service Client Task
</code></pre>

<p>这里的代码才是 task id 的诠释。那么,task type 呢?</p>

<p>  在 rwip_config.h 中定义了</p>

<pre>
<code class="language-cpp">/// Tasks types definition
enum KE_TASK_TYPE
{
#if (BT_EMB_PRESENT)
    // BT Controller Tasks
    TASK_LM,
    TASK_LC,
    TASK_LB,
    TASK_LD,
    TASK_HCI,
#endif // (BT_EMB_PRESENT)

#if (BLE_EMB_PRESENT)
    // Link Layer Tasks
    TASK_LLM ,
    TASK_LLC ,
    TASK_LLD ,
#endif // (BLE_EMB_PRESENT)

#if ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT))
    TASK_DBG,
#endif // ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT))

#if (DISPLAY_SUPPORT)
    TASK_DISPLAY,
#endif // (DISPLAY_SUPPORT)

#if (BLE_APP_PRESENT)
    TASK_APP,
#endif // (BLE_APP_PRESENT)

#if (BLE_HOST_PRESENT)
    TASK_L2CC,    // L2CAP Controller Task
    TASK_GATTM,   // Generic Attribute Profile Manager Task
    TASK_GATTC,   // Generic Attribute Profile Controller Task
    TASK_GAPM,    // Generic Access Profile Manager
    TASK_GAPC,    // Generic Access Profile Controller

    // allocate a certain number of profiles task
    TASK_PRF_MAX = (TASK_GAPC + BLE_NB_PROFILES),

    #ifdef BLE_AUDIO_AM0_TASK
    TASK_AM0,   // BLE Audio Mode 0 Task
    #endif // BLE_AUDIO_AM0_TASK
#endif // (BLE_HOST_PRESENT)

#if (AHI_TL_SUPPORT)
    TASK_AHI,
#endif // (AHI_TL_SUPPORT)

    /// Maximum number of tasks
    TASK_MAX,

    TASK_NONE = 0xFF,
};</code></pre>

<p>&nbsp;</p>

<p>  可见,task type 和 task index 都是预定义的常量。而且 task index 值的意义是固定的,并非动态分配。task type 值对应的任务类型可以配置,不完全固定。然后,task type 和 task index 看起来不能随意组合成一个有效的 task id. 消息ID里面包含的,是 task index 而非 task type, 文档的叙述不确切。</p>

<p>&nbsp;</p>

<p>  来看一个工程代码中涉及到 task id 的调用:</p>

<pre>
<code class="language-cpp">   ke_timer_set(LED_TIMER, TASK_APP, TIMER_2S_SETTING);</code></pre>

<p>  这个函数原型是:</p>

<pre>
<code class="language-cpp">/* @param timer_id      Timer identifier (message identifier type).
* @param task_id       Task identifier which will be notified
* @param delay         Delay in time units.               ******/
void ke_timer_set(ke_msg_id_t const timer_id, ke_task_id_t const task, uint32_t delay);</code></pre>

<p>其中的第二个参数是 ke_task_id_t 类型的,在调用中传入参数是 TASK_APP, 这是一个 task type 值。这样的话,高8位,即 task index 被置0了。又晕了。</p>

<p>&nbsp;</p>

<p>  再看一处调用:</p>

<pre>
<code class="language-cpp">    cmd = KE_MSG_ALLOC(GAPM_RESET_CMD, TASK_GAPM, TASK_APP, gapm_reset_cmd);</code></pre>

<p>隐含调用的是函数</p>

<pre>
<code class="language-cpp">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);</code></pre>

<p>仍然是 TASK_GAPM, TASK_APP 两个 task type 值被用作了需要 task id 的参数。</p>

<p>&nbsp;</p>

<p>  既然如此用法是能工作的,那么 task index 在实际中并不是很重要?尚且不明白的是,task type, task index 在消息处理过程中的作用是什么。</p>

<p>&nbsp;</p>

<p>  我将 ble_peripheral_server_hrp 例子稍做修改,用自己的 handler 替换原来的,以便插入调试代码:</p>

<pre>
<code class="language-cpp">int My_MsgHandler(ke_msg_id_t const msg_id, void *param,
                ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
        PRINTF("[%04X: %04X&lt;-%04X]\n", msg_id, dest_id, src_id);

        return MsgHandler_Notify(msg_id, param, dest_id, src_id);
}</code></pre>

<p>  然后重新编译,烧写,运行。在 RTT Viewer 中看到:</p>

<pre>
<code>00&gt;
00&gt; ble_peripheral_server_bond has started 20:34:28!
00&gt;
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt; conidx=0
00&gt;
00&gt;
00&gt;
00&gt;
00&gt;
00&gt;
00&gt;
00&gt;
00&gt;
00&gt; </code></pre>

<p>  My_MsgHandler 处理过的以上消息,参数中 task id 对应的 task index 都是0, 即仅含有 task type. 但是消息ID都包含了task index. 那么消息ID的task index是发送方还是接收方?看似都有可能。</p>

<p>  由 <strong>Kernel_Schedule()</strong> 来处理所有的消息,选择恰当的 handler, 那么它首先要决定的是在哪个 task (type)的 handler 函数列表中查找。根据上面测试结果,应当是由消息的 dest_id 包含的 task type 来决定。</p>

<p>  如前所述,一个 task 的 handler 函数可以不止一个,在 ke_msg_handler 结构中有一个id成员表示了消息ID, 那就意味着有一种根据消息ID进行匹配的机制。由于这部分代码是二进制的,不容易看它是如何匹配的。</p>

<p>  用 GDB 查看了一下 TASK_GATTM 的 default_handler 列表,一共8个,包括消息ID与 handler 函数</p>

<table align="left" border="1" cellpadding="1" cellspacing="1" style="width: 100%;">
        <tbody>
                <tr>
                        <td>id = 65535,</td>
                        <td>func = 0x1129bf &lt;gattm_default_msg_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2816,</td>
                        <td>func = 0x112b0f &lt;gattm_add_svc_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2818,</td>
                        <td>func = 0x112ae5 &lt;gattm_svc_get_permission_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2820,</td>
                        <td>func = 0x112abb &lt;gattm_svc_set_permission_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2822,</td>
                        <td>func = 0x112a75 &lt;gattm_att_get_permission_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2824,</td>
                        <td>func = 0x112a49 &lt;gattm_att_set_permission_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2826,</td>
                        <td>func = 0x1129f1 &lt;gattm_att_get_value_req_handler+1&gt;</td>
                </tr>
                <tr>
                        <td>id = 2828,</td>
                        <td>
                        <p>func = 0x1129c3 &lt;gattm_att_set_value_req_handler+1&gt;</p>
                        </td>
                </tr>
        </tbody>
</table>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>  除了第一项的ID为0xFFFF外,后面7项ID的高8位都是0x0B, 也就是对应 TASK_ID_GATTM.&nbsp;<br />
  在 gattm_task.h 中找到消息ID的定义:<br />
&nbsp;</p>

<pre>
<code class="language-cpp">/// GATT Task messages
enum gattm_msg_id
{
    /* Database Management */
    /// Add service in database request
    GATTM_ADD_SVC_REQ = TASK_FIRST_MSG(TASK_ID_GATTM),
    /// Add service in database response
    GATTM_ADD_SVC_RSP,

    /* Service management */
    /// Get permission settings of service request
    GATTM_SVC_GET_PERMISSION_REQ,
    /// Get permission settings of service response
    GATTM_SVC_GET_PERMISSION_RSP,
    /// Set permission settings of service request
    GATTM_SVC_SET_PERMISSION_REQ,
    /// Set permission settings of service response
    GATTM_SVC_SET_PERMISSION_RSP,

    /* Attribute Manipulation */
    /// Get permission settings of attribute request
    GATTM_ATT_GET_PERMISSION_REQ,
    /// Get permission settings of attribute response
    GATTM_ATT_GET_PERMISSION_RSP,
    /// Set permission settings of attribute request
    GATTM_ATT_SET_PERMISSION_REQ,
    /// Set permission settings of attribute response
    GATTM_ATT_SET_PERMISSION_RSP,

    /// Get attribute value request
    GATTM_ATT_GET_VALUE_REQ,
    /// Get attribute value response
    GATTM_ATT_GET_VALUE_RSP,
    /// Set attribute value request
    GATTM_ATT_SET_VALUE_REQ,
    /// Set attribute value response
    GATTM_ATT_SET_VALUE_RSP,

    /* Debug messages */
    /// DEBUG ONLY: Destroy Attribute database request
    GATTM_DESTROY_DB_REQ,
    /// DEBUG ONLY: Destroy Attribute database response
    GATTM_DESTROY_DB_RSP,
    /// DEBUG ONLY: Retrieve list of services request
    GATTM_SVC_GET_LIST_REQ,
    /// DEBUG ONLY: Retrieve list of services response
    GATTM_SVC_GET_LIST_RSP,
    /// DEBUG ONLY: Retrieve information of attribute request
    GATTM_ATT_GET_INFO_REQ,
    /// DEBUG ONLY: Retrieve information of attribute response
    GATTM_ATT_GET_INFO_RSP,
};</code></pre>

<p>&nbsp;</p>

<p>  翻译出来,表中消息ID与handler函数是:</p>

<p>&nbsp; &nbsp; GATTM_ADD_SVC_REQ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;----- gattm_add_svc_req_handler<br />
&nbsp; &nbsp; GATTM_SVC_GET_PERMISSION_REQ &nbsp; ----- gattm_svc_get_permission_req_handler<br />
&nbsp; &nbsp; GATTM_SVC_SET_PERMISSION_REQ &nbsp; ----- gattm_svc_set_permission_req_handler<br />
&nbsp; &nbsp; GATTM_ATT_GET_PERMISSION_REQ &nbsp; ----- gattm_att_get_permission_req_handler<br />
&nbsp; &nbsp; GATTM_ATT_SET_PERMISSION_REQ &nbsp; ----- gattm_att_set_permission_req_handler<br />
&nbsp; &nbsp; GATTM_ATT_GET_VALUE_REQ &nbsp; &nbsp; &nbsp; &nbsp;----- gattm_att_get_value_req_handler<br />
&nbsp; &nbsp; GATTM_ATT_SET_VALUE_REQ &nbsp; &nbsp; &nbsp; &nbsp;----- gattm_att_set_value_req_handler</p>

<p>刚好名称都对应上了。看来第一个 gattm_default_msg_handler 是用来处理余下的没有对应ID的消息的。反汇编了一下,发现它什么都没有做,就算处理完了。<br />
<span style="color:#2980b9;"><span style="font-family:Courier;">(gdb) disass gattm_default_msg_handler<br />
Dump of assembler code for function gattm_default_msg_handler:<br />
&nbsp; &nbsp;0x001129be &lt;+0&gt;: &nbsp; &nbsp; movs &nbsp; &nbsp;r0, #0<br />
&nbsp; &nbsp;0x001129c0 &lt;+2&gt;: &nbsp; &nbsp; bx &nbsp; &nbsp; &nbsp;lr<br />
End of assembler dump.</span></span></p>

<p>这表明,在正常情况下是不应当有除了以上7种ID的消息之外的任何消息,发送给 GATTM_TASK 的。</p>

<p>&nbsp;</p>

<p>  至此,我大概明白了Event Kernel 涉及到的 task 是怎样一个概念,消息发送给一个&nbsp;task 时,调度器如何选择其默认的 handler 函数列表中的函数来处理消息。</p>

<p>&nbsp;</p>

Jacktang 发表于 2021-6-9 07:40

<p>经验之谈,</p>

<p>楼主把自己陌生学习分析心得总结出来,肯定会对大家开发RSL10程序有帮助的</p>

<p>这次活动&nbsp;ON 的文档RSL10 Firmware Reference有的地方说明确实欠缺,该说明的没说</p>

7905 发表于 2021-6-9 08:56

<p>谢谢楼主分享!因忙做不到像楼主一样做细致深入工作,点个赞!功在当代,利在千秋!先收藏下来用时学习,谢啦~</p>

dql2016 发表于 2021-6-9 13:15

<p>前来学习,话说,这个芯片资料上手难度比常用的芯片确实高了点,估计是用的人少的原因吧,网上关于它的资料太少了。</p>

lightxixi 发表于 2021-6-9 14:09

<p>谢谢分享,辛苦楼主了。<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/congra.gif" width="48" /></p>

freebsder 发表于 2021-6-9 17:47

<p>回调确实严重阻碍静态代码分析,跑跑就不知道调哪里去了。</p>

ljj3166 发表于 2021-6-9 23:04

本帖最后由 ljj3166 于 2021-6-9 23:05 编辑

<p>真牛,还没这么仔细考虑过</p>

<p>不过我觉得这个所谓kernel本质上只是完成了一个BLE协议栈软件定时器的调度工作</p>

<p>更像是一个链表或者队列的调度</p>

<p>所有task是根据软件定时器的ID和handler来完成处理</p>

<p>至于index,可能只是对应软件定时器在链表或者队列索引吧</p>

bobde163 发表于 2021-6-12 10:08

<p>看着像是基于消息驱动的处理架构,任务间的协作都是通过发送消息来处理的,但是又叫event_kernel事件内核,一开始以为是事件驱动呢,楼主分析的很细致,有些代码不开源,分析确实会比较难懂</p>
页: [1]
查看完整版本: 关于RSL10 SDK中Event Kernel部分的代码分析(上)