/****************************************************************************** * Software License Agreement * * Copyright (c) 2015-2016, Infineon Technologies AG * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the copyright holders nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * To improve the quality of the software, users are encouraged to share * modifications, enhancements or bug fixes with Infineon Technologies AG * (dave@infineon.com). * *****************************************************************************/ /** * @file main.c * @date 30 July, 2016 * @version 1.0.0 * * @brief Implements an example of USB host CDC ACM class
* * Detailed description of file
* The file implements the main function where it initializes USB peripheral, UART peripheral, * LUFA stack and executes the device enumeration and character echo application. * * History * * 01 Jul 2014 Version 1.0.0
* Initial version */ #include //Declarations from DAVE Code Generation (includes SFR declaration) #include "xmc_usbh.h" #include "USB/GLUE/USB_Glue.h" #include "USBH_VCOM/USBVCH.h" #include "uart.h" void ClockSetup(void); /*Port interrupt callback function*/ void CDC_USB_PortCb(uint8_t port, uint32_t event); /*BULK OUT and NOTIFICATION pipe transfer completion handler*/ void CDC_TransferCompletion_Handle(void); extern bool BULK_OUT_TransferCompleted; extern bool NOTIFICATION_TransferCompleted; extern uint8_t SerialState[SERIAL_STATE_SIZE]; extern uint8_t UART_RX_Buffer[UART_RX_BUFF_SIZE]; /*USB receive buffer*/ #define USB_RX_BUFFER_SIZE 80 uint8_t RxBuffer[USB_RX_BUFFER_SIZE]; #if (defined (XMC4500_E144x1024) || defined (XMC4500_F144x1024) || defined (XMC4500_F100x1024) || \ defined (XMC4500_F144x768) || defined (XMC4500_F100x768) || defined (XMC4502_F100x768) || \ defined (XMC4504_F100x512) || defined (XMC4504_F144x512)) /* Data structure for initializing the clock functional block */ const XMC_SCU_CLOCK_CONFIG_t CLOCK_XMC4_0_CONFIG = { .syspll_config.n_div = 80U, .syspll_config.p_div = 2U, .syspll_config.k_div = 4U, .syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL, .syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP, .enable_oschp = true, .enable_osculp = false, .calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY, .fstdby_clksrc = XMC_SCU_HIB_STDBYCLKSRC_OSI, .fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL, .fsys_clkdiv = 1U, .fcpu_clkdiv = 1U, .fperipheral_clkdiv = 1U }; #else #error "Clock configuration has to be updated for the device selected. You may use CLOCK_XMC4 APP to derive the required configuration." #endif /*Callback functions to be called from USB glue layer*/ USBH_GLUE_APP_IF_t USBVCH_CB = { .GetBytesInPipe = USBVCH_Pipe_BytesInPipe, .GetReadByte = USBVCH_Pipe_Read_8, .IsINReceived = USBVCH_Pipe_IsINReceived, .PipeEventHandler = USBH_VCOM_Rx_Data_Handler, .PortEventHandler = CDC_USB_PortCb }; /*Flag to identify remote wakeup event*/ volatile uint32_t USBH_RemoteWkUp_Detected = 0U; /** * @brief main() - Application entry point * * Details of function
* This routine is the application entry point. It is invoked by the device startup code. It is responsible for * invoking the APP initialization dispatcher routine - DAVE_Init() and hosting the place-holder for user application * code. */ int main(void) { uint8_t USBHostState; int8_t ReceivedByte; uint8_t *RxPtr; uint32_t Rxlen; uint32_t uart_data_count; /*Configure USB and CPU clocks*/ ClockSetup(); /*Initialize UART channel*/ UART_init(); /*Select VBUS pin as P3.2*/ XMC_USBH_Select_VBUS(XMC_GPIO_PORT3, 2U); /* Initializes the USB host driver. */ USB_Init_Host(&USBVCH_CB); /*LED pin to indicate USB status*/ XMC_GPIO_SetMode(XMC_GPIO_PORT3, 9, XMC_GPIO_MODE_OUTPUT_PUSH_PULL); XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9); /* Placeholder for user application code. The while loop below can be replaced with user application code. */ while(1U) { /*Check if remote wakeup is detected and clear the resume * bit after 20ms delay*/ if (USBH_RemoteWkUp_Detected) { (void)XMC_USBH_osDelay(20U); XMC_USBH_TurnOffResumeBit(); USBH_RemoteWkUp_Detected = 0; } USB_GetHostState(&USBHostState); /* Check whether device is in configured status */ if(USBHostState == HOST_STATE_Configured) { XMC_GPIO_SetOutputLow(XMC_GPIO_PORT3, 9); /*Check if any data received on UART channel and forward * the same to USB device*/ uart_data_count = UART_CheckRxData(); /*Send received data to USB device*/ if(uart_data_count > 0) { USBVCH_SendData(UART_RX_Buffer, uart_data_count, NULL); } /*Check if anything received on USB channel and forward the smae * to UART channel*/ Rxlen = 0; RxPtr = RxBuffer; do{ ReceivedByte = -1; USBVCH_ReceiveByte(&ReceivedByte); if(ReceivedByte != -1) { *RxPtr = ReceivedByte; Rxlen++; RxPtr++; if(Rxlen == USB_RX_BUFFER_SIZE) { break; } } }while(ReceivedByte != -1); /*Transmit the received data to UART channel*/ UART_Transmit(RxBuffer, Rxlen); } USBVCH_Process(); /* Keep calling this function for USB management */ USB_USBTask(); /*Handle transfer completion on BULK OUT and NOTIFICATION*/ CDC_TransferCompletion_Handle(); } } /*Callback function executed on port interrupt*/ void CDC_USB_PortCb(uint8_t port, uint32_t event) { if(event & XMC_USBH_EVENT_DISCONNECT) { XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9); Driver_USBH0.PipeDelete(USBHost_Pipe_State[0].pipe_handle); Driver_USBH0.PipeDelete(USBHost_Pipe_State[1].pipe_handle); Driver_USBH0.PipeDelete(USBHost_Pipe_State[2].pipe_handle); Driver_USBH0.PipeDelete(USBHost_Pipe_State[3].pipe_handle); /*Reset the data handling indices*/ USBH_VCOM_RX_cur_index = 0; USBH_VCOM_RX_prev_index = 0; } if(event & XMC_USBH_EVENT_REMOTE_WAKEUP) { /*This flag is set to remember the occurrence of remote wakeup event and * to return from ISR immediately. This helps to time a 20ms delay in * the context of the application main loop rather than inside the ISR context. * The reason for this is that the example uses a timer interrupt whose priority is * lower than the USB interrupt and therefore would result in a deadlock.*/ USBH_RemoteWkUp_Detected = 1; } } /*Function handles BULK OUT and NOTIFICATION pipe transfer completion*/ void CDC_TransferCompletion_Handle(void) { if(NOTIFICATION_TransferCompleted) { /*Notification received from device. * Data is available in the buffer SerialState[]*/ } if(BULK_OUT_TransferCompleted) { /*Application code to be executed when BULK OUT transfer completes*/ } } /*Clock configuration*/ void ClockSetup(void) { /* Initialize the SCU clock */ XMC_SCU_CLOCK_Init(&CLOCK_XMC4_0_CONFIG); /* RTC source clock */ XMC_SCU_HIB_SetRtcClockSource(XMC_SCU_HIB_RTCCLKSRC_OSI); /*CLOCK_XMC4_USBCLK_ENABLED*/ /* USB/SDMMC source clock */ XMC_SCU_CLOCK_SetUsbClockSource(XMC_SCU_CLOCK_USBCLKSRC_USBPLL); /* USB/SDMMC divider setting */ XMC_SCU_CLOCK_SetUsbClockDivider(4U); /* Start USB PLL */ XMC_SCU_CLOCK_StartUsbPll(1U, 32U); }