📄 otg_drv.c
字号:
OTG_Start_Timer(OTG_TIMER_B_ASE0_BRST, TB_ASE0_BRST);
}
}
static void OTG_Process_B_Wait_ACon(void)
{
/*
** After waiting long enough to insure that the D+ line
** cannot be high due to the residual effect of the B-device
** pull-up,(see Section 5.1.9), the B-device sees that the
** D+ line is high and D- low, (i.e. J state). This indicates
** that the A-device has recognized the HNP request from the
** B-device. At this point, the B-device becomes Host and
** asserts bus reset to start using the bus. The B-device
** must assert the bus reset (SE0) within 1 ms (TB_ACON_BSE0 max)
** of the time that the A-device turns on its
** pull-up.
*/
/* ATTACH_INT will be processed by the host ISR */
if (g_OtgInfo.b_detect_a_conn)
{
OTG_Stop_Timer();
g_OtgInfo.b_suspend_req = KAL_FALSE;
g_OtgInfo.b_hnp_enable = KAL_FALSE;
g_OtgInfo.otg_state = OTG_STATE_B_HOST;
return;
} /* Endif */
/*
** While waiting in the b_wait_acon state, the B-device
** may detect a K state on the bus. This indicates that the
** A-device is signaling a resume condition and is retaining
** control of the bus. In this case, the B-device will return
** to the b_peripheral state.
*/
/*
** b_detect_a_resume will be set by the host ISR when K state is
** detected if (b_detect_a_resume || b_ase0_brst_tmr)
*/
else if ((g_OtgInfo.b_detect_a_resume==KAL_TRUE) ||
(OTG_Is_TimerOut(OTG_TIMER_B_ASE0_BRST) == KAL_TRUE))
{
g_OtgInfo.b_detect_a_resume = KAL_FALSE;
g_OtgInfo.b_hnp_enable = KAL_FALSE;
/* HNP fail, this is caused by A device dose not pull up D+*/
/***********************************************************
OPT test 5.8 and 5.9 require that we must display a message
when a HNP fails. This event should allow the application
to know that HNP failed with Host.
***********************************************************/
if(OTG_Is_TimerOut(OTG_TIMER_B_ASE0_BRST) == KAL_TRUE)
{
/* time out */
g_OtgInfo.b_hnp_fail_hdlr();
}
/* stop the timer */
OTG_Stop_Timer();
/* start up device*/
if((g_OtgInfo.host_up!=KAL_TRUE) || (g_OtgInfo.device_up!=KAL_FALSE))
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.host_up, (kal_uint32)g_OtgInfo.device_up, 0);
g_OtgInfo.host_up = KAL_FALSE;
g_OtgInfo.host_down_hdlr();
g_OtgInfo.device_up = KAL_TRUE;
g_OtgInfo.device_up_hdlr();
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW)));
g_OtgInfo.otg_state = OTG_STATE_B_PERIPHERAL;
}
}
static void OTG_Process_B_Host(void)
{
/*
** If the B-device at any time detects more than 3.125 ms of SE0
** (TB_ASE0_BRST min), then this is an indication that the
** A-device is remaining Host and is resetting the bus. In this
** case the B-device shall return to the b_peripheral state
** and start to process the bus reset before TB_ASE0_BRST max.
*/
if((g_OtgInfo.b_suspend_req==KAL_TRUE) || (g_OtgInfo.b_detect_a_conn==KAL_FALSE))
{
/* start up device*/
if((g_OtgInfo.host_up!=KAL_TRUE) || (g_OtgInfo.device_up!=KAL_FALSE))
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.host_up, (kal_uint32)g_OtgInfo.device_up, 0);
g_OtgInfo.host_up = KAL_FALSE;
g_OtgInfo.host_down_hdlr();
g_OtgInfo.device_up = KAL_TRUE;
g_OtgInfo.device_up_hdlr();
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW)));
g_OtgInfo.otg_state = OTG_STATE_B_PERIPHERAL;
}
}
kal_bool OTG_Process_Exceptions(void)
{
OTG_STATE previous_state = g_OtgInfo.otg_state;
/* Check exception for A device */
if ((g_OtgInfo.otg_state < OTG_STATE_B_IDLE))
{
/*
** Exceptions are as follows.
** 1. Transition to B_IDLE when id = TRUE.
** 2. Transition to A_WAIT_VFALL when V_BUS is voltage is fallen below
** 3. 4 VDC or not able to set the V_BUS voltage.
*/
if((OTG_Get_Plug_Type()==OTG_PLUG_B) ||
(OTG_Is_A_Bus_Valid()==KAL_FALSE))
{
/* stop any active timers*/
/* stop the timer */
OTG_Stop_Timer();
if ((g_OtgInfo.otg_state== OTG_STATE_A_IDLE) &&
(OTG_Get_Plug_Type()==OTG_PLUG_B))
{
g_OtgInfo.otg_state = OTG_STATE_B_IDLE;
if(g_OtgInfo.b_srp_request==KAL_TRUE)
g_OtgInfo.b_srp_stop_hdlr();
g_OtgInfo.b_srp_request = KAL_FALSE;
OTG_Process_B_Idle();
}
else if((g_OtgInfo.otg_state!=OTG_STATE_A_IDLE) && (g_OtgInfo.otg_state!=OTG_STATE_A_WAIT_VFALL))
{
if(g_OtgInfo.a_process_hnp==KAL_TRUE)
g_OtgInfo.a_hnp_stop_hdlr();
g_OtgInfo.a_process_hnp = KAL_FALSE;
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_VFALL;
/* Turn off VBUS*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_ON));
OTG_Process_A_Wait_VFall();
}
}
}
else
{
/*
** Process B- device exceptions
*/
if((OTG_Get_Plug_Type()==OTG_PLUG_A)||
((g_OtgInfo.b_session_valid==KAL_FALSE)&&(g_OtgInfo.otg_state!=OTG_STATE_B_SRP_INIT)))
{
if(g_OtgInfo.b_srp_request==KAL_TRUE)
g_OtgInfo.b_srp_stop_hdlr();
g_OtgInfo.b_srp_request = KAL_FALSE;
if(OTG_Get_Plug_Type()==OTG_PLUG_B)
{
g_OtgInfo.otg_state = OTG_STATE_B_IDLE;
OTG_Process_B_Idle();
}
else
{
g_OtgInfo.otg_state = OTG_STATE_A_IDLE;
g_OtgInfo.a_bus_req = KAL_TRUE;
OTG_Process_A_Idle();
}
}
}
if (g_OtgInfo.otg_state!= previous_state)
{
/* state changed, exception is processed*/
return KAL_TRUE;
}
else
{
/* state not changed, exception is not processed*/
return KAL_FALSE;
}
}
static void OTG_State_Machine(void)
{
static kal_bool b_processing = KAL_FALSE;
if(b_processing==KAL_TRUE)
ASSERT(0);
b_processing = KAL_TRUE;
switch (g_OtgInfo.otg_state)
{
case OTG_STATE_START:
if(OTG_Get_Plug_Type()==OTG_PLUG_B)
{
g_OtgInfo.otg_state = OTG_STATE_B_IDLE;
OTG_Process_B_Idle();
}
else
{
/* ID is false when A device is identified */
g_OtgInfo.a_bus_req = KAL_TRUE;
g_OtgInfo.otg_state = OTG_STATE_A_IDLE;
OTG_Process_A_Idle();
}
break;
case OTG_STATE_A_IDLE:
OTG_Process_A_Idle();
break;
case OTG_STATE_A_WAIT_VRISE:
OTG_Process_A_Wait_VRise();
break;
case OTG_STATE_A_WAIT_BCON:
OTG_Process_A_Wait_BCon();
break;
case OTG_STATE_A_HOST:
OTG_Process_A_Host();
break;
case OTG_STATE_A_SUSPEND:
OTG_Process_A_Suspend();
break;
case OTG_STATE_A_PERIPHERAL:
OTG_Process_A_Peripheral();
break;
case OTG_STATE_A_WAIT_VFALL:
OTG_Process_A_Wait_VFall();
break;
case OTG_STATE_B_IDLE:
OTG_Process_B_Idle();
break;
case OTG_STATE_B_SRP_INIT:
OTG_Process_B_SRP_Init();
break;
case OTG_STATE_B_PERIPHERAL:
OTG_Process_B_Peripheral();
break;
case OTG_STATE_B_WAIT_ACON:
OTG_Process_B_Wait_ACon();
break;
case OTG_STATE_B_HOST:
OTG_Process_B_Host();
break;
default:
ASSERT(0);
break;
}
b_processing = KAL_FALSE;
}
static void OTG_HISR(void)
{
kal_bool b_dev_unmask_irq = KAL_TRUE;
kal_bool b_process_state_machine = KAL_FALSE;
kal_uint32 savedMask;
volatile kal_uint8 IntrStatus;
g_OtgInfo.otg_intr_status = DRV_Reg8(OTG_INT_STAT)&DRV_Reg8(OTG_INT_EN);
IntrStatus = DRV_Reg8(USB_INT_STAT)&DRV_Reg8(USB_INT_ENB);
/* process OTG state machine*/
if( g_OtgInfo.otg_intr_status)
{
if(g_OtgInfo.otg_intr_status&OTG_INT_STATUS_1_MSEC)
OTG_Check_Timer();
savedMask = SaveAndSetIRQMask();
if(g_OtgInfo.b_processing == KAL_FALSE)
{
g_OtgInfo.b_processing = KAL_TRUE;
b_process_state_machine = KAL_TRUE;
}
RestoreIRQMask(savedMask);
if(b_process_state_machine==KAL_TRUE)
{
OTG_State_Machine();
g_OtgInfo.b_processing = KAL_FALSE;
}
}
if(g_OtgInfo.host_up==KAL_TRUE)
{
/* Check data line pulsing by B device */
if ((g_OtgInfo.otg_state == OTG_STATE_A_IDLE) && (g_OtgInfo.a_bus_req==KAL_FALSE) &&
(IntrStatus & VUSB_INT_STAT_ATTACH) && (g_OtgInfo.a_process_srp == KAL_FALSE))
{
OTG_Set_Status(OTG_STATUS_A_DETECT_B_DATA_PLS, KAL_TRUE);
/* clear interrupt and unmask interrupt*/
IRQClearInt(IRQ_USB_CODE);
if((g_OtgInfo.b_unmask_irq==KAL_TRUE) && (USB_HCD_Get_UnMask_Irq()==KAL_TRUE))
IRQUnmask(IRQ_USB_CODE);
return ;
} /* Endif */
USB_HCD_HISR();
b_dev_unmask_irq = USB_HCD_Get_UnMask_Irq();
}
else if(g_OtgInfo.device_up==KAL_TRUE)
{
USB_HISR();
b_dev_unmask_irq = USB_Get_UnMask_Irq();
}
else
{
DRV_Reg8(USB_INT_STAT) = IntrStatus;
}
DRV_Reg8(OTG_INT_STAT) = g_OtgInfo.otg_intr_status;
/* clear interrupt and unmask interrupt*/
IRQClearInt(IRQ_USB_CODE);
g_OtgInfo.is_ProOTGHISR = KAL_FALSE;
if((g_OtgInfo.b_unmask_irq==KAL_TRUE) && (b_dev_unmask_irq == KAL_TRUE))
IRQUnmask(IRQ_USB_CODE);
}
static void OTG_LISR(void)
{
IRQMask(IRQ_USB_CODE);
g_OtgInfo.is_ProOTGHISR = KAL_TRUE;
drv_active_hisr(DRV_USB_HISR_ID);
}
/************************************************************
A plug detection functions
*************************************************************/
/* Detect whether A plug is plug in when power on */
kal_bool OTG_PowerOn_Is_A_Plug(void)
{
volatile kal_uint32 delay;
kal_uint32 nfiq_status;
#ifndef __CUST_NEW__
/*GPIO mode setting as NFIQ*/
GPIO_ModeSetup(63, 0x01);
#endif /* __CUST_NEW__ */
/*level trigger*/
IRQSensitivity(IRQ_GPI_CODE,KAL_FALSE);
//level=DRV_Reg32(IRQ_SENSL);
//DRV_WriteReg32(IRQ_SENSL, (level|0x00020000));
IRQUnmask(IRQ_GPI_CODE);
for(delay=0;delay<300;delay++);
nfiq_status=DRV_Reg32(IRQ_STS2);
IRQMask(IRQ_GPI_CODE);
/* A-plug detect */
if(nfiq_status&IRQCode2Line[IRQ_GPI_CODE])
{
*IRQ_EOI2 = nfiq_status;
return KAL_TRUE;
}
else
{
return KAL_FALSE;
}
}
void OTG_Init_A_Plug_Detect(void)
{
/* ID pin detection*/
nFIQ_Init(OTG_A_Plug_HISR, KAL_TRUE, KAL_FALSE, LEVEL_SENSITIVE); /* not auto unmask*/
if (g_OtgInfo.a_plug_gpt_handle == 0)
GPTI_GetHandle(&g_OtgInfo.a_plug_gpt_handle);
g_OtgInfo.a_plug_intr_allow = KAL_FALSE;
g_OtgInfo.plug_type = OTG_PLUG_B;
}
static void OTG_A_Plug_Timer_Callback(void *data)
{
GPTI_StopItem(g_OtgInfo.a_plug_gpt_handle);
g_OtgInfo.a_plug_intr_allow = (g_OtgInfo.a_plug_intr_allow == KAL_TRUE)? KAL_FALSE: KAL_TRUE;
/*
* This timer is to avoid if interrupt status is changed but
* sw_debounce->eint_intr_allow is still in KAL_TRUE state
* because of no interrupt
*/
if (g_OtgInfo.a_plug_intr_allow)
{
GPTI_StartItem(g_OtgInfo.a_plug_gpt_handle, 5, OTG_A_Plug_Timer_Callback, data);
}
IRQUnmask(IRQ_GPI_CODE);
}
static void OTG_A_Plug_HISR(void)
{
ilm_struct *mfiq_ilm;
GPTI_StopItem(g_OtgInfo.a_plug_gpt_handle);
if ( g_OtgInfo.a_plug_intr_allow == KAL_FALSE)
{
GPTI_StartItem(g_OtgInfo.a_plug_gpt_handle, 5, OTG_A_Plug_Timer_Callback, &g_OtgInfo.a_plug_gpt_handle);
IRQClearInt(IRQ_GPI_CODE);
}
else
{
g_OtgInfo.a_plug_intr_allow = KAL_FALSE;
if(DRV_Reg(GPIO_DINV4)&0x8000)
{
/* inverse */
#ifdef __CUST_NEW__
GPIO_DinvSetup(63, KAL_FALSE);
#else /* __CUST_NEW__ */
DRV_WriteReg(GPIO_DINV4, DRV_Reg(GPIO_DINV4)&(~0x8000));
#endif /* __CUST_NEW__ */
OTG_Set_Plug_Type(OTG_PLUG_B);
DRV_BuildPrimitive(mfiq_ilm,
MOD_DRV_HISR,
MOD_USB,
MSG_ID_USB_A_PLUGOUT_IND,
NULL);
msg_send_ext_queue(mfiq_ilm);
}
else
{
/* inverse */
#ifdef __CUST_NEW__
GPIO_DinvSetup(63, KAL_TRUE);
#else /* __CUST_NEW__ */
DRV_WriteReg(GPIO_DINV4, DRV_Reg(GPIO_DINV4)|0x8000);
#endif /* __CUST_NEW__ */
OTG_Set_Plug_Type(OTG_PLUG_A);
DRV_BuildPrimitive(mfiq_ilm,
MOD_DRV_HISR,
MOD_USB,
MSG_ID_USB_A_PLUGIN_IND,
NULL);
msg_send_ext_queue(mfiq_ilm);
}
IRQClearInt(IRQ_GPI_CODE);
IRQUnmask(IRQ_GPI_CODE);
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -