📄 usb_hwinterface_layer.c
字号:
/*================================================================================================== Module Name: usb_hwinterface_layer.c General Description: This file contains all API's and functions of USB IP Layer . ====================================================================================================Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.This file contains copyrighted material. Use of this file isrestricted by the provisions of a Freescale Software LicenseAgreement, which has either been electronically accepted byyou or has been expressly executed between the parties. Revision History:==================================================================================================== INCLUDE FILES==================================================================================================*/#include "su_basictypes.h"#include <usb_common.h>#include <usb_hwinterface_layer.h>#include <usb_ipl_tl_extern.h>#include <usb_ipl_al_extern.h>#include <usb_global.h>/*================================================================================================== GLOBAL VARIABLES==================================================================================================*//*================================================================================================== LOCAL CONSTANTS==================================================================================================*//*================================================================================================= LOCAL FUNCTION PROTOTYPES==================================================================================================*/static void ipl_clear_dqh(void);static void ipl_setup_qhead(struct dqh_t* );static void ipl_setup_transfer_desc(struct dtd_t* );static void ipl_device_only_mode(void);static U32 ipl_get_dqh(U8, U8);static U32 ipl_get_dtd(U8, U8 ) ;static void copy_to_buffer(U8* , U32* , U32 );static void copy_from_buffer(U32*, U8*, U32);static U32 get_rxd_buffer(void);static void free_buffer(U32 );static U32 alloc_buffer(void);static void ipl_init_hw(void);/*================================================================================================== LOCAL VARIABLES==================================================================================================*/static U32 g_buffer_address_base; /* Base address of the buffer allocated to IP Layer */static U32 g_buffer_length; /* length of the buffer */static buffer_map_t g_buffer_map; /* Buffer information used for data transfer */static U8 g_in_endpoint; /* Number of Endpoint configured as IN */static U8 g_out_endpoint; /* Number of Endpoint configured as OUT*/static U8 g_max_ep_supported; /* Number of Endpoints configured in system *//*================================================================================================== LOCAL MACROS==================================================================================================*//*================================================================================================== LOCAL FUNCTIONS==================================================================================================*//*==================================================================================================FUNCTION: ipl_init_hwDESCRIPTION: This Function Initialise the USB Core . ARGUMENTS PASSED: None RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/void ipl_init_hw(void){ struct dqh_t qhead; U32 total_bytes; /* Init to Device mode only */ ipl_device_only_mode(); /* Clear the dQH before initialized */ ipl_clear_dqh(); /****************************************************************************** / ================= / dQH0 for EP0OUT / ================= / Initialize device queue heads in system memory / 8 bytes for the 1st setup packet */ total_bytes = 0x8; qhead.dqh_base = ipl_get_dqh(EP0,OUT); qhead.zlt = ZLT_DISABLE; qhead.mps = MPS_64; qhead.ios = IOS_SET; qhead.next_link_ptr = ipl_get_dtd(EP0,OUT); qhead.terminate = NOT_TERMINATE; qhead.total_bytes = total_bytes; qhead.ioc = IOC_SET; qhead.status = NO_STATUS; qhead.buffer_ptr0 = 0; qhead.current_offset = 0; qhead.buffer_ptr1 = 0; qhead.buffer_ptr2 = 0; qhead.buffer_ptr3 = 0; qhead.buffer_ptr4 = 0; /* Set Device Queue Head */ ipl_setup_qhead(&qhead); /* ================== END of dQH0 setup ====================*/ /*================= dQH1 for EP0IN ================= */ total_bytes = 0x8; qhead.dqh_base = ipl_get_dqh(EP0,IN); qhead.zlt = ZLT_DISABLE; qhead.mps = MPS_64; qhead.ios = IOS_SET; qhead.next_link_ptr = ipl_get_dtd(EP0,IN); qhead.terminate = TERMINATE; qhead.total_bytes = total_bytes; qhead.ioc = IOC_SET; qhead.status = NO_STATUS; qhead.buffer_ptr0 = g_buffer_map.ep0_buffer_addrs; qhead.current_offset = (g_buffer_map.ep0_buffer_addrs & 0xFFF); qhead.buffer_ptr1 = 0; qhead.buffer_ptr2 = 0; qhead.buffer_ptr3 = 0; qhead.buffer_ptr4 = 0; /* Set Device Queue Head */ ipl_setup_qhead(&qhead); /* ================== / END of dQH1 setup / ================*/ /* Configure ENDPOINTLISTADDR Pointer */ *(VP_U32)USB_OTG_ENDPOINTLISTADDR = g_buffer_map.ep_dqh_base_addrs; /* Set OTG termination, controls the pulldown on DM */ *(VP_U32)USB_OTG_OTGSC |= BIT3; /* Disable Setup Lockout by writing '1' to SLOM in USBMODE */ *(VP_U32)USB_OTG_USBMODE |= BIT3; /* Set Run/Stop bit to Run Mode */ *(VP_U32)USB_OTG_USBCMD |= BIT0;}/*==================================================================================================FUNCTION: ipl_initDESCRIPTION: This function does the IP Layer InitialisationARGUMENTS PASSED: usb_plat_config_data_t* config_data_ptrRETURN VALUE: None IMPORTANT NOTES: There are two buffers each of size 0x200 ( 512 ) will be used for bulk data transfer. So total 0x400(1k) will be used for bulk data transfer and this will be the last 1k of the allocated buffer. There is 0x40 ( 64 ) size of the buffer will be used for data transfer over control endpoint ( EP0 ) Rest of the buffer area will be used for endpoint data structires ( device qhead and device transfer descriptor ). ==================================================================================================*/voidipl_init(usb_plat_config_data_t* config_data_ptr){ U32 temp; /* Base address of the buffer allocated to IP Layer */ g_buffer_address_base = config_data_ptr->buffer_address; /* length of the buffer */ g_buffer_length = config_data_ptr->buffer_size; /* Maximum Number of EPs to be confiured */ g_max_ep_supported = (( g_buffer_length - TOTAL_DATA_BUFFER_SIZE)/(BUFFER_USED_PER_EP)); /* Base of queue Head Pointer */ g_buffer_map.ep_dqh_base_addrs = g_buffer_address_base; /* Total size of qhead */ temp = (SIZE_OF_QHD * (g_max_ep_supported * 2)); /* Base Address of device transfer descriptor */ g_buffer_map.ep_dtd_base_addrs = (g_buffer_map.ep_dqh_base_addrs + temp); /* Total size of transfer descriptor */ temp = ((dTD_SIZE_EPIN * g_max_ep_supported) + (dTD_SIZE_EPOUT * g_max_ep_supported )); /* Base Address of EP0 Buffer */ g_buffer_map.ep0_buffer_addrs = (g_buffer_map.ep_dtd_base_addrs + temp ); /* transfer buffer 1 */ g_buffer_map.buffer1_address=(g_buffer_address_base + g_buffer_length -(BULK_BUFFER_SIZE*NUM_OF_BULK_BUFFER)); g_buffer_map.buffer1_status = BUFFER_FREE; /* transfer buffer 2 */ g_buffer_map.buffer2_address = g_buffer_map.buffer1_address + BULK_BUFFER_SIZE; g_buffer_map.buffer2_status = BUFFER_FREE; ipl_init_hw();}/*==================================================================================================FUNCTION: ipl_check_bus_resetDESCRIPTION: This function check if reset event is received on USB bus.ARGUMENTS PASSED: None RETURN VALUE: BOOL status TRUE If reset received. FALSE If reset not received. IMPORTANT NOTES: None ==================================================================================================*/BOOLipl_check_bus_reset(void){ BOOL status=FALSE; if ((*(VP_U32)USB_OTG_USBSTS) & BIT6) { status=TRUE; }return status;}/*==================================================================================================FUNCTION: ipl_check_setup_tokenDESCRIPTION: This function check if Setup Token is received on USB bus.ARGUMENTS PASSED: None RETURN VALUE: U8 status TRUE If Setup Token received. FALSE If Setup Token not received. IMPORTANT NOTES: None==================================================================================================*/BOOLipl_check_setup_token(void){ BOOL status = FALSE; if ((*(VP_U32)USB_OTG_ENDPTSETUPSTAT) & BIT0) { status= TRUE; }return status;}/*==================================================================================================FUNCTION: ipl_is_interface_high_speedDESCRIPTION: This function return the speed at which the selected interface working.ARGUMENTS PASSED: None RETURN VALUE: U8 interface_speed 0 If interface is working at FS. 1 If interface is working at HS. IMPORTANT NOTES: Note : Low Speed is not supported.==================================================================================================*/BOOLipl_is_interface_high_speed(void){ BOOL speed = FALSE; /* Full Speed by default */#ifndef SIMULATOR_TESTING while(!((*(VP_U32)USB_OTG_USBSTS) & USB_OTG_PORT_OPERATIONAL ));#endif if(((*(VP_U32)USB_OTG_PORTSC1) & USB_OTG_INF_SPEED_MASK) == USB_OTG_INF_SPEED_HS) { speed = TRUE; }return speed;}/*==================================================================================================FUNCTION: ipl_handle_bus_resetDESCRIPTION: This function Handle the reset event from USB HostARGUMENTS PASSED: None RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/voidipl_handle_bus_reset(void){ U32 temp,total_bytes; struct dqh_t qhead; *(VP_U32)USB_OTG_USBCMD &= ~BIT0; (*(VP_U32)USB_OTG_USBSTS) &= BIT6; /*Reading and writing back the ENDPTSETUPSTAT register clears the setup token semaphores */ temp = (*(VP_U32)USB_OTG_ENDPTSETUPSTAT); (*(VP_U32)USB_OTG_ENDPTSETUPSTAT) = temp; /*Reading and writing back the ENDPTCOMPLETE register clears the endpoint complete status bits */ temp = (*(VP_U32)USB_OTG_ENDPTCOMPLETE); (*(VP_U32)USB_OTG_ENDPTCOMPLETE) = temp; while((*(VP_U32)USB_OTG_ENDPTPRIME)); (*(VP_U32)USB_OTG_ENDPTFLUSH) = 0xFFFFFFFF; ipl_clear_dqh(); /* Initialize device queue heads in system memory for EP0OUT */ total_bytes = 0x8; qhead.dqh_base = ipl_get_dqh(EP0,OUT); qhead.zlt = ZLT_DISABLE; qhead.mps = MPS_64; qhead.ios = IOS_SET; qhead.next_link_ptr = 0; qhead.terminate = TERMINATE; qhead.total_bytes = total_bytes; qhead.ioc = IOC_SET; qhead.status = NO_STATUS; qhead.buffer_ptr0 = 0; qhead.current_offset = 0; qhead.buffer_ptr1 = 0; qhead.buffer_ptr2 = 0; qhead.buffer_ptr3 = 0; qhead.buffer_ptr4 = 0; ipl_setup_qhead(&qhead); /* Initialize device queue heads in system memory for EP0IN */ qhead.dqh_base = ipl_get_dqh(EP0,IN); qhead.zlt = ZLT_DISABLE; qhead.mps = MPS_64; qhead.ios = IOS_SET; qhead.next_link_ptr = 0; qhead.terminate = TERMINATE; qhead.total_bytes = 0; qhead.ioc = IOC_SET; qhead.status = NO_STATUS; qhead.buffer_ptr0 = 0; qhead.current_offset = 0; qhead.buffer_ptr1 = 0; qhead.buffer_ptr2 = 0; qhead.buffer_ptr3 = 0; qhead.buffer_ptr4 = 0; ipl_setup_qhead(&qhead); *(VP_U32)USB_OTG_ENDPOINTLISTADDR = g_buffer_map.ep_dqh_base_addrs; *(VP_U32)USB_OTG_USBCMD |= BIT0;}/*==================================================================================================FUNCTION: ipl_set_device_addressDESCRIPTION: This function set the Device AddressARGUMENTS PASSED: U8 Address : Address of Device to be Set. RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/voidipl_set_device_address(U16 Address){ /* set the USB Device address */ *(VP_U32)USB_OTG_DEVICEADDR = ((U32)Address & 0x7F) << 25;}/*==================================================================================================FUNCTION: ipl_send_stall_handshakeDESCRIPTION: This function Send/Receive the STALL HANDSHAKE to USB HostARGUMENTS PASSED: U8 endpoint - Endpoint Number . U8 direction - IN/OUT : direction of EndPoint. RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/voidipl_send_stall_handshake(U8 endpoint , U8 direction){ if( direction == OUT ) { *(VP_U32)( USB_OTG_ENDPTCTRL0 + (4*endpoint) ) |= STALL_RX; } else { *(VP_U32)( USB_OTG_ENDPTCTRL0 + (4*endpoint) ) |= STALL_TX; }}/*==================================================================================================FUNCTION: ipl_set_configurationDESCRIPTION: This function Handle the SET CONFIGRATION Request.ARGUMENTS PASSED: usb_end_pt_info_t* config_data;RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/voidipl_set_configuration(usb_end_pt_info_t* config_data){ struct dtd_t td; U32 total_bytes = 0x0; U32 buffer_addrs_page0 = 0; U32 dqh_address = 0; U32 dtd_address = 0; U8 endpt_num,direction; struct dqh_t qhead; /* get endpoint number to be configured and its direction */ endpt_num= config_data->end_pt_no; direction= config_data->direction; /* Check if the endpoint number and direction is withing the permitted range or not */ if (( endpt_num != EP0 ) && (endpt_num <= ( g_max_ep_supported - 1)) && ( direction == OUT || direction == IN)) { /* get the device q head and deice TD */ dqh_address = ipl_get_dqh(endpt_num,direction); dtd_address = ipl_get_dtd(endpt_num,direction); if ( direction == OUT ) { total_bytes = BULK_BUFFER_SIZE ; qhead.dqh_base = dqh_address; qhead.zlt = ZLT_DISABLE; qhead.mps = config_data->max_pkt_size; qhead.ios = IOS_SET; qhead.next_link_ptr = dtd_address ; qhead.terminate = TERMINATE; qhead.total_bytes = total_bytes; qhead.ioc = IOC_SET; qhead.status = NO_STATUS; qhead.buffer_ptr0 = 0; qhead.current_offset = 0; qhead.buffer_ptr1 = 0; qhead.buffer_ptr2 = 0; qhead.buffer_ptr3 = 0; qhead.buffer_ptr4 = 0; ipl_setup_qhead(&qhead); /* Endpoint 1 : MPS = 64, OUT (Rx endpoint) */ *(VP_U32)(USB_OTG_ENDPTCTRL0 + (0x4*endpt_num))= 0x00080048; /* Enable EP1 OUT */ *(VP_U32)(USB_OTG_ENDPTCTRL0 + ( 0x4 * endpt_num)) |= EPOUT_ENABLE; /* allocate buffer for receiving data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -