/* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2008, Atmel Corporation * * 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 disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL 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. * ---------------------------------------------------------------------------- */ //----------------------------------------------------------------------------- /// \dir "USB CDC serial converter" /// /// !!!Purpose /// /// The USB CDC Serial Project will help you to get familiar with the /// USB Device Port(UDP) and USART interface on AT91SAM microcontrollers. Also /// it can help you to be familiar with the USB Framework that is used for /// rapid development of USB-compliant class drivers such as USB Communication /// Device class (CDC). /// /// You can find following information depends on your needs: /// - Sample usage of USB CDC driver and USART driver. /// - USB CDC driver development based on the AT91 USB Framework. /// - USB enumerate sequence, the standard and class-specific descriptors and /// requests handling. /// - The initialize sequence and usage of UDP interface. /// - The initialize sequence and usage of USART interface with PDC. /// /// !See /// - usart: USART interface driver /// - tc: TIMER/COUNTER interface driver /// - usb: USB Framework, USB CDC driver and UDP interface driver /// - "AT91 USB device framework" /// - "USBD API" /// - "cdc-serial" /// - "USB CDC Serial Device" /// - "USB CDC Serial Host Driver" /// /// !!!Requirements /// /// This package can be used with all Atmel evaluation kits that have both /// UDP and USART interface. /// /// The current supported board list: /// - at91sam7s-ek (exclude at91sam7s32) /// - at91sam7x-ek /// - at91sam7xc-ek /// - at91sam7a3-ek /// - at91sam7se-ek /// - at91sam9260-ek /// - at91sam9263-ek /// /// !!!Description /// /// When an EK running this program connected to a host (PC for example), with /// USB cable, the EK appears as a Seriao COM port for the host, after driver /// installation with the offered 6119.inf. Then the host can send or receive /// data through the port with host software. The data stream from the host is /// then sent to the EK, and forward to USART port of AT91SAM chips. The USART /// port of the EK is monitored by the timer and the incoming data will be sent /// to the host. /// /// !!!Usage /// /// -# Build the program and download it inside the evaluation board. Please /// refer to the /// /// SAM-BA User Guide, the /// /// GNU-Based Software Development application note or to the /// /// IAR EWARM User Guide, depending on your chosen solution. /// -# On the computer, open and configure a terminal application /// (e.g. HyperTerminal on Microsoft Windows) with these settings: /// - 115200 bauds /// - 8 bits of data /// - No parity /// - 1 stop bit /// - No flow control /// -# Start the application. /// -# In the terminal window, the following text should appear: /// \code /// -- USB Device CDC Serial Project xxx -- /// -- AT91xxxxxx-xx /// -- Compiled: xxx xx xxxx xx:xx:xx -- /// \endcode /// -# When connecting USB cable to windows, the LED blinks, and the host /// reports a new USB %device attachment (if it's the first time you connect /// an %audio speaker demo board to your host). You can use the inf file /// at91lib\\usb\\device\\cdc-serial\\drv\\6119.inf to install the serial /// port. Then new "AT91 USB to Serial Converter (COMx)" appears in the /// hardware %device list. /// -# You can run hyperterminal to send data to the port. And it can be seen /// at the other hyperterminal connected to the USART port of the EK. /// //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- /// \unit /// /// !Purpose /// /// This file contains all the specific code for the /// usb-device-cdc-serial-project /// /// !Contents /// /// The code can be roughly broken down as follows: /// - Configuration functions /// - VBus_Configure /// - PIO & Timer configurations in start of main /// - Interrupt handlers /// - ISR_Vbus /// - ISR_Timer0 /// - ISR_Usart0 /// - Callback functions /// - UsbDataReceived /// - The main function, which implements the program behavior /// /// Please refer to the list of functions in the #Overview# tab of this unit /// for more detailed information. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Headers //------------------------------------------------------------------------------ #include #include #include #include #include #include #include #include #include #include #include //------------------------------------------------------------------------------ // Definitions //------------------------------------------------------------------------------ #ifndef AT91C_ID_TC0 #define AT91C_ID_TC0 AT91C_ID_TC #endif /// Size in bytes of the buffer used for reading data from the USB & USART #define DATABUFFERSIZE \ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN) /// Use for power management #define STATE_IDLE 0 /// The USB device is in suspend state #define STATE_SUSPEND 4 /// The USB device is in resume state #define STATE_RESUME 5 //------------------------------------------------------------------------------ // Internal variables //------------------------------------------------------------------------------ /// State of USB, for suspend and resume unsigned char USBState = STATE_IDLE; /// List of pins that must be configured for use by the application. static const Pin pins[] = {PIN_USART1_TXD, PIN_USART1_RXD}; /// Double-buffer for storing incoming USART data. static unsigned char usartBuffers[2][DATABUFFERSIZE]; /// Current USART buffer index. static unsigned char usartCurrentBuffer = 0; /// Buffer for storing incoming USB data. static unsigned char usbBuffer[DATABUFFERSIZE]; //------------------------------------------------------------------------------ // VBus monitoring (optional) //------------------------------------------------------------------------------ #if defined(PIN_USB_VBUS) #define VBUS_CONFIGURE() VBus_Configure() /// VBus pin instance. static const Pin pinVbus = PIN_USB_VBUS; //------------------------------------------------------------------------------ /// Handles interrupts coming from PIO controllers. //------------------------------------------------------------------------------ static void ISR_Vbus(const Pin *pPin) { // Check current level on VBus if (PIO_Get(&pinVbus)) { TRACE_INFO("VBUS conn\n\r"); USBD_Connect(); } else { TRACE_INFO("VBUS discon\n\r"); USBD_Disconnect(); } } //------------------------------------------------------------------------------ /// Configures the VBus pin to trigger an interrupt when the level on that pin /// changes. //------------------------------------------------------------------------------ static void VBus_Configure( void ) { TRACE_INFO("VBus configuration\n\r"); // Configure PIO PIO_Configure(&pinVbus, 1); PIO_ConfigureIt(&pinVbus, ISR_Vbus); PIO_EnableIt(&pinVbus); // Check current level on VBus if (PIO_Get(&pinVbus)) { // if VBUS present, force the connect TRACE_INFO("VBUS conn\n\r"); USBD_Connect(); } else { USBD_Disconnect(); } } #else #define VBUS_CONFIGURE() USBD_Connect() #endif //#if defined(PIN_USB_VBUS) #if defined (CP15_PRESENT) //------------------------------------------------------------------------------ /// Put the CPU in 32kHz, disable PLL, main oscillator /// Put voltage regulator in standby mode //------------------------------------------------------------------------------ void LowPowerMode(void) { PMC_CPUInIdleMode(); } //------------------------------------------------------------------------------ /// Put voltage regulator in normal mode /// Return the CPU to normal speed 48MHz, enable PLL, main oscillator //------------------------------------------------------------------------------ void NormalPowerMode(void) { } #elif defined(at91sam7a3) //------------------------------------------------------------------------------ /// Put the CPU in 32kHz, disable PLL, main oscillator //------------------------------------------------------------------------------ void LowPowerMode(void) { // MCK=48MHz to MCK=32kHz // MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=SLCK : then change prescaler AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // disable PLL AT91C_BASE_PMC->PMC_PLLR = 0; // Disable Main Oscillator AT91C_BASE_PMC->PMC_MOR = 0; PMC_DisableProcessorClock(); } //------------------------------------------------------------------------------ /// Return the CPU to normal speed 48MHz, enable PLL, main oscillator //------------------------------------------------------------------------------ void NormalPowerMode(void) { // MCK=32kHz to MCK=48MHz // enable Main Oscillator AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN )); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) ); // enable PLL@96MHz AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) | (AT91C_CKGR_PLLCOUNT & (28<<8)) | (AT91C_CKGR_MUL & (0x48<<16))); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) ); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; // MCK=SLCK/2 : change prescaler first AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=PLLCK/2 : then change source AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); } #elif defined (at91sam7se) //------------------------------------------------------------------------------ /// Put the CPU in 32kHz, disable PLL, main oscillator /// Put voltage regulator in standby mode //------------------------------------------------------------------------------ void LowPowerMode(void) { // MCK=48MHz to MCK=32kHz // MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=SLCK : then change prescaler AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // disable PLL AT91C_BASE_PMC->PMC_PLLR = 0; // Disable Main Oscillator AT91C_BASE_PMC->PMC_MOR = 0; // Voltage regulator in standby mode : Enable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY; PMC_DisableProcessorClock(); } //------------------------------------------------------------------------------ /// Put voltage regulator in normal mode /// Return the CPU to normal speed 48MHz, enable PLL, main oscillator //------------------------------------------------------------------------------ void NormalPowerMode(void) { // Voltage regulator in normal mode : Disable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY; // MCK=32kHz to MCK=48MHz // enable Main Oscillator AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN )); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) ); // enable PLL@96MHz AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) | (AT91C_CKGR_PLLCOUNT & (28<<8)) | (AT91C_CKGR_MUL & (0x48<<16))); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) ); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; // MCK=SLCK/2 : change prescaler first AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=PLLCK/2 : then change source AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); } #elif defined (at91sam7s) //------------------------------------------------------------------------------ /// Put the CPU in 32kHz, disable PLL, main oscillator /// Put voltage regulator in standby mode //------------------------------------------------------------------------------ void LowPowerMode(void) { // MCK=48MHz to MCK=32kHz // MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=SLCK : then change prescaler AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // disable PLL AT91C_BASE_PMC->PMC_PLLR = 0; // Disable Main Oscillator AT91C_BASE_PMC->PMC_MOR = 0; // Voltage regulator in standby mode : Enable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY; PMC_DisableProcessorClock(); } //------------------------------------------------------------------------------ /// Put voltage regulator in normal mode /// Return the CPU to normal speed 48MHz, enable PLL, main oscillator //------------------------------------------------------------------------------ void NormalPowerMode(void) { // Voltage regulator in normal mode : Disable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY; // MCK=32kHz to MCK=48MHz // enable Main Oscillator AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN )); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) ); // enable PLL@96MHz AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) | (AT91C_CKGR_PLLCOUNT & (28<<8)) | (AT91C_CKGR_MUL & (0x48<<16))); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) ); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; // MCK=SLCK/2 : change prescaler first AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=PLLCK/2 : then change source AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); } #elif defined (at91sam7x) || defined (at91sam7xc) //------------------------------------------------------------------------------ /// Put the CPU in 32kHz, disable PLL, main oscillator /// Put voltage regulator in standby mode //------------------------------------------------------------------------------ void LowPowerMode(void) { // MCK=48MHz to MCK=32kHz // MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=SLCK : then change prescaler AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // disable PLL AT91C_BASE_PMC->PMC_PLLR = 0; // Disable Main Oscillator AT91C_BASE_PMC->PMC_MOR = 0; // Voltage regulator in standby mode : Enable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY; PMC_DisableProcessorClock(); } //------------------------------------------------------------------------------ /// Put voltage regulator in normal mode /// Return the CPU to normal speed 48MHz, enable PLL, main oscillator //------------------------------------------------------------------------------ void NormalPowerMode(void) { // Voltage regulator in normal mode : Disable VREG Low Power Mode AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY; // MCK=32kHz to MCK=48MHz // enable Main Oscillator AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN )); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) ); // enable PLL@96MHz AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) | (AT91C_CKGR_PLLCOUNT & (28<<8)) | (AT91C_CKGR_MUL & (0x48<<16))); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) ); while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; // MCK=SLCK/2 : change prescaler first AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); // MCK=PLLCK/2 : then change source AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ; while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) ); } #endif //------------------------------------------------------------------------------ // Internal functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Handles interrupts coming from Timer #0. //------------------------------------------------------------------------------ static void ISR_Timer0() { unsigned char size; unsigned int status = AT91C_BASE_TC0->TC_SR; if ((status & AT91C_TC_CPCS) != 0) { // Flush PDC buffer size = DATABUFFERSIZE - AT91C_BASE_US1->US_RCR; if (size == 0) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; return; } AT91C_BASE_US1->US_RCR = 0; // Send current buffer through the USB while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer], size, 0, 0) != USBD_STATUS_SUCCESS); // Restart read on buffer USART_ReadBuffer(AT91C_BASE_US1, usartBuffers[usartCurrentBuffer], DATABUFFERSIZE); usartCurrentBuffer = 1 - usartCurrentBuffer; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; } } //------------------------------------------------------------------------------ // Callbacks re-implementation //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Invoked when the USB device leaves the Suspended state. By default, /// configures the LEDs. //------------------------------------------------------------------------------ void USBDCallbacks_Resumed(void) { // Initialize LEDs LED_Configure(USBD_LEDPOWER); LED_Set(USBD_LEDPOWER); LED_Configure(USBD_LEDUSB); LED_Clear(USBD_LEDUSB); USBState = STATE_RESUME; } //------------------------------------------------------------------------------ /// Invoked when the USB device gets suspended. By default, turns off all LEDs. //------------------------------------------------------------------------------ void USBDCallbacks_Suspended(void) { // Turn off LEDs LED_Clear(USBD_LEDPOWER); LED_Clear(USBD_LEDUSB); USBState = STATE_SUSPEND; } //------------------------------------------------------------------------------ /// Callback invoked when data has been received on the USB. //------------------------------------------------------------------------------ static void UsbDataReceived(unsigned int unused, unsigned char status, unsigned int received, unsigned int remaining) { // Check that data has been received successfully if (status == USBD_STATUS_SUCCESS) { // Send data through USART while (!USART_WriteBuffer(AT91C_BASE_US1, usbBuffer, received)); AT91C_BASE_US1->US_IER = AT91C_US_TXBUFE; // Check if bytes have been discarded if ((received == DATABUFFERSIZE) && (remaining > 0)) { TRACE_WARNING( "UsbDataReceived: %u bytes discarded\n\r", remaining); } } else { TRACE_WARNING( "UsbDataReceived: Transfer error\n\r"); } } //------------------------------------------------------------------------------ /// Handles interrupts coming from USART #1. //------------------------------------------------------------------------------ static void ISR_Usart0() { unsigned int status = AT91C_BASE_US1->US_CSR; unsigned short serialState; // If USB device is not configured, do nothing if (USBD_GetState() != USBD_STATE_CONFIGURED) { AT91C_BASE_US1->US_IDR = 0xFFFFFFFF; return; } // Buffer has been read successfully if ((status & AT91C_US_ENDRX) != 0) { // Disable timer AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // Send buffer through the USB while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer], DATABUFFERSIZE, 0, 0) != USBD_STATUS_SUCCESS); // Restart read on buffer USART_ReadBuffer(AT91C_BASE_US1, usartBuffers[usartCurrentBuffer], DATABUFFERSIZE); usartCurrentBuffer = 1 - usartCurrentBuffer; // Restart timer AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; } // Buffer has been sent if ((status & AT91C_US_TXBUFE) != 0) { // Restart USB read CDCDSerialDriver_Read(usbBuffer, DATABUFFERSIZE, (TransferCallback) UsbDataReceived, 0); AT91C_BASE_US1->US_IDR = AT91C_US_TXBUFE; } // Errors serialState = CDCDSerialDriver_GetSerialState(); // Overrun if ((status & AT91C_US_OVER) != 0) { TRACE_WARNING( "ISR_Usart0: Overrun\n\r"); serialState |= CDCDSerialDriver_STATE_OVERRUN; } // Framing error if ((status & AT91C_US_FRAME) != 0) { TRACE_WARNING( "ISR_Usart0: Framing error\n\r"); serialState |= CDCDSerialDriver_STATE_FRAMING; } CDCDSerialDriver_SetSerialState(serialState); } //------------------------------------------------------------------------------ // Main //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Initializes drivers and start the USB <-> Serial bridge. //------------------------------------------------------------------------------ int main() { TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK); printf("-- USB Device CDC Serial Project %s --\n\r", SOFTPACK_VERSION); printf("-- %s\n\r", BOARD_NAME); printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); // If they are present, configure Vbus & Wake-up pins PIO_InitializeInterrupts(0); // Configure USART PIO_Configure(pins, PIO_LISTSIZE(pins)); AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US1; AT91C_BASE_US1->US_IDR = 0xFFFFFFFF; USART_Configure(AT91C_BASE_US1, USART_MODE_ASYNCHRONOUS, 115200, BOARD_MCK); USART_SetTransmitterEnabled(AT91C_BASE_US1, 1); USART_SetReceiverEnabled(AT91C_BASE_US1, 1); AIC_ConfigureIT(AT91C_ID_US1, 0, ISR_Usart0); AIC_EnableIT(AT91C_ID_US1); // Configure timer 0 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF; AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_CPCSTOP | AT91C_TC_CPCDIS | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE; AT91C_BASE_TC0->TC_RC = 0x00FF; AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; AIC_ConfigureIT(AT91C_ID_TC0, 0, ISR_Timer0); AIC_EnableIT(AT91C_ID_TC0); // BOT driver initialization CDCDSerialDriver_Initialize(); // connect if needed VBUS_CONFIGURE(); // Driver loop while (1) { // Device is not configured if (USBD_GetState() < USBD_STATE_CONFIGURED) { // Connect pull-up, wait for configuration USBD_Connect(); while (USBD_GetState() < USBD_STATE_CONFIGURED); // Start receiving data on the USART usartCurrentBuffer = 0; USART_ReadBuffer(AT91C_BASE_US1, usartBuffers[0], DATABUFFERSIZE); USART_ReadBuffer(AT91C_BASE_US1, usartBuffers[1], DATABUFFERSIZE); AT91C_BASE_US1->US_IER = AT91C_US_ENDRX | AT91C_US_FRAME | AT91C_US_OVER; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Start receiving data on the USB CDCDSerialDriver_Read(usbBuffer, DATABUFFERSIZE, (TransferCallback) UsbDataReceived, 0); } if( USBState == STATE_SUSPEND ) { TRACE_DEBUG("suspend !\n\r"); LowPowerMode(); USBState = STATE_IDLE; } if( USBState == STATE_RESUME ) { // Return in normal MODE TRACE_DEBUG("resume !\n\r"); NormalPowerMode(); USBState = STATE_IDLE; } } }