📄 otg_drv.c
字号:
/* HNP failed */
if(OTG_Is_TimerOut(OTG_TIMER_A_IDLE_BDIS)==KAL_TRUE)
{
OTG_Stop_Timer();
if(g_OtgInfo.a_process_hnp!=KAL_TRUE)
{
ASSERT(0);
}
g_OtgInfo.a_process_hnp = KAL_FALSE;
g_OtgInfo.a_hnp_fail_hdlr();
/* B device done not response for HNP, turn off VBUS at this time*/
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_VFALL;
/* Turn off VBUS*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_ON));
}
/* a_detect_b_conn = FALSE if a RESET interrupt happens and it will set by
** the application; a_set_b_hnp_en is false as default and set to
** if the request is not stalled
*/
else if((g_OtgInfo.a_detect_b_conn==KAL_FALSE)&&(g_OtgInfo.a_set_b_hnp_enable==KAL_FALSE))
{
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_BCON;
// USB_Ms_Dbg_Trace(OTG_STATE_A_SUSPEND_WAIT_B_CON, 0);
}
/*
** If the B-device disconnects after the bus has been suspended,
** then this is an indication that the B-device is attempting
** to become Host. When the A-device detects the disconnect
** from the B-device, it shall turn on its D+ pull-up resistor
** within 3 ms (TA_BDIS_ACON max) to acknowledge
** the request from the B-device.
*/
else if((g_OtgInfo.a_detect_b_conn==KAL_FALSE)&&(g_OtgInfo.a_set_b_hnp_enable==KAL_TRUE))
{
/* stop OTG_TIMER_A_IDLE_BDIS 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_DP_HIGH | OTG_CTL_DM_LOW));
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW)));
g_OtgInfo.otg_state = OTG_STATE_A_PERIPHERAL;
g_OtgInfo.a_set_b_hnp_enable = KAL_FALSE;
g_OtgInfo.a_process_hnp = KAL_FALSE;
g_OtgInfo.a_hnp_stop_hdlr();
} /* Endif */
else if (g_OtgInfo.a_resume_req==KAL_TRUE)
{
/* stop OTG_TIMER_A_IDLE_BDIS timer */
OTG_Stop_Timer();
if(g_OtgInfo.a_process_hnp==KAL_TRUE)
{
g_OtgInfo.a_process_hnp = KAL_FALSE;
g_OtgInfo.a_hnp_fail_hdlr();
}
g_OtgInfo.otg_state = OTG_STATE_A_HOST;
USB_HCD_Bus_Control(USB_HCD_BUS_RESUME_SOF);
g_OtgInfo.a_resume_req = KAL_FALSE;
}
/* OPT remote wakeup*/
else if(g_OtgInfo.a_detect_b_resume == KAL_TRUE)
{
/* stop OTG_TIMER_A_IDLE_BDIS timer */
OTG_Stop_Timer();
if(g_OtgInfo.a_process_hnp==KAL_TRUE)
{
g_OtgInfo.a_process_hnp = KAL_FALSE;
g_OtgInfo.a_hnp_fail_hdlr();
}
g_OtgInfo.otg_state = OTG_STATE_A_HOST;
g_OtgInfo.a_set_b_hnp_enable = KAL_FALSE;
OTG_Start_Timer(OTG_TIMER_A_REMOTE_WAKEUP, TA_REMOTE_WAKEUP);
}
/* Activate check VBUS timer */
if(OTG_Is_TimerActive()==KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_A_CHECK_VBUS, TA_CHECK_VBUS);
}
}
static void OTG_Process_A_Peripheral(void)
{
/* check whether VBUS is maintained above VBUS threshold */
if(OTG_Is_TimerOut(OTG_TIMER_A_CHECK_VBUS)==KAL_TRUE)
{
OTG_Stop_Timer();
if(OTG_Is_A_Bus_Valid()==KAL_FALSE)
{
OTG_Process_A_Vbus_Fail();
return;
}
}
#if 1 /* In the curent design, do not allow host init again*/
/*
** A-device detects lack of bus activity for more than 3 ms
** (TA_BIDL_ADIS min) and turns off its D+ pull-up.Alternatively,
** if the A-device has no further need to communicate with the
** B-device, the A-device may turn off VBUS and end the session.
** Sleep INT will be processed by the device ISR a_detect_b_suspend
** variable will be set by the application
** The following will be done when this happens:
**
** - disconnect its pull up
** - allow time for the data line to discharge
** - check if the B-device has connected its pull up
*/
if((g_OtgInfo.a_detect_b_suspend) && ((OTG_Is_TimerActive()==KAL_FALSE) || (OTG_Get_TimerType()==OTG_TIMER_A_CHECK_VBUS)))
{
OTG_Stop_Timer();
/* debounce for OPT4.5-2.9ms */
OTG_Start_Timer(OTG_TIMER_A_BIDLE_ADIS, TA_BIDL_ADIS);
}
else if( (g_OtgInfo.a_detect_b_suspend==KAL_FALSE) && (OTG_Is_TimerOut(OTG_TIMER_A_BIDLE_ADIS)==KAL_TRUE))
{
/* resume or reset during debounce time */
/* stop OTG_TIMER_A_BIDLE_ADIS timer */
OTG_Stop_Timer();
}
else if(OTG_Is_TimerOut(OTG_TIMER_A_BIDLE_ADIS) == KAL_TRUE)
{
OTG_Stop_Timer();
/* start up host */
if((g_OtgInfo.device_up!=KAL_TRUE) || (g_OtgInfo.host_up!=KAL_FALSE))
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.device_up, (kal_uint32)g_OtgInfo.host_up, 0);
g_OtgInfo.device_up = KAL_FALSE;
g_OtgInfo.device_down_hdlr();
g_OtgInfo.host_up = KAL_TRUE;
g_OtgInfo.host_up_hdlr();
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|(OTG_CTL_DP_LOW | OTG_CTL_DM_LOW));
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DP_HIGH | OTG_CTL_DM_HIGH)));
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_BCON;
// USB_Ms_Dbg_Trace(OTG_STATE_A_PERIPHERAL_WAIT_B_CON, 0);
}
#endif
/* Activate check VBUS timer */
if(OTG_Is_TimerActive()==KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_A_CHECK_VBUS, TA_CHECK_VBUS);
}
// official should be this , but not suitable for OPT test
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
}
static void OTG_Process_A_Wait_VFall(void)
{
if((OTG_Is_B_Session_Valid()==KAL_FALSE)
||(OTG_Get_Plug_Type()==OTG_PLUG_B))
{
g_OtgInfo.otg_state = OTG_STATE_A_IDLE;
OTG_Stop_Timer();
/* In current design, conditions that may go here are
1. B device draws too much current
2. A device dose not recognize B device and B device dose not take HNP
3. B device return from HNP host
*/
g_OtgInfo.a_bus_req = KAL_FALSE;
OTG_Process_A_Idle();
} /* Endif */
}
static void OTG_Process_B_Idle(void)
{
/* reset HNP enabled state */
g_OtgInfo.b_hnp_enable = KAL_FALSE;
/* If host or device is up, pull it down*/
if(g_OtgInfo.host_up==KAL_TRUE)
{
g_OtgInfo.host_up = KAL_FALSE;
g_OtgInfo.host_down_hdlr();
}
if(g_OtgInfo.device_up==KAL_TRUE)
{
g_OtgInfo.device_up = KAL_FALSE;
g_OtgInfo.device_down_hdlr();
}
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&
(~(OTG_CTL_DP_HIGH | OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW |OTG_CTL_DM_LOW)) );
/*
** When a B-device detects that the voltage on VBUS is greater
** than the B-Device Session Valid threshold (VSESS_VLD),
** then the B-device shall consider a session to be in progress.
** After the VBUS voltage crosses this threshold, the B-device
** shall assert either the D+ or D- data-line within 100 ms.
*/
if(g_OtgInfo.b_session_valid==KAL_TRUE)
{
OTG_Process_B_Session_Valid();
}
else if(g_OtgInfo.b_srp_request==KAL_TRUE)
{
/* ********* Starting SRP *****************************************
** When the B-device detects that VBUS has gone below its Session End
** threshold and detects that both D+ and D- have been low (SE0) for
** at least 2 ms (TB_SE0_SRP min), then any previous session on the
** A-device is over and a new session may start. The B-device may
** initiate the SRP any time the initial conditions of Section 5.3.2
** are met.
*/
/* activate the timer only if we want to do SRP */
if(OTG_Is_TimerActive() == KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_B_SE0_SRP, TB_SE0_SRP);
/* mask all interrupt in case interrupt happens during SRP
The only interrupt tat be be taken is session valid interrupt (by EINT)*/
DRV_WriteReg8(USB_INT_ENB, 0);
}
/* timeout and below session end*/
if((OTG_Is_TimerOut(OTG_TIMER_B_SE0_SRP)) &&
(OTG_Is_B_Session_End()==KAL_TRUE))
{
OTG_Stop_Timer();
/*
** initial conditions are met as described above and then turns
** on its data line pull-up resistor (either D+ or D-) for a
** period of 5 ms to 10 ms (TB_DATA_PLS). A dual-role B-device is
** only allowed to initiate SRP at full-speed, and thus shall
** only pull up D+. The duration of such a data line pulse is
** sufficient to allow the A-device to reject spurious voltage
** transients on the data lines.
*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|OTG_CTL_DP_HIGH);
OTG_Start_Timer(OTG_TIMER_B_DATA_PLS, TB_DATA_PLS);
g_OtgInfo.otg_state = OTG_STATE_B_SRP_INIT;
g_OtgInfo.b_check_session = KAL_TRUE;
}
}
}
static void OTG_Process_B_Session_Valid(void)
{
if(g_OtgInfo.otg_state==OTG_STATE_B_SRP_INIT)
{
/* This section is executed in USB task context*/
OTG_Stop_Timer();
/* DP High off*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_DP_HIGH));
/* VBUS charge off */
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_CHG));
/* VBUS discharge off*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_DSCHG));
/* restore the interrupt masked during SRP */
DRV_WriteReg8(USB_INT_ENB, 0xff&(~(VUSB_INT_ENB_SOF|VUSB_INT_ENB_RESUME)));
}
else if(g_OtgInfo.b_srp_request==KAL_TRUE )
{
/* In case still measure B session end */
/* This section is executed in USB task context*/
OTG_Stop_Timer();
/* restore the interrupt masked during SRP */
DRV_WriteReg8(USB_INT_ENB, 0xff&(~(VUSB_INT_ENB_SOF|VUSB_INT_ENB_RESUME)));
g_OtgInfo.b_srp_stop_hdlr();
}
/* init device */
if(g_OtgInfo.device_up!=KAL_FALSE)
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.device_up, 0, 0);
g_OtgInfo.device_up = KAL_TRUE;
g_OtgInfo.device_up_hdlr();
//DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|(OTG_CTL_DP_HIGH | OTG_CTL_DM_LOW));
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW)));
g_OtgInfo.b_srp_request = KAL_FALSE;
g_OtgInfo.otg_state = OTG_STATE_B_PERIPHERAL;
}
static void OTG_Process_B_SRP_Init(void)
{
if(OTG_Is_B_Session_Valid()==KAL_TRUE)
g_OtgInfo.b_session_valid = KAL_TRUE;
/*
** When a B-device detects that the voltage on VBUS is greater than the
** B-Device Session Valid threshold (VSESS_VLD), then the B-device
** shall consider a session to be in progress. After the VBUS voltage
** crosses this threshold, the B-device shall assert either the D+ or
** D- data-line within 100 ms(TB_SVLD_BCON max).
*/
//if((DRV_Reg8(OTG_STATUS)&OTG_STATUS_SESS_VLD) && (g_OtgInfo.b_check_session==KAL_TRUE))
if((g_OtgInfo.b_session_valid==KAL_TRUE) && (g_OtgInfo.b_check_session==KAL_TRUE))
{
OTG_Process_B_Session_Valid();
}
else
{
/* check_srp_activity */
if(OTG_Is_TimerOut(OTG_TIMER_B_DATA_PLS)==KAL_TRUE)
{
OTG_Stop_Timer();
/* DP High off*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_DP_HIGH));
/* An A-device is only required to respond to one of the two
** SRP signaling methods. A B-device shall use both methods
** when initiating SRP to insure that the A-device responds.
*/
g_OtgInfo.b_check_session = KAL_FALSE;
/* VBUS charge */
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|OTG_CTL_VBUS_CHG);
/* Turn on the timer so as to keep VBUS pusling ON for 8 ms */
OTG_Start_Timer(OTG_TIMER_B_VBUS_PLS, TB_VBUS_PLS);
}
else if(OTG_Is_TimerOut(OTG_TIMER_B_VBUS_PLS)==KAL_TRUE)
{
OTG_Stop_Timer();
/* VBUS charge off */
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_CHG));
/* VBUS discharge */
//DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|OTG_CTL_VBUS_DSCHG);
OTG_Start_Timer(OTG_TIMER_B_VBUS_DSCHG, TB_VBUS_DSCHRG);
}
else if(OTG_Is_TimerOut(OTG_TIMER_B_VBUS_DSCHG)==KAL_TRUE)
{
OTG_Stop_Timer();
/* VBUS discharge off*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_DSCHG));
g_OtgInfo.b_check_session = KAL_TRUE;
/* If session is valid then proceed */
if(g_OtgInfo.b_session_valid==KAL_TRUE)
{
OTG_Process_B_Session_Valid();
}
else
{
/* start the fail timer*/
OTG_Start_Timer(OTG_TIMER_B_SRP_FAIL, TB_SRP_FAIL);
}
}
/*
** The error call back have the following requirement:
** After initiating SRP, the B-device is required to wait at least
** 5 seconds (TB_TB_SRP_FAIL min) for the A-device to respond,
** before informing the user that the communication attempt
** has failed.
**
*/
else if (OTG_Is_TimerOut(OTG_TIMER_B_SRP_FAIL) == KAL_TRUE)
{
OTG_Stop_Timer();
g_OtgInfo.b_srp_request = KAL_FALSE;
g_OtgInfo.otg_state = OTG_STATE_B_IDLE;
g_OtgInfo.b_srp_fail_hdlr();
OTG_Process_B_Idle();
/* restore the interrupt masked during SRP */
DRV_WriteReg8(USB_INT_ENB, 0xff&(~(VUSB_INT_ENB_SOF|VUSB_INT_ENB_RESUME)));
}
}
}
static void OTG_Process_B_Peripheral(void)
{
/* b_detect_a_suspend (SLEEP_INT) will be processed by the DEVICE ISR */
/*
** B-device detects that bus is idle for more than 3 ms
** (TB_AIDL_BDIS min) and begins HNP by turning off pull-up on D+.
** This allows the bus to discharge to the SE0 state.
** The following will be done when this happens:
**
** disconnect its pull up
** allow time for the data line to discharge
** check if the A-device has connected its pull up
*/
if((g_OtgInfo.b_hnp_enable==KAL_TRUE) && (g_OtgInfo.b_detect_a_suspend==KAL_TRUE) &&
(OTG_Is_TimerActive()==KAL_FALSE))
{
OTG_Start_Timer(OTG_TIMER_A_BUS_SUSPEND, TB_A_SUSPEND);
}
else if(OTG_Is_TimerOut(OTG_TIMER_A_BUS_SUSPEND)==KAL_TRUE)
{
OTG_Stop_Timer();
g_OtgInfo.b_detect_a_suspend = KAL_FALSE;
/* start up host */
if((g_OtgInfo.device_up!=KAL_TRUE) || (g_OtgInfo.host_up!=KAL_FALSE))
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.device_up, (kal_uint32)g_OtgInfo.host_up, 0);
g_OtgInfo.device_up = KAL_FALSE;
g_OtgInfo.device_down_hdlr();
g_OtgInfo.host_up = KAL_TRUE;
g_OtgInfo.host_up_hdlr();
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|(OTG_CTL_DP_LOW | OTG_CTL_DM_LOW));
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DP_HIGH | OTG_CTL_DM_HIGH)));
g_OtgInfo.otg_state = OTG_STATE_B_WAIT_ACON;
/* start timer to wait A connect*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -