| 帮同学宣传一下http://shop57644665.taobao.com/ |
协议栈原语(primitive)与消息(message)的区别如下:
原语是上下层协议栈实体用来交换信息的,而消息是对等实体之间交换信息的。
如设备端mm与rr之间是原语,而设备与网络端rr之间则是消息。
| 帮同学宣传一下http://shop57644665.taobao.com/ |
协议栈原语(primitive)与消息(message)的区别如下:
原语是上下层协议栈实体用来交换信息的,而消息是对等实体之间交换信息的。
如设备端mm与rr之间是原语,而设备与网络端rr之间则是消息。
| 帮同学宣传一下http://shop57644665.taobao.com/ |
本节描述了SIM向GSM的MM和GMM提供的信息。
在GSM协议11.11中对GSM操作的前提有如下描述
For a SIM of Phase 2 or greater, GSM operation shall only start if one of the two following conditions is
fulfilled:
- if EFIMSI and EFLOCI are not invalidated, the GSM operation shall start immediately;
- if EFIMSI and EFLOCI are invalidated, the ME rehabilitates these two EFs.
那么SIM应该提供哪些信息呢?流程是什么样的呢?
Afterwards, the ME runs the following procedures:
- Administrative Information request;
- SIM Service Table request;
- IMSI request;
- Access Control request;
- HPLMN Search Period request;
- PLMN selector request;
- Location Information request;
- Cipher Key request;
- BCCH information request;
- Forbidden PLMN request;
- CBMID request;
- Depersonalisation Control Keys request
- Network’s indication of alerting request (if $(NIA)$ is supported)
好了,我们来看看TI是如何实现这部分协议栈的代码的吧。
总的流程如下(app_sim_read_parameters函数中)
result = app_fdn_bdn_procedures (sim_mmi_insert_ind);
if ((result EQ SIM_NO_OPERATION) OR
!app_sim_mm_insert_ind (sim_mmi_insert_ind))
app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);
else
app_sim_mmi_insert_ind (sim_mmi_insert_ind, result);
PSENDX (MMI, sim_mmi_insert_ind);
if (result NEQ SIM_NO_OPERATION)
app_sim_sms_insert_ind ();
在app_fdn_bdn_procedures函数中会对SIM的IMSI和LOCI是否支持进行判断,同时对bdn和fdn进行判断。
当然一般的SIM卡肯定不会是SIM_NO_OPERATION的,所以必然会进行app_sim_mm_insert_ind (sim_mmi_insert_ind)。
GLOBAL UBYTE app_sim_mm_insert_ind (T_SIM_MMI_INSERT_IND * sim_mmi_insert_ind)
{
//首先分配一个SIMMM协议原语
PALLOC (sim_mm_insert_ind, SIM_MM_INSERT_IND);
SIM_CLEAR_FLAG (TEST_SIM_INSERTED);
//读取administrative data
if (FKT_Select (SIM_AD, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)
sim_mm_insert_ind->c_ad = (UBYTE)length;
if(FKT_ReadBinary ((UBYTE *)&sim_mm_insert_ind->ad, 0, length) EQ SIM_NO_ERROR)
//如果ad[0]&0x80为真表示这是一张测试卡
if(sim_mm_insert_ind->ad[0] & 0x80)
{
SIM_SET_FLAG (TEST_SIM_INSERTED);
#if defined SIM_TOOLKIT
SIM_SET_FLAG (TEST_MODE_POLLING);
#endif
}
/*
* read IMSI (set to zero in case of error)
*/
memset (&sim_mmi_insert_ind->imsi_field, 0, sizeof (T_imsi_field));
if (FKT_Select (SIM_IMSI, NULL, 0) EQ SIM_NO_ERROR)
{
if (FKT_ReadBinary ((UBYTE *)&sim_mm_insert_ind->imsi_field, 0, MAX_IMSI)
…………..
}
/*
* Modify polling algorithm in case of HPLMN == Test Network
*/
if ((sim_mm_insert_ind->imsi_field.c_field >= 3) AND
((sim_mm_insert_ind->imsi_field.field[0] & 0xF7) EQ 0x01) AND
(sim_mm_insert_ind->imsi_field.field[1] EQ 0x10) AND
(sim_mm_insert_ind->imsi_field.field[2] EQ 0x10))
{
SIM_SET_FLAG (TEST_SIM_INSERTED);
#if defined SIM_TOOLKIT
SIM_SET_FLAG (TEST_MODE_POLLING);
#endif
}
/*
* read location information
*/
if (FKT_Select (SIM_LOCI, NULL, 0) EQ SIM_NO_ERROR)
/*
* Access control classes
*/
if (FKT_Select (SIM_ACC, NULL, 0) EQ SIM_NO_ERROR)
/*
* BCCH information
*/
if (FKT_Select (SIM_BCCH, NULL, 0) EQ SIM_NO_ERROR)
/*
* KC and cipher key sequence number
*/
if (FKT_Select (SIM_KC, NULL, 0) EQ SIM_NO_ERROR)
/*
* Read Preferred PLMNs
*/
if (SIM_IS_FLAG_SET (SERVICE_7_SUPPORT))
{
if (FKT_Select (SIM_PLMNSEL, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)
/*
* Read forbidden PLMNs
*/
if (FKT_Select (SIM_FPLMN, NULL, 0) EQ SIM_NO_ERROR)
/*
* Read Acting HPLMN
*/
FileSelRes = FKT_Select(SIM_CING_AHPLMN, NULL, 0);
#if defined (GPRS)
gprs_gmm_insert_ind (sim_mm_insert_ind);
#endif
/*
* send information to mobility management
*/
PSENDX (MM, sim_mm_insert_ind);
SIM_SET_FLAG (MM_KNOWS_FROM_SIM);
}
| 帮同学宣传一下http://shop57644665.taobao.com/ |
SIM协议栈实体在系统启动时会进行什么样的初始化步骤呢?以下以TI的协议栈实现来分析。
在app_init_sim_data这个函数中注册了SIM的insert和remove的hook函数。
simdrv_register(app_sim_insert, app_sim_remove);
GLOBAL void app_sim_insert( T_SIMDRV_atr_string_info *atr_string_info,
U8 config_requested,
T_SIMDRV_config_characteristics *config_characteristics)
{
//在ATR处理完成后,首先将当前dir设为MF
sim_data.act_directory = SIM_MF;
//首先选择DFgsm
error = FKT_Select (SIM_DF_GSM, response, SIM_MIN_DMF_ST_LEN);
//如果成功选择将返回信息存入dir_status中,并设置标识
SIM_SET_FLAG (GSM_DATAFIELD);
//否则选择DF1800
error = FKT_Select (SIM_DF_1800, response, SIM_MIN_DMF_ST_LEN);
SIM_CLEAR_FLAG (GSM_DATAFIELD);
然后分配一个协议原语
T_SIM_ACTIVATE_CNF * sim_activate_cnf;
if (SIM_IS_FLAG_SET (ACTIVATION_STARTED))
{
PALLOC (sim_activate, SIM_ACTIVATE_CNF);
sim_activate_cnf = sim_activate;
}
else
{
PALLOC (sim_activate, SIM_ACTIVATE_IND);
sim_activate_cnf = (T_SIM_ACTIVATE_CNF *)sim_activate;
}
//然后读取ECC
if (FKT_Select (SIM_ECC, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)
FKT_ReadBinary (sim_activate_cnf->ec_code, 0, length);
//然后读取LP
if (FKT_Select (SIM_LP, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)
FKT_ReadBinary (sim_activate_cnf->pref_lang, 0, length);
//将atr也放入协议原语中
memcpy (sim_activate_cnf->atr, atr_string_info->atr_string, length);
//接着检查PIN与PUk的状态
SIM_CLEAR_FLAG (SIM_PIN_FLAG);
sim_activate_cnf->pin_cnt = FKT_check_pin_count (dir_status.pinstatus);
sim_activate_cnf->puk_cnt = FKT_check_pin_count (dir_status.unbstatus);
sim_activate_cnf->pin2_cnt = FKT_check_pin_count (dir_status.pin2status);
sim_activate_cnf->puk2_cnt = FKT_check_pin_count (dir_status.unb2status);
//然后根据pin与puk的状态设置
sim_activate_cnf->cause = SIM_CAUSE_PIN1_EXPECT/SIM_CAUSE_PIN1_EXPECT;
//如果是SIM_CAUSE_PUK1_BLOCKED则向mmi发送消息后直接返回,不在继续向MM和GMM发送消息的过程。
TRACE_EVENT (”Card blocked”);
sim_activate_cnf->cause = SIM_CAUSE_PUK1_BLOCKED;
SIM_EM_SIM_ACTIVATION_RESULT;
PSENDX (MMI, sim_activate_cnf);
SIM_CLEAR_FLAG (ACTIVATION_STARTED);
return;
//如果pin与puk不需要则继续向下执行,否则等待pin与puk的验证。
if (SIM_IS_FLAG_CLEARED (SIM_PIN_FLAG))
/*
* PIN entering is not necessary
*/
{
SIM_SET_FLAG(PIN1_VERIFIED);
TRACE_EVENT (”Read the rest of Parameters”);
app_sim_read_parameters ();
app_start_status_timer (TRUE);
}
else
{
TRACE_EVENT (”Wait for PIN/PUK entering”);
SIM_CLEAR_FLAG (MM_KNOWS_FROM_SIM);
vsi_t_stop (VSI_CALLER SIM_TIMER);
}
app_sim_read_parameters ()
{
//分配SIM_MMI_INSERT_IND协议原语
PALLOC (sim_mmi_insert_ind, SIM_MMI_INSERT_IND);
接着读取SIM的Phase
error = FKT_Select (SIM_PHASE, NULL, 0);
if (error EQ SIM_NO_ERROR)
error = FKT_ReadBinary (&sim_data.sim_phase, 0, 1);
if (sim_data.sim_phase EQ 0)
sim_data.sim_phase = 1;
if (sim_data.sim_phase > 3)
sim_data.sim_phase = 3;
Phase为1的情况下会进行如下操作
// try to read the SIM service table
if (!app_read_sim_service_table(sim_mmi_insert_ind))
{
app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);
return;
}
if (app_sim_mm_insert_ind (sim_mmi_insert_ind) EQ FALSE)
app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);
else
app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_ADN_ENABLED) ;
PSENDX (MMI, sim_mmi_insert_ind);
app_sim_sms_insert_ind ();
Phase为2+的情况说明该sim卡支持STK服务。
stk_perform_profile_download ();
/* Update the Terminal Support table*/
if(FKT_Select(SIM_CING_TRMST, NULL, 0) EQ SIM_NO_ERROR)
{
FKT_UpdateBinary (sim_data.trmst, MAX_TRMST, 0);
}
Phase 2和2+会接着进行如下的操作
result = app_fdn_bdn_procedures (sim_mmi_insert_ind);
if ((result EQ SIM_NO_OPERATION) OR
!app_sim_mm_insert_ind (sim_mmi_insert_ind))
app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);
else
app_sim_mmi_insert_ind (sim_mmi_insert_ind, result);
PSENDX (MMI, sim_mmi_insert_ind);
if (result NEQ SIM_NO_OPERATION)
app_sim_sms_insert_ind ();
}
}
| 帮同学宣传一下http://shop57644665.taobao.com/ |
以data abort 为例
Data_Abort_ISR MOV a1,#DATA_EXCEPTION_TYPE ; Set type DATA_ABORT (4) MOV a2,lr saveException MRS a3,CPSR ; Pickup current CPSR BIC a3,a3,#MODE_MASK ; Clear the mode bits ORR a3,a3,#SUP_MODE ; Prepare to switch to supervisor mode (SVC) MSR CPSR_cxsf,a3 ; Switch to supervisor mode (SVC) LDR a4, SYSTEM_FATAL_ERROR BX a4
SYSTEM_FATAL_ERROR实际是函数stack_system_error的地址
在stack_system_error函数中,首先会切换sp到一个专门为异常处理预留的内存地址上,然后根据异常传入的类型填充必要的参数后调用fatal_error_handler。
kal_fatal_error_handler(kal_char *error_message_ptr, kal_uint32 error_code, kal_uint32 os_error_code)
{
DisableIRQ();
error_param_g.param1 = (kal_uint32)error_message_ptr;
error_param_g.param2 = (kal_uint32)error_code;
error_param_g.param3 = (kal_uint32)os_error_code;
fatal_error_handler((kal_uint8 *)error_param_g.param1, error_param_g.param2, error_param_g.param3);
}
在fatal_error_handler中
{
/* lockout all interrupts */
DisableIRQ();
/* mask all interrupts */
IRQDirectMaskAll();
/*
* NoteXXX: To avoid system hang in the exception handler,
* watchdog remains active while handling exception (if it is enabled).
*/
WDT_Restart2();
/* increase the coutner */
INT_Exception_Enter++;
/* determine if multi-level exception*/
if (INT_Exception_Enter >= 2) {
tst_sysfatal_trace((kal_uint8 *)"Caution: Possibly Endless Nested Exceptions!");
ex_reboot();
}
//以下开始准备得到reset时的系统状态。
/*
* I. Initialize the exception log.
*/
/* reset hardware */
ex_reset_hw();//dma_recover_all,L1Audio_ResetDevice,L1D_PauseDSP
/* re-start WDT again */
WDT_Restart2();
然后得到当前task,并将其优先级设为0,最高
/* get the current thread id */
current_thread = kal_get_current_thread_ID();
/* determine if the current executed task is a TASK, not a HISR */
if ((current_thread != NULL) && (kal_if_hisr() == KAL_FALSE)) {
/* raise the task priority level to the highest */
kal_change_priority((NU_TASK *)current_thread, 0);
}
/* setup param */
param.ext = KAL_FALSE;
param.e1 = param.e2 = param.e3 = 0;
param.dump_param = NULL;
/* initialize the exception log */
/* determine if ARM pre-defined exceptions */
if (err_code < ASSERT_FAIL_EXCEPTION) {
param.type = (exception_type)err_code;
param.code1 = (kal_uint32 *)&os_err_code;
param.code2 = 0;
ex_init_log(¶m);
} else
//在ex_init_log中会取得当前版本信息,当前时间,当前系统堆栈信息,当前task状态,hisr状态
然后
/* output the exception log */
ex_output_log();
最后重启系统
/* reboot silently */
ex_reboot(); //使用watchdog来重启系统。
}
在系统重启后有如下一段代码
; /* Check if abnormal reset */
LDR a1,ABN_RST_PTR
BL INT_SystemReset_Check
在INT_SystemReset_Check中会读取地址为0×80040018 的寄存器的值并且同0×0ffa进行比较不相等就返回否则进入kal_fatal_error_handler
关于0×80040018的这个寄存器,datasheet上如下描述Watchdog Timer Reset Signal Duration Register。This register indicates the reset duration
When Watchdog timer times out
关于这段代码,猜测是因为有可能是系统因为挂起而没有reset watchdog寄存器导致重启,这里就可以进行log的抓取。