本文为看雪论坛精华文章
看雪论坛作者ID:vessial(xee)
背景
消息机制简介
* 驱动/任务初始化线程(Driver initiator/Services Launcher)
* 中断服务例程(IST)
* 阻塞型消息接受线程
//信号发送
int rex_send_sigs(utcb *dst_task_obj,unsigned int signal_id);
//第一个参数为向目标任务发送消息的结构定义,第二个参数为要发送的信号id
int rex_wait_sigs(unsigned int recv_sigs_masks);
//第一个参数为可以允许接受信号id的掩码,每个任务最多可以设置可接受信号id个数为32个,每个任务可以接受多个信号id时,通过信号id的或操作来得到该任务可以接受信号的掩码,返回值为接受到的信号id
//如果是带数据的信号发送,封装底层API,类似如下
int send_sigs_with_dat(utcb *dst_task_obj,unsigned int signal_id,data_queue *send_data_queue);
int recv_sigs_with_dat(unsigned int recv_sigs_masks,data_queue *recv_data_queue);
(1) 系统功能任务
* GSM/WCDMA/TDSCDMA/LTE L1/L2/L3相关的协议栈的任务等
* IMS volte/ecall/数据服务/包服务等
* UIM/SIO/A2等
高通基带系统消息机制
在新的基带芯片上面开发新的移动通信技术单元的同时,保证老的功能模块能够正常使用,例如在开发5G功能的同时,以往的4G/3G/2G功能都能够正常使用和切换。
(2) 可扩展性
(3) 低耦合性
msgr_send(umsg *buf,uint32 buf_size);
struct umsg{
struct msgr_hdr_struct_type{
uint32 dest_umid; //offset 0 ,要发送的UMID号
uint16 src_tech_mod_id; //offset 4,发送源tech_mod_id的标识
uint8 num_attach;// offset 7
uint8 tail_flag ;// offset 8 ,头部结尾标志0x7f
uint8 inst_id;// offset 9,
}
uint8 send_dsm_flag;//offset 0x10 ,置1表示发送数据通过dsm结构承载的标志
dsm *dsm_obj;//offset 0x14 , 发送数据dsm结构指针
}
msgrq_wait(void *msgr_client_ptr,void *msg_recv_buf,uint32 msg_recv_buf_size,uint32 *msg_recvd_size_ptr);//接受消息的函数
msgr_register(uint16 mod_id,void *msgr_client_ptr,void *mailbox_obj,uint32 umid);//msgr_client注册umid的消息路由
struct msgr_client_desc{ //全局msgr_client结构描述
uint32 umids_registered;
uint16 msgr_client_reg_type;//1 ->msgrq_sig type,2-> rexq_sig
uint16 tech_mod_id;//
union *msg_sig_p{ //offset 0x10
struct msgrq_sig *msgq_p;//msgr reg type 1,4G及以后使用的mailbox消息传递系统
struct rexq_sig *rexq_p;//msgr reg type 2,兼容2G/3G时代使用的Rex IPC消息传递系统
}
struct msgrq *msgrq_p;//offset 0x14 ,if reg type 1
struct msgr_client_obj *msgr_client_obj_ptr;//offset 0x30
}
struct msgr_client_obj{//msgr_client结构体
unsigned int msgr_client_reg_type;//1-> msgrq aka mailbox,2->rex_q,接受消息的方式
unsigned int register_umid_counts;//offset 8 ,消息接受器注册的umid的总数
unsigned int total_reged_recv_signal_counts;//offset 0x0c,注册的接受消息的signal的个数
union sig_recv_obj{
msgrq_sig *msgrq_signal_obj;// offset 0x10 msgrq_sig type,4/5G未来的主流类型
rexq_sig *rex_signal_obj;//offset 0x10 rexq_sig type ,这个主要是为了兼容之前2/3G的系统的数据结构
}
unsigned int task_recv_signal_set_mask;//offset 0x14 ,注册的接受消息的signal号的掩码
uint32 err_counts;//offset 0x18
unsigned int recvd_signal_id;//offset 0x1c,当前接受到的signal id,msgr_client_reg_type为1
struct msgrq *recvd_msgrq_ptr;//offset 0x20,当前接受消息承载的msgrq对象,msgr_client_reg_type为1
struct msgrq *msgrq_first_entry;// offset 0x24,接受msgrq消息链表结构指针,msgr_client_reg_type为1
unsigned int total_msgrq_counts;//offset 0x28, 可以接受msgrq消息的总数,通过可以task_recv_signal_set_mask来确定,msgr_client_reg_type为1
}
struct msgrq_sig{
uint32 sig_ready_flag;//must be 1
struct sig_def{
uint32 signal_id_for_recv;//offset 8
uint32 signal_reged_wait_mask;//offset 0xc
void * kernel_msg_queue;
unsigned int attribute;
};
}
struct rexq_sig{ //size 0x1c, 兼容2/3G系统的数据结构
utcb *msgr_client_utcb_ptr;//offset 0 任务接受消息使用的utcb标识
uint32 msgr_client_signal_id;//offset 4 接受消息使用的signal id
msg_queue *msgr_out_msg_q;//offset 0x8
msg_queue *rex_msg_in_q;//offset 0xc
uint16 msg_data_q_used_size;//offset 0x10
uint16 rexq_id;//offset 0x12
uint16 msg_data_q_size;//offset 0x14
}
struct msg_data_q{
struct msg_data_q *prev_q;
struct msg_data_q *next_q;
char data[msg_data_q_size-8];
}
struct msg_queue{
struct msg_data_q *headp;
struct msg_data_q *tailp;
uint32 total_q_counts;
}
struct msgrq{
void *msg_recv_buf_header;//offset 0
void *msg_recv_end_buf;//offset 4
char msgrq_name[16];//offset 0x10
int msgrq_recvd_seq;//ofset 0x18
unsigned int reged_recv_signal_id_mask;//offset 0x1c,可供接受消息signal的掩码
void *msgr_buf_remain_ptr;//offset 0x20,可供接受消息的剩余空间起始地址
void *msgr_recv_buf;//offset 0x24,当前接受到消息的buf地址
uint32 msgr_buf_remain_size;//offset 0x28
unsigned int total_msg_recv_buf_size;//offset 0x30
int8 is_buf_in_use;//offset 0x70 ,0-> in use, 1-> not in use
uint32 recvd_msg_blocks;//offset 0x58 ,收到的消息次数总和
struct msgrq *next_msgrq;//offset 0x74
}
struct sm_state_instance{ //eg ,size 0x1c
struct sm_obj *sm;//状态机对象定义
unsigned int current_state_id;//状态机当前所处的状态id
unsigned int recvd_umid_in_sm_entity_seq;//offset 8, 状态机当前收到的umid所在状态机umid列表中的序列号
unsigned int instance_id;// 状态机实例编号
uint8 sm_state_lock;//offset 0x11 0->state unlock,1-> state lock 状态机锁的状态
void *stm_idle_buf;//offset 0x14 状态机操作可能需要的buf空间
unsigned int debug_code;//offset 0x18 状态机调试码
}
struct sm_obj{ //状态机的定义结构
struct msgr_stm_obj *stm;
unsigned char *stm_obj_name; //状态机的名称,例如LTE_RRC_SIB_SM
unsigned int stm_obj_name_hash; //状态机名称的hash值
unsigned int stm_inst_id;//stm instance id ,状态机的实例编号,状态机可能存在多个实例,通过这个编号来区别不同的状态机实体
}
struct msgr_stm_obj {
int instance_counts; //该状态机支持的实例个数
int state_cnts; //该状态机的状态数量
struct state_status_def *state_def;//状态机每个不同状态的定义的数据结构,size state_cnts*0x10
int umid_cnts;//状态机注册的可接受umid总数
struct umid_msg_list *umid_msg_def;//存储umid和umid描述信息的指针,size umid_cnts*8
struct umid_msg_states_func_cb_list *umid_in_state_cb;//存储着所有umid对应每个状态的回调操作函数
void *cb_func1;// stm enter //offset 0x18 ,进入该状态机的回调函数
void *cb_func2;// stm exit //offset 0x1c ,退出该状态机的回调函数
void *cb_func3;// stm error //offset 0x20 ,状态机出错的回调函数
void *cb_func4; //stm debug //offset 0x24 ,状态机调试的回调函数
unsigned int init_state_id; // default 0 ,状态机初始默认状态id
}
struct umid_msg_states_func_cb_list {//状态机在接受到相应的umid后的原语操作回调函数
void *umid_msg_in_states_1_cb_list[umid_cnts];
void *umid_msg_in_states_2_cb_list[umid_cnts];
void *umid_msg_in_states_3_cb_list[umid_cnts];
...
void *umid_msg_in_states_state_cnts_cb_list[umid_cnts];
}
struct state_status_def{//每个状态的定义
unsigned char *state_name; //状态名称,eg,active/inactive etc
void *cb_func1; //state enter //状态机进入该状态的回调函数
void *cb_func2; //state exit //状态机退出该状态的回调函数
void *cb_func3; //state debug ?//可能是调试函数
}
struct umid_msg_list{//状态机可接受的umid消息定义
unsigned char *umid_msg_name; //umid对应的描述名称
unsigned int umid; //umid
}
关键API描述
stm_instance_activate(struct sm_state_instance *sm_st_inst,uint32 inst_id,uint32 initial_state_id);//初始化状态机实例
stm_instance_process_input(uint32 state_id,struct sm_state_instance *sm_st_inst,uint32 sm_inst_id,uint32 umid_input,void *stm_payload_ptr);//对状态机接受到的umid和数据进行原语操作
LTE_RRC_PAGING_SM addr 0xd10b35e0
state machine name: LTE_RRC_PAGING_SM inst_cnts 1 total states 3 total umid 10
state name: INITIAL state enter 0xd0b923a8 state exit 0xd0b923c8 state debug 0x0
state name: IDLE_CAMPED state enter 0xd0b923e0 state exit 0xd0b92400 state debug 0x0
state name: CONNECTED state enter 0xd0b92418 state exit 0xd0b92450 state debug 0x0
0x040d140c LTE_RRC_CAMPED_INDI
0x040d0207 LTE_RRC_DRX_INFO_REQ
0x040d0206 LTE_RRC_SIM_UPDATE_REQ
0x040d0401 LTE_RRC_SERVICE_IND
0x040d0710 LTE_RRC_PAGING_DLM
0x040d1405 LTE_RRC_CONNECTED_INDI
0x040d022a LTE_RRC_MTC_CFG_REQ
0x040d1400 LTE_RRC_STOPPED_INDI
0x040d140b LTE_RRC_NOT_CAMPED_INDI
0x040d1402 LTE_RRC_SIB_UPDATED_INDI
结语
看雪ID:vessial(xee)
https://bbs.pediy.com/user-home-1422.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!