UIM卡上电需要满足下面的时序。
    
                                 UIM上电时序                                                          UIM下电时序

MSM8909平台UIM初始化流程如下。

在initialize_intctrl中设置了UART接收数据的中断服务程序为uimIntctrlIsr,当UART的DATA数据线为接收模式时,一旦DATA线上面有数据,uimIntctrlIsr函数就会被调用。

/* Initialize interrupt controller */
void initialize_intctrl(uim_instance_global_type *uim_ptr)
{. . . . . .DalInterruptController_RegisterISR(uim_hw_if.intctrl[uim_instance].m_IntCtrl_handle_ptr,uim_hw_if.intctrl[uim_instance].m_uartIRQNum,(DALISR) uimIntctrlIsr,// 设置UART接收中断服务函数(const DALIRQCtx) uim_ptr,DALINTRCTRL_ENABLE_LEVEL_HIGH_TRIGGER);
. . . . . .
} /* initialize_intctrl */

在uim_initialize_state中,设置UIM的当前工作电压为1.8V,UIM支持的最大电压为3V。

void uim_initialize_state
(uim_instance_global_type *uim_ptr
)
{
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *//* Initialize the uim Rx character ISR processing state. */uim_ptr->rxtx_state_machine.rx_state = UIM_RX_PROCESS_IDLE;if (uim_ptr->hardware.uim_ldo.customize_ldo_setting &&uim_ptr->hardware.uim_ldo.desired_voltage_class != UIM_VOLTAGE_CLASS_INVALID){/* Set the UIM interface voltage to desired voltage class */uim_ptr->state.current_voltage_class = uim_ptr->hardware.uim_ldo.desired_voltage_class;uim_ptr->state.max_possible_voltage_class = uim_ptr->hardware.uim_ldo.desired_voltage_class;}else{/* Set the UIM interface voltage to the minimum voltage class */// 设置UIM的当前电源电压为1.8Vuim_ptr->state.current_voltage_class = UIM_VOLTAGE_CLASS_C;// 设置UIM支持的最大电压为3Vuim_ptr->state.max_possible_voltage_class = UIM_VOLTAGE_CLASS_B;}
} /* uim_initialize_state */

UIM_VOLTAGE_CLASS_C和UIM_VOLTAGE_CLASS_B在modem_proc\uim\uimdrv\src\uimdrv.h中定义。

/* The enum type describes the voltage classes supported on the UIM interface.The list must start at the lowest voltage and progress top the highest voltagein order. */
typedef enum {UIM_VOLTAGE_CLASS_INVALID,UIM_VOLTAGE_CLASS_C,  /* Use 1.8 volts */UIM_VOLTAGE_CLASS_B,  /* Use 3 volts */
} uim_voltage_class_type;

SET_UIM_BAUD_RATE_SLOT函数用来设置UART通信的波特率,该函数在modem_proc\uim\uimdrv\src\hw\clkregime\uimdrv_clk.c中定义。

void SET_UIM_BAUD_RATE_SLOT
(uim_instance_enum_type  uim_instance,uim_clock_rate_conversion_factor_type  nFI,uim_baud_rate_adjustment_factor_type   nDI
)
{uim_instance_global_type *uim_ptr = uim_get_instance_ptr(uim_instance);if(uim_ptr == NULL){UIM_MSG_ERR_0("SET_UIM_BAUD_RATE_SLOT: uim_ptr is NULL");return;}/* Store the current FI and DI */// 设置FI参数uim_ptr->state.FI_current = nFI;// 设置DI参数uim_ptr->state.DI_current = nDI;setBaudRate(uim_ptr->id, nFI, nDI);return;
} /* SET_UIM_BAUD_RATE_SLOT */

UART波特率的计算方法:CLK / (FI / DI),CLK一般输出为3.84MHZ或者4.8MHZ,本例中SET_UIM_BAUD_RATE_SLOT传入的参数分别是UIM_CRCF_372_1和UIM_BRAF_1。

/* Set the UART clock to the default values. */
SET_UIM_BAUD_RATE_SLOT ( uim_ptr->id, UIM_CRCF_372_1, UIM_BRAF_1);

UART的波特率等于3840000 / (372 / 1) = 10323。这个是大部分UIM卡的速率,叫做一倍速卡,还有一种4倍速的卡,波特率等于3840000 / (372 / 4) = 41290,高通平台目前支持一倍速的卡。uim_dev_init中设置的波特率在后面给UIM卡复位的时候会再次被更改,后面会提到。

UIM上电流程如下。

进入uim_reset_uim函数分析

void uim_reset_uim
(rex_sigs_type            *mask,boolean                   me_powerup,uim_instance_global_type *uim_ptr
)
{. . . . . ./* Indicate that we did not receive the ATR */uim_ptr->atr.atr_received = FALSE;/* reset the voltage_class_known_from_atr varialbe */uim_ptr->flag.voltage_class_known_from_atr = FALSE;if (me_powerup){. . . . . ./* command to power up the UIM due to task start up */if (uim_ptr->command.static_cmd_buf.hdr.command == UIM_HOTSWAP_CARD_INS_F){UIMDRV_MSG_LOW_1(uim_ptr->id,"HOTSWAP: uim_reset_uim due to card inserted command for slot 0x%x",uim_ptr->command.static_cmd_buf.hdr.slot);}uim_ptr->command.static_cmd_buf.hdr.command = UIM_INTERNAL_ME_PUP_F;}else{. . . . . .}uim_process_command(mask, uim_ptr);
} /* uim_reset_uim() */

uim_ptr->command.static_cmd_buf.hdr.command = UIM_INTERNAL_ME_PUP_F;设置状态机的初始状态。UIM_INTERNAL_ME_PUP_F是一个宏,值为0x0100,在modem_proc\uim\api\uim_v.h中定义:

/* Command types */
typedef enum {UIM_NO_SUCH_COMMAND_F = 0,     /* No such command */UIM_INTERNAL_ME_PUP_F = 0x0100,/* POWER UP UIM due to task start up */UIM_INTERNAL_WAKE_UP_F,        /* Power up due to Power management */. . . . . .UIM_MAX_F
} uim_cmd_name_type;

接下来调用uim_process_command函数:

void uim_process_command
(/* Pointer to received command */rex_sigs_type            *mask,/* rex signals type mask */uim_instance_global_type *uim_ptr
)
{. . . . . ./* If the current directory is current to process the command, thenprocess the command */if(FALSE == intermediate_select.is_needed){. . . . . ./* Get the mode of the command */uim_ptr->state.cmd_mode =(uim_command_mode_type) UIM_GET_CMD_MODE((int)uim_ptr->command.cmd_ptr->hdr.command);switch (uim_ptr->state.cmd_mode){. . . . . .case UIM_GENERIC_CMD:default:command_transacted = uim_process_generic_command (uim_ptr);break;}  /* end for switch */}else{. . . . . .}. . . . . .
} /* uim_process_command */

UIM_GET_CMD_MODE是一个宏,在modem_proc\uim\uimdrv\src\uim.c中定义:
#define UIM_GET_CMD_MODE(command) ((command >> 8) & 0x0F)
uim_ptr->command.cmd_ptr->hdr.command在前面被赋值为0x0100,这样uim_ptr->state.cmd_mode的值就是0x01,在switch中会走UIM_GENERIC_CMD分支。UIM_GENERIC_CMD是一个宏,在modem_proc\uim\uimdrv\src\uimi.h中定义:

typedef enum {UIM_NO_SUCH_CMD = 0x0,UIM_GENERIC_CMD = 0x1,UIM_GSM_CMD     = 0x2,UIM_CDMA_CMD    = 0x3,UIM_USIM_CMD    = 0x4,UIM_ISIM_CMD    = 0x5
} uim_command_mode_type;

接下来进入uim_process_generic_command函数:

boolean uim_process_generic_command
(uim_instance_global_type *uim_ptr
)
{. . . . . ./* Process the generic command. */switch (uim_ptr->command.cmd_ptr->hdr.command){case UIM_INTERNAL_ME_PUP_F:         /* POWER UP UIM due to task start up */uim_ptr->command.generic_state_ptr = UIM_INTERNAL_PUP_STATES;break;. . . . . .}if (status){/* Call the state machine. */uim_generic_command (uim_ptr);}else{. . . . . .}return(status);
} /* uim_process_generic_command() */

uim_ptr->command.cmd_ptr->hdr.command在前面被赋值为UIM_INTERNAL_ME_PUP_F,所以在switch中会走UIM_INTERNAL_ME_PUP_F分支。在这个case分支中,执行了让uim_ptr->command.generic_state_ptr 指针指向了UIM_INTERNAL_PUP_STATES数组,该数组在modem_proc\uim\uimdrv\src\uimgen.c中定义:

/* State configuration for the commands. */
/*  UIM_INTERNAL_ME_PUP_F    = 0x0100, POWER UP UIM due to task start up */
static const uim_generic_state_type UIM_INTERNAL_PUP_STATES[] =
{ UIM_POWER_UP_ST, UIM_RESET_ST,UIM_DELAY_AFTER_ATR_ST, UIM_PPS_ST, UIM_UPDATE_OP_PARAMS_ST,
#if defined( FEATURE_UIM_T_1_SUPPORT )UIM_IFS_NEG_ST,
#endif /* FEATURE_UIM_T_1_SUPPORT */UIM_SEND_STATUS_ST,UIM_CHECK_CHARACTERISTICS_ST,UIM_TERMINAL_CAPABILITY_ST,UIM_SELECT_ICCID_ST, UIM_READ_ICCID_ST,UIM_CHECK_FOR_CDMA_DF,UIM_DONE_ST };

后面会通过对generic_state_ptr指针的操作来进行状态机的切换。接下来调用uim_generic_command函数。

void uim_generic_command
(uim_instance_global_type *uim_ptr
)
{. . . . . ./* Build an APDU based on the UIM generic state */switch(*uim_ptr->command.generic_state_ptr){. . . . . .case UIM_POWER_UP_ST:                     /* Power Up state */{. . . . . .uim_power_up(uim_ptr);. . . . . .if(uim_nv_is_feature_enabled(UIMDRV_FEATURE_INTERFACE_NOT_USED,uim_ptr) == FALSE){uim_timed_sleep(UIM_CARD_DELAY_TIMEOUT, uim_ptr, UIM_ALL_ZERO_SIG);(void)rex_set_sigs(uim_ptr->tcb_ptr, UIM_CMD_RSP_SIG);}} /* end case - UIM_POWER_UP_ST */break;case UIM_RESET_ST:                        /* Reset State */{/* Indicate that we have not yet received an ATR */uim_ptr->atr.atr_received = FALSE;. . . . . ./* Set the flag to FALSE */uim_ptr->atr.atr_pps_done= FALSE;uim_ptr->flag.invalid_pps_received = FALSE;. . . . . ./* Reset the UIM card */uim_reset( &uim_ptr->command.rsp_buf, uim_ptr);. . . . . .} /* end case - UIM_RESET_ST */break;case UIM_DELAY_AFTER_ATR_ST:              /* Introduce delay after ATR */{uim_timed_sleep(UIM_DELAY_TIME_AFTER_ATR, uim_ptr, UIM_ALL_ZERO_SIG);(void)rex_set_sigs(uim_ptr->tcb_ptr,UIM_CMD_RSP_SIG);}break;case UIM_PPS_ST:                          /* PPS State */{. . . . . .uim_send_pps(&uim_ptr->atr.pps_req_buf, uim_ptr);} /* end case - UIM_PPS_ST */break;case UIM_UPDATE_OP_PARAMS_ST:  /* Update Operational Parameters State */{/* Fill out the operational parameters as default values */uim_ptr->state.op_params_buf.change_baud_rate = TRUE;uim_ptr->state.op_params_buf.change_clk_freq = TRUE;uim_ptr->state.op_params_buf.change_guardtime = TRUE;uim_ptr->state.op_params_buf.FI = UIM_CRCF_372_1;uim_ptr->state.op_params_buf.DI = UIM_BRAF_1;if (uim_hw_if.clkreg[uim_ptr->id].m_simClkFreq ==uim_clock_frequency[UIMDRV_CLK_FREQ_3_84_MHZ]){uim_ptr->state.op_params_buf.clock_frequency =UIMDRV_CLK_FREQ_3_84_MHZ;}else if(uim_hw_if.clkreg[uim_ptr->id].m_simClkFreq ==uim_clock_frequency[UIMDRV_CLK_FREQ_4_8_MHZ]){uim_ptr->state.op_params_buf.clock_frequency =UIMDRV_CLK_FREQ_4_8_MHZ;}/* Determine if there is an interface byte to process.  This codeoperates on the ATR as well as the PPS response. */if (uim_ptr->command.rsp_buf.rsp.data[UIM_ATR_T0_BYTE] & (UIM_ATR_TA_PRESENT)){/* Set the op parameters from the ATR/PPS response */uim_ptr->state.op_params_buf.FI = (uim_clock_rate_conversion_factor_type)(uim_ptr->command.rsp_buf.rsp.data[UIM_TA1_INDEX] >> UIM_FI_SHIFT_OF_TA1);uim_ptr->state.op_params_buf.DI = (uim_baud_rate_adjustment_factor_type)(uim_ptr->command.rsp_buf.rsp.data[UIM_TA1_INDEX] & UIM_DI_MASK_OF_TA1);} /* end if - TA(1) does exist in the ATR/PPS. */. . . . . ./* Send the operational parameters */uim_update_op_params( &uim_ptr->state.op_params_buf, uim_ptr);. . . . . ./* Signal is set internally for proper operation of state machine */uim_timed_sleep(UIM_CARD_DELAY_TIMEOUT, uim_ptr, UIM_ALL_ZERO_SIG);(void)rex_set_sigs(uim_ptr->tcb_ptr, UIM_CMD_RSP_SIG);} /* end case - UIM_UPDATE_OP_PARAMS_ST */break;. . . . . .} /* end of main switch */
} /* uim_generic_command */

uim_ptr->command.generic_state_ptr在前面指向了UIM_INTERNAL_PUP_STATES数组,该数组的第一个元素是UIM_POWER_UP_ST,所以在switch中,会走UIM_POWER_UP_ST分支。在这个case中,最后会调用uim_power_up函数。

void uim_power_up
(uim_instance_global_type *uim_ptr
)
{. . . . . ./* Program the currently selected voltage */switch (uim_ptr->state.current_voltage_class){case UIM_VOLTAGE_CLASS_C:{UIMDRV_MSG_HIGH_0(uim_ptr->id, "uim power up @ 1.8 v");uim_program_voltage_class( uim_ptr, UIM_VOLTAGE_CLASS_C );} /* end case - UIM_VOLTAGE_1_8_V */break;case UIM_VOLTAGE_CLASS_B:{UIMDRV_MSG_HIGH_0(uim_ptr->id, "uim power up @ 3 v");uim_program_voltage_class( uim_ptr, UIM_VOLTAGE_CLASS_B );} /* end case - UIM_VOLTAGE_3V */break;default:{UIMDRV_MSG_HIGH_0(uim_ptr->id, "uim power up @ unknown voltage");return;}}/* Turn on the clock for the R-UIM interface */UIM_TCXO_MUST_BE_ON_SLOT(uim_ptr);/* Print the configuration before changing the state */uim_print_uim_config(uim_ptr);/* First, turn on the UIM LDO. */uim_power_on_ldo_slot(uim_ptr);/* Next, place the I/O line in reception mode. */UIM_STOP_BREAK_SLOT(uim_ptr);UIM_CONFIGURE_DATA_FOR_UIM_CONTROLLER(uim_ptr);uim_clk_busy_wait(500);uim_uartdm_uim_controller_recover(uim_ptr);uim_clk_busy_wait(200);UIM_CONFIGURE_CLK_FOR_UIM_CONTROLLER(uim_ptr);uim_clk_busy_wait(200);/* Setup the UIM clock based on clock frequency set by HW enumeration */if (uim_hw_if.clkreg[uim_ptr->id].m_simClkFreq ==uim_clock_frequency[UIMDRV_CLK_FREQ_3_84_MHZ]){uim_clock_control (uim_ptr->id, UIMDRV_CLK_FREQ_3_84_MHZ);}else if(uim_hw_if.clkreg[uim_ptr->id].m_simClkFreq ==uim_clock_frequency[UIMDRV_CLK_FREQ_4_8_MHZ]){uim_clock_control (uim_ptr->id, UIMDRV_CLK_FREQ_4_8_MHZ);}/* Reset the receiver so that the receiver does not process the stop breakas a received byte */UIM_RESET_RX_SLOT (uim_ptr);
} /* uim_power_up */

该函数中,首先根据uim_ptr->state.current_voltage_class的值来进行UIM电源的配置,该值在前面被赋值为UIM_VOLTAGE_CLASS_C,即1.8V。接下来将DATA线设置为接收模式,最后打开UIM的电源,配置CLK线输出3.84MHZ的时钟。注意,uim_power_up中并没有拉高RST线。
uim_generic_command调用完uim_power_up后,通过rex_set_sigs发送UIM_CMD_RSP_SIG信号。返回到uim_task_common函数,在调用完uim_start_initial_powerup后,uim_task_common会进入for循环。

void uim_task_common
(dword uim_global_ptr
)
{. . . . . .uim_dev_init(uim_ptr);. . . . . ./* Power up/reset the card */uim_start_initial_powerup(uim_ptr, &i_mask);. . . . . .for (;;){/* Never exit this loop... *//* Perform the rex wait or check the q and set the signal mask */rex_signals_mask = get_rex_sigs_mask(uim_ptr, i_mask);#ifdef FEATURE_UIM_TEST_FRAMEWORK#error code not present
#endif /* FEATURE_UIM_TEST_FRAMEWORK *//* Handle the signals that are set */b_goto_top = uim_signal_handler(&rex_signals_mask, &i_mask, uim_ptr);. . . . . .} /* end for (;;) */
} /* end uim_task */

该循环会阻塞等待信号,一旦有信号发送,相应的函数就会被调用,信号和函数的对应关系在modem_proc\uim\uimdrv\src\uim_sigs.c中。

/*  This table associates each UIM signal to its appropriate handler function */
static uim_sig_map_type uim_sig_map[] =
{{UIM_DOG_HB_RPT_SIG, uim_handle_dog_sig},{UIM_TASK_STOP_SIG, uim_handle_task_stop_sig},{UIM_SUSPICIOUS_CARD_REM_SIG,uim_handle_card_removed_suspicious_sig},{UIM_POLL_TIMER_SIG, uim_handle_poll_timer_sig},{UIM_HOTSWAP_CMD_CARD_REM_SIG, uim_handle_card_removed_sig},{UIM_HOTSWAP_CMD_CARD_INS_SIG, uim_handle_card_inserted_sig},
#ifdef FEATURE_UIM_USB_UICC{UIM_USB_FALLBACK_TO_ISO_SIG, uim_handle_usb_fallback_to_iso_sig},{UIM_USB_REMOTE_WAKEUP_SIG, uim_handle_usb_remote_wakeup_sig},
#endif /* FEATURE_UIM_USB_UICC */{UIM_STATE_TOGGLE_SIG, uim_handle_state_toggle_sig},{UIM_FETCH_PENDING_SIG, uim_handle_fetch_pending_sig},{UIM_CMD_Q_SIG, uim_handle_cmd_q_sig},{UIM_CMD_RSP_SIG, uim_handle_cmd_rsp_sig},{UIM_EFSLOG_PURGE_SIG, uim_handle_efslog_purge_sig},{UIM_CMD_RSP_TIMEOUT_SIG, uim_handle_cmd_rsp_timeout_sig},{UIM_TRANSACTION_SIG, uim_handle_cmd_rsp_timeout_sig},{UIM_SIMULATE_NULL_TIMER_EXP_SIG, uim_handle_simulate_null_timer_exp_sig},{UIM_BUSY_IND_TIMER_EXP_SIG, uim_handle_busy_ind_timer_exp_sig},{UIM_TRANS_TIMER_EXP_SIG, uim_handle_trans_timer_exp_sig},{UIM_MCGF_NV_REFRESH_SIG, uim_handle_mcgf_nv_refresh_sig},{UIM_EXT_RECOVERY_TIMER_EXP_SIG, uim_handle_extended_recovery_timer_exp_sig},
};

前面说过,uim_generic_command调用完uim_power_up后,通过rex_set_sigs发送UIM_CMD_RSP_SIG信号。在uim_sig_map数组中,UIM_CMD_RSP_SIG信号对应得处理函数是uim_handle_cmd_rsp_sig,该函数调用的流程如下。

进入uim_generic_command_response函数分析。

uim_cmd_status_type uim_generic_command_response
(uim_rsp_buf_type      *rsp_ptr,uim_instance_global_type *uim_ptr
)
{. . . . . ./* Necessary so that we do not change the uim state and switch into thatcase also */curr_uim_generic_state = *uim_ptr->command.generic_state_ptr;UIMDRV_MSG_HIGH_1(uim_ptr->id,"Processsing uim_generic_command_response for state 0x%x",curr_uim_generic_state);switch (curr_uim_generic_state){. . . . . .case UIM_POWER_UP_ST:                     /* Power Up state */{/* Get the next state. */++uim_ptr->command.generic_state_ptr;} /* end case - UIM_POWER_UP_ST */break;. . . . . .} /* end switch - curr_uim_generic_state *//* Continue processing the command only if the response indicates success. */if (status == UIM_CMD_SUCCESS){/* Process the next state of this command. */uim_generic_command(uim_ptr);} /* end if - command is still in progress */. . . . .return(status);
} /* uim_generic_command_response */

在switch中,会走UIM_POWER_UP_ST分支。在这个case中,只是让uim_ptr->command.generic_state_ptr指针指向UIM_INTERNAL_PUP_STATES数组的下一项。所以uim_ptr->command.generic_state_ptr指针指向的值等于UIM_RESET_ST。然后调用uim_generic_command函数,该函数在前面介绍过。uim_generic_command执行到switch时,会走UIM_RESET_ST分支,于是uim_reset被调用。

void uim_reset
(uim_rsp_buf_type         *rsp_ptr,    /* Defines where to put the ATR */uim_instance_global_type *uim_ptr
)
{. . . . . ./* Assert the reset line */UIM_ASSERT_RESET_SLOT (uim_ptr);/* Enable the UART transmitter */UIM_ENABLE_UART_TX_SLOT (uim_ptr);/* Enable the UART receiver */UIM_ENABLE_UART_RX_SLOT (uim_ptr);. . . . . ./* Set the UART clock to the default values. */SET_UIM_BAUD_RATE_SLOT ( uim_ptr->id, UIM_CRCF_372_1, UIM_BRAF_1);. . . . . ./* De-assert the reset line */UIM_DEASSERT_RESET_SLOT (uim_ptr);. . . . . if(uim_nv_is_feature_enabled(UIMDRV_FEATURE_HANDLE_NO_ATR_IN_40000_CLK_CYCLES,uim_ptr) == TRUE){. . . . . .}else{if((uim_ptr->state.DI_current < UIM_BRAF_SIZE) &&(uim_ptr->state.FI_current < UIM_CRCF_SIZE)){uim_uartdm_set_wwt_val(uim_ptr, uim_ptr->card_cmd.work_waiting_time_etus);uim_start_cmd_rsp_timer( uim_ptr->card_cmd.work_waiting_time +UIM_UART_DM_WAITING_TIME_CORRECTION,uim_ptr);}else{. . . . . .}}
} /* uim_reset */

重点来了,uim_reset会调用SET_UIM_BAUD_RATE_SLOT ( uim_ptr->id, UIM_CRCF_372_1, UIM_BRAF_1);重新设置波特率为一倍速,所以不管前面的uim_dev_init函数设置波特率为多少,uim_reset会重置波特率。随后通过UIM_DEASSERT_RESET_SLOT (uim_ptr);来拉高RST线,UIM卡在检测到RST线被高后,会发送ATR给到DATA线。uim_reset的最后会开启定时器,如果定时器超时,那么会发送UIM_CMD_RSP_TIMEOUT_SIG信号,uim_handle_cmd_rsp_timeout_sig函数就会被调用。如果UIM卡在定时时间内发送了ATR,那么uimIntctrlIsr函数就会被调用。

uim_read_rx_fifo会读取DATA线上的数据,保存早uim_ptr->card_cmd.uart_rx_buf中。

void uim_read_rx_fifo
(uim_instance_global_type *uim_ptr,dword  isr,dword *no_of_bytes_received_ptr)
{int length;dword uart_status;int i=0;if(isr == MSMU_ISR_RXSTALE){*no_of_bytes_received_ptr = UIM_GET_NUM_BYTES_IN_RX_SLOT(uim_ptr) - uim_ptr->card_cmd.total_bytes_read;}if (isr == MSMU_ISR_RXLEV){*no_of_bytes_received_ptr = (4 * MSMU_DEF_RFWR_VAL);}if (*no_of_bytes_received_ptr % 4){length = (*no_of_bytes_received_ptr/4) + 1;}else{length = *no_of_bytes_received_ptr/4;}for(uart_status = UIM_READ_STATUS_SLOT(uim_ptr); ((uart_status & MSMU_SR_RXRDY) && (length > 0)) ; length--){uim_ptr->card_cmd.uart_rx_buf[i++] = UIM_GET_RX_WORD_SLOT(uim_ptr);}uim_ptr->card_cmd.total_bytes_read += *no_of_bytes_received_ptr; return;
} /* end uim_read_rx_fifo */

uim_rx_isr_receive_atr会解析ATR中TS,T0等参数,最后会调用uim_command_response_callback来清除定时器,这样定时器就不会发送超时信号。

void uim_command_response_callback
(uim_instance_global_type *uim_ptr
)
{/*if it is a bad status word and Feature is enabled trigger recovery*/if(TRUE == uim_nv_is_feature_enabled(UIMDRV_FEATURE_RECOVERY_ON_BAD_STATUS_WORD, uim_ptr) &&TRUE == uim_ptr->flag.bad_status_words_error){UIMDRV_MSG_ERR_0(uim_ptr->id,"recieved bad status word. forcing recovery");uim_force_recovery(uim_ptr);return;}/* set the command response signal */UIMDRV_MSG_LOW_0(uim_ptr->id,"Recd Command Response Signal");uim_clear_cmd_rsp_timer(uim_ptr);/* clear the signal as well just in case if it was set */(void) rex_clr_sigs( uim_ptr->tcb_ptr, UIM_TRANSACTION_SIG );(void) rex_set_sigs( uim_ptr->tcb_ptr, UIM_CMD_RSP_SIG );
} /*  uim_command_response_callback */

MSM8909平台UIM驱动流程相关推荐

  1. linux设备驱动——andriod平台wlan驱动

    转自 :http://blog.chinaunix.net/space.php?uid=22278460&do=blog&cuid=2186191 linux设备驱动--andriod ...

  2. 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

    以下内容转载于微信公众号:嵌入式企鹅圈.如有侵权,请告知删除. 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sysfs等相关概念和技术. 对于初学者来说会非常 ...

  3. android移植wifi驱动流程porting

    android载入wifi驱动流程 wifi_load_driver check_wifi_chip_type_string get_wifi_device_id save_wifi_chip_typ ...

  4. 高通平台RF配置流程

    高通平台RF配置流程 **注:**本文参考项目路径和代码为SIM7600 LE20分支 1 准备工作 需要的资料: 各个器件的datasheet 原理图 逻辑表(内容包含支持哪些制式.band,各个b ...

  5. MTK平台闪光灯驱动分析

    MTK平台闪光灯驱动分析   以前没写过博客,总想写着来着,把之前学到的做过的东西都记录下来,但是一直没有时间也没那么大的决心.这次趁着刚换工作,正在学习熟悉平台不是太忙的机会,把自己总结的文档写下来 ...

  6. andorid之摄像头驱动流程

    camera成像原理: 景物通过镜头生产光学图像投射到sensor表面上,然后转为模拟电信号,经过数模变成数字图像信号,在经过DSP加工出来,然后在通过IO接口传输到CPU处理. 由于摄像头满足总线. ...

  7. 高通SM4350平台指纹移植流程

    本文总结了高通sm4350平台指纹移植流程,厂家一般会提供移植文档,本文档可作为补充: 准备工作: 1.把指纹模组扣到主板上的SPI连接器上 2.高通sm4350平台,Android R版本全代码,全 ...

  8. 全志linux关机键,全志平台linux启动流程分析

    转载:全志平台linux启动流程分析 一.BROM阶段 机器上电之后会执行固化在BROM里面的一段引导程序,这个程序会依次遍历所有支持的启动介质,直到找到第一个支持的.目前支持的启动介质是sd/mmc ...

  9. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    参考原文:https://www.kancloud.cn/yueqian_scut/emlinux/106829 对原文笔误地方做了修改.重新排版 目录 字符设备驱动.平台设备驱动.设备驱动模型.sy ...

最新文章

  1. 用 Python 快速制作海报级地图
  2. Oracle笔记 十四、查询XML操作、操作系统文件
  3. RHEL7 修改SSH默认端口
  4. sql排名名次分页mysql_mysql 实现排名及中文排序实例[分页累加行号]
  5. 自动化设计-框架介绍 TestSnap
  6. Java中的SOAP技术
  7. 查找php中的内容,如何通过PHP从内容中查找URL?
  8. 阿里云服务器ip:端口号无法访问
  9. 微众银行互联网架构首次曝光
  10. java txt 修改_java创建TXT文件并进行读、写、修改操作
  11. 16c语言第七届省赛,第十六届青少年信息学奥林匹克联赛初赛试题(附答案)
  12. 工具:SQL Server软件使用指南
  13. 在Maya和ZBrush中制作战士模型
  14. 斐波那契数列的java代码
  15. 计算机硬件认识与了解,计算机硬件认识实习报告参考
  16. 软件测试面试两分钟自我介绍
  17. 【个人总结】 2016年个人年度总结
  18. 视频剪辑,就上这5个网站找素材,免费可商用。
  19. cuda安装失败原因汇总
  20. 基于Echarts+HTML5可视化数据大屏展示—大数据统计展示大屏

热门文章

  1. 东星医疗通过注册:上半年营收2亿 苏州济峰与平安基金是股东
  2. P1909 买铅笔(C语言)
  3. 华硕电脑如何开启虚拟化?华硕飞行堡垒7开启虚拟化后,电脑开机黑屏;BOIS中将SVM Mode选择为Enabled就开不了机;控制面板中打开Hyper-V和windows虚拟机监控平台后,重启电脑黑屏
  4. 初二(2)班快乐暑假
  5. 有没有柯尼卡打印机的过滤器
  6. mtk使用android开关机动画,Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)...
  7. 这四款前端开发工具,你必须知道
  8. threejs + mapboxgl 实现能量护盾效果
  9. JavaScript(js)事件冒泡、事件捕获、事件委托详解
  10. matlab拓扑优化流程图,Sigmund的99行Matlab拓扑优化程序简析