BLE-DA14580-Part-9-Da14580 框架
----------------------------------------------转载请注明出处------------------------------------
BLE-DA14580-Part-8-串⼝透传略..........
// DA14580 框架简要分析:
以官⽅demo为例,解析经常出现的关键结构,
DA14580 中可以创建多个“任务”任务ID如下图,详细查看源码,
enum KE_TASK_TYPE
{
TASK_NONE = 0xFF,
TASK_APP          = 50  ,  // Do not Alter.
TASK_SAMPLE128    ,  // Sample128 Task
.
..
TASK_MAX          = 64,  //MAX is 64. Do  not exceed.
};
那么每个ID都会有相应的消息接收函数,查看app.c,app_task.c⽂件,这两个⽂件主要处理蓝⽛底层消息处理定义的Handler部分如下,此时只要知道,当有个消息(⽐如GAPM_CMP_EVT)传送过来,
那么接下去就是调⽤gapm_cmp_evt_handler函数。(那么消息是怎么传过来的?详见下⾯消息传送)EXTERN const struct ke_msg_handler app_default_state[] =
{
{GAPM_DEVICE_READY_IND,                (ke_msg_func_t)gapm_device_ready_ind_handler},
{GAPM_CMP_EVT,                          (ke_msg_func_t)gapm_cmp_evt_handler},
{GAPM_DEV_NAME_IND,                        (ke_msg_func_t)gapm_dev_name_ind_handler},
…-…-…-…-
}
//-----------------  消息发送    -------------------------------------
个⼈归纳,可以分为两种类型,
⼀种由DA14580内核发送:(我们在源码中查看不到发送的函数,但能到相应⽂档,查到相应的⼊⼝函数):参看⽂档RW-BLE-GAP-IS.PDF以及RW-BLE-GAPP-IS.PDF,
举例:发送开始⼴播命令给RW-内核,GAPM_START_ADVERTISE_CMD (上述两个⽂档⾃⼰查下该命令)根据⽂档,会产⽣两种应答:
Response:      GAPC_CONNECTION_REQ_IND          如果有连接建⽴
GAPM_CMP_EVT                        当操作完成⼜或者取消
那么显⽽易见,当发送完开始⼴播命令时,
有连接建⽴时,调⽤上述 app_default_state[] GAPC_CONNECTION_REQ_IND 对应的函数~
当操作完成(即设备开始发出⼴播),或者中途⼜发送了停⽌⼴播的命令时,
⼀种由我们⾃⼰发送:以bass.c bass_task.c为例
在bass_task.c⽂件中定义了如下⼏个状态,每种状态对应⼀个或多个消息函数。
enum
{
enum函数BASS_DISABLED, /// Disabled state
BASS_IDLE,/// Idle state
BASS_CONNECTED, /// Connected state
BASS_STATE_MAX/// Number of defined states.
};
举例:发送BASS_BATT_LEVEL_UPD_REQ 消息,注:该消息是我们⾃⼰定义的(⼜或者官⽅demo事先写好了),消息定义如下,第⼀个消息不为0,(可以⼤胆猜测每个profile对应的消息ID实际上是唯⼀的)。
enum/// Messages for Battery Server
{
/// Add a BAS instance into the database
BASS_CREATE_DB_REQ = KE_FIRST_MSG(TASK_BASS),
/// Battery Level Value Update Request
BASS_BATT_LEVEL_UPD_REQ,
}
对应的消息接收函数(该接收函数实际也是要我们⾃⼰写的):
/// Connected State handler definition.
const struct ke_msg_handler bass_connected[] =
{
{BASS_BATT_LEVEL_UPD_REQ,      (ke_msg_func_t) bass_batt_level_upd_req_handler},
{GATTC_WRITE_CMD_IND,          (ke_msg_func_t) gattc_write_cmd_ind_handler},
{GATTC_CMP_EVT,                (ke_msg_func_t) gattc_cmp_evt_handler},
};
那么我们只要发送这样的消息:
struct bass_batt_level_upd_req * req = KE_MSG_ALLOC(BASS_BATT_LEVEL_UPD_REQ, TASK_BASS, TASK_APP, bass_batt_level_upd_req);
// Fill in the parameter structure
…-…-
// Send the message
ke_msg_send(req);
接下来内核⾃动回调bass_batt_level_upd_req_handler。
//---------------    以上是消息的发送      --------------
内核就是通过消息传递的形式来运⾏的,
app.c 跟app_task.c 该⽂件中的函数以及消息类型要参看⽂档就能理解。
下⾯讲解如果我们⾃定义profile,需要注意的东西:
同样以bass.c bass_task.c ⽂件为例,如下的ke_msg_handler 是必须的。
/// Specifies the message handler structure for every input state.
const struct ke_state_handler bass_state_handler[BASS_STATE_MAX] =
{
[BASS_DISABLED]      = KE_STATE_HANDLER(bass_disabled),
[BASS_IDLE]          = KE_STATE_HANDLER(bass_idle),
[BASS_CONNECTED]      = KE_STATE_HANDLER(bass_connected),
};
/// Default State handlers definition
const struct ke_msg_handler bass_default_state[] =
{
{GAPC_DISCONNECT_IND,        (ke_msg_func_t)gapc_disconnect_ind_handler},
};
注意到,有状态:disable,idle,connected,default,⼤胆猜测:根据状态的不同⽽选择不同的消息⼊⼝!
可以看到有变量⽤于指⽰当前的状态:/// Defines the place holder for the states of all the task instances.
ke_state_t bass_state[BASS_IDX_MAX] __attribute__((section("retention_mem_area0"),zero_init)); //@RETENTION MEMORY
(BASS_IDX_MAX)⼀般为1,实例的对象。
内核中提供函数来修改BASS这个实例的状态:
ke_state_set(TASK_BASS, BASS_CONNECTED);设置到connected状态,消息接收函数要注意变成了bass_connected 这个handler了。
//--------------------  以上为⾃定义实例对象的主要框架。
// 系统提供的定时器的使⽤
app_timer_set(……)的使⽤。
ke_timer_clear(……)的使⽤。
按照上述的消息发送与接收介绍,设置定时器只需要
1.定义定时器消息,如APP_TIMER_BUTTON_100MS
/// APP Task messages
enum APP_MSG
{
APP_MODULE_INIT_CMP_EVT = KE_FIRST_MSG(TASK_APP),
…-…-
APP_TIMER_BUTTON_100MS,
};
2.定义定时器消息⼊⼝函数,(注意,该消息定义在TASK_APP 这个实例中!因此回调函数也应放在TASK_APP 这个实例中,
也就是app_default_state 的handler 中)
EXTERN const struct ke_msg_handler app_default_state[] =
{
{GAPM_DEVICE_READY_IND,                (ke_msg_func_t)gapm_device_ready_ind_handler},
…-…-
{APP_TIMER_BUTTON_100MS,                (ke_msg_func_t)app_timer_button_100ms_handler},
…-…-
}
int app_timer_button_100ms_handler(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
…-…-…-…-…-…-
}
3.发送定时器消息给内核。
设置定时器 app_timer_set(APP_TIMER_BUTTON_100MS,TASK_APP,10); //10代表10 * 10ms = 100ms
取消定时器ke_timer_clear(APP_TIMER_BUTTON_100MS, TASK_APP);
这样⼀个定时器就完成咯~(注意,定时器在内核接收到RESET_CMD 的时候,定时器会清空)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。