summaryrefslogtreecommitdiff
path: root/boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-03-16 14:31:22 +0200
committerYuval Adam <yuv.adm@gmail.com>2014-03-16 14:31:22 +0200
commitac4fd8e8340886f455add8cf92ee1c8458b8ae19 (patch)
treefdeb96af9d57573855405fb5099468244772cd49 /boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c
parent821e3405f23958760f7c27e8934940abfed3d5cb (diff)
Add ek-tm4c1294xl example projects
Diffstat (limited to 'boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c')
-rw-r--r--boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c1687
1 files changed, 1687 insertions, 0 deletions
diff --git a/boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c b/boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c
new file mode 100644
index 0000000..16ad2ee
--- /dev/null
+++ b/boards/ek-tm4c1294xl/usb_dev_cserial/usb_dev_cserial.c
@@ -0,0 +1,1687 @@
+//****************************************************************************
+//
+// usb_dev_cserial.c - Main routines for the USB CDC composite serial example.
+//
+// Copyright (c) 2010-2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.0.12573 of the EK-TM4C1294XL Firmware Package.
+//
+//****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_types.h"
+#include "inc/hw_uart.h"
+#include "driverlib/debug.h"
+#include "driverlib/gpio.h"
+#include "driverlib/interrupt.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/systick.h"
+#include "driverlib/timer.h"
+#include "driverlib/uart.h"
+#include "driverlib/usb.h"
+#include "usblib/usblib.h"
+#include "usblib/usbcdc.h"
+#include "usblib/usb-ids.h"
+#include "usblib/device/usbdevice.h"
+#include "usblib/device/usbdcomp.h"
+#include "usblib/device/usbdcdc.h"
+#include "utils/cmdline.h"
+#include "utils/ustdlib.h"
+#include "drivers/pinout.h"
+#include "usb_structs.h"
+
+//****************************************************************************
+//
+//! \addtogroup example_list
+//! <h1>USB Composite Serial Device (usb_dev_cserial)</h1>
+//!
+//! This example application turns the evaluation kit into a multiple virtual
+//! serial ports when connected to the USB host system. The application
+//! supports the USB Communication Device Class, Abstract Control Model to
+//! redirect UART0 traffic to and from the USB host system. For this example,
+//! the evaluation kit will enumerate as a composite device with two virtual
+//! serial ports. Including the physical UART0 connection with the ICDI, this
+//! means that three independent virtual serial ports will be visible to the
+//! USB host.
+//!
+//! The first virtual serial port will echo data to the physical UART0 port on
+//! the device which is connected to the virtual serial port on the ICDI device
+//! on this board. The physical UART0 will also echo onto the first virtual
+//! serial device provided by the Stellaris controller.
+//!
+//! The second Stellaris virtual serial port will provide a console that can
+//! echo data to both the ICDI virtual serial port and the first Stellaris
+//! virtual serial port. It will also allow turning on, off or toggling the
+//! boards led status. Typing a "?" and pressing return should echo a list of
+//! commands to the terminal, since this board can show up as possibly three
+//! individual virtual serial devices.
+//!
+//! Assuming you installed TivaWare in the default directory, a driver
+//! information (INF) file for use with Windows XP, Windows Vista and Windows7
+//! can be found in C:/TivaWare_C_Series-x.x/windows_drivers. For Windows 2000,
+//! the required INF file is in C:/TivaWare_C_Series-x.x/windows_drivers/win2K.
+//
+//*****************************************************************************
+
+//****************************************************************************
+//
+// Note:
+//
+// This example is intended to run on Stellaris evaluation kit hardware
+// where the UARTs are wired solely for TX and RX, and do not have GPIOs
+// connected to act as handshake signals. As a result, this example mimics
+// the case where communication is always possible. It reports DSR, DCD
+// and CTS as high to ensure that the USB host recognizes that data can be
+// sent and merely ignores the host's requested DTR and RTS states. "TODO"
+// comments in the code indicate where code would be required to add support
+// for real handshakes.
+//
+//****************************************************************************
+
+
+//****************************************************************************
+//
+// The system tick rate expressed both as ticks per second and a millisecond
+// period.
+//
+//****************************************************************************
+#define SYSTICKS_PER_SECOND 100
+#define SYSTICK_PERIOD_MS (1000 / SYSTICKS_PER_SECOND)
+
+//*****************************************************************************
+//
+// Variable to remember our clock frequency
+//
+//*****************************************************************************
+uint32_t g_ui32SysClock = 0;
+
+//****************************************************************************
+//
+// Variables tracking transmit and receive counts.
+//
+//****************************************************************************
+volatile uint32_t g_ui32UARTTxCount = 0;
+volatile uint32_t g_ui32UARTRxCount = 0;
+
+//****************************************************************************
+//
+// Default line coding settings for the redirected UART.
+//
+//****************************************************************************
+#define DEFAULT_BIT_RATE 115200
+#define DEFAULT_UART_CONFIG (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | \
+ UART_CONFIG_STOP_ONE)
+
+//****************************************************************************
+//
+// GPIO peripherals and pins muxed with the redirected UART. These will
+// depend upon the IC in use and the UART selected in UART0_BASE. Be careful
+// that these settings all agree with the hardware you are using.
+//
+//****************************************************************************
+#define TX_GPIO_BASE GPIO_PORTA_BASE
+#define TX_GPIO_PERIPH SYSCTL_PERIPH_GPIOA
+#define TX_GPIO_PIN GPIO_PIN_1
+
+#define RX_GPIO_BASE GPIO_PORTA_BASE
+#define RX_GPIO_PERIPH SYSCTL_PERIPH_GPIOA
+#define RX_GPIO_PIN GPIO_PIN_0
+
+//****************************************************************************
+//
+// The LED control macros.
+//
+//****************************************************************************
+#define LEDOn() ROM_GPIOPinWrite(CLP_D1_PORT, CLP_D1_PIN, CLP_D1_PIN);
+
+#define LEDOff() ROM_GPIOPinWrite(CLP_D1_PORT, CLP_D1_PIN, 0)
+#define LEDToggle() \
+ ROM_GPIOPinWrite(CLP_D1_PORT, CLP_D1_PIN, \
+ (ROM_GPIOPinRead(CLP_D1_PORT, CLP_D1_PIN) ^ \
+ CLP_D1_PIN));
+
+//****************************************************************************
+//
+// Character sequence sent to the serial terminal to implement a character
+// erase when backspace is pressed.
+//
+//****************************************************************************
+static const char g_pcBackspace[3] = {0x08, ' ', 0x08};
+
+//****************************************************************************
+//
+// Defines the size of the buffer that holds the command line.
+//
+//****************************************************************************
+#define CMD_BUF_SIZE 256
+
+//****************************************************************************
+//
+// The buffer that holds the command line.
+//
+//****************************************************************************
+static char g_pcCmdBuf[CMD_BUF_SIZE];
+static uint32_t ui32CmdIdx;
+
+//****************************************************************************
+//
+// Flag indicating whether or not we are currently sending a Break condition.
+//
+//****************************************************************************
+static bool g_bSendingBreak = false;
+
+//****************************************************************************
+//
+// Global system tick counter
+//
+//****************************************************************************
+volatile uint32_t g_ui32SysTickCount = 0;
+
+//****************************************************************************
+//
+// The memory allocated to hold the composite descriptor that is created by
+// the call to USBDCompositeInit().
+//
+//****************************************************************************
+uint8_t g_pucDescriptorData[DESCRIPTOR_DATA_SIZE];
+
+//****************************************************************************
+//
+// Flags used to pass commands from interrupt context to the main loop.
+//
+//****************************************************************************
+#define COMMAND_PACKET_RECEIVED 0x00000001
+#define COMMAND_STATUS_UPDATE 0x00000002
+#define COMMAND_RECEIVED 0x00000004
+
+volatile uint32_t g_ui32Flags = 0;
+char *g_pcStatus;
+
+//****************************************************************************
+//
+// Global flag indicating that a USB configuration has been set.
+//
+//****************************************************************************
+static volatile bool g_bUSBConfigured = false;
+
+//****************************************************************************
+//
+// The error routine that is called if the driver library encounters an error.
+//
+//****************************************************************************
+#ifdef DEBUG
+void
+__error__(char *pcFilename, uint32_t ui32Line)
+{
+ while(1)
+ {
+ }
+}
+#endif
+
+//****************************************************************************
+//
+// This function will print out to the console UART and not the echo UART.
+//
+//****************************************************************************
+void
+CommandPrint(const char *pcStr)
+{
+ uint32_t ui32Index;
+ const char cCR = 0xd;
+
+ ui32Index = 0;
+
+ while(pcStr[ui32Index] != 0)
+ {
+ //
+ // Wait for space for two bytes in case there is a need to send out
+ // the line feed plus the carriage return.
+ //
+ while(USBBufferSpaceAvailable(&g_psTxBuffer[1]) < 2)
+ {
+ }
+
+ //
+ // Print the next character.
+ //
+ USBBufferWrite(&g_psTxBuffer[1], (const uint8_t *)&pcStr[ui32Index],
+ 1);
+
+ //
+ // If this is a line feed then send a carriage return as well.
+ //
+ if(pcStr[ui32Index] == 0xa)
+ {
+ USBBufferWrite(&g_psTxBuffer[1], (const uint8_t *)&cCR, 1);
+ }
+
+ ui32Index++;
+ }
+}
+
+//****************************************************************************
+//
+// This function is called whenever serial data is received from the UART.
+// It is passed the accumulated error flags from each character received in
+// this interrupt and determines from them whether or not an interrupt
+// notification to the host is required.
+//
+// If a notification is required and the control interrupt endpoint is idle,
+// we send the notification immediately. If the endpoint is not idle, we
+// accumulate the errors in a global variable which will be checked on
+// completion of the previous notification and used to send a second one
+// if necessary.
+//
+//****************************************************************************
+static void
+CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, int32_t i32Errors)
+{
+ unsigned short usSerialState;
+
+ //
+ // Clear our USB serial state. Since we are faking the handshakes, always
+ // set the TXCARRIER (DSR) and RXCARRIER (DCD) bits.
+ //
+ usSerialState = USB_CDC_SERIAL_STATE_TXCARRIER |
+ USB_CDC_SERIAL_STATE_RXCARRIER;
+
+ //
+ // Are any error bits set?
+ //
+ if(i32Errors)
+ {
+ //
+ // At least one error is being notified so translate from our hardware
+ // error bits into the correct state markers for the USB notification.
+ //
+ if(i32Errors & UART_DR_OE)
+ {
+ usSerialState |= USB_CDC_SERIAL_STATE_OVERRUN;
+ }
+
+ if(i32Errors & UART_DR_PE)
+ {
+ usSerialState |= USB_CDC_SERIAL_STATE_PARITY;
+ }
+
+ if(i32Errors & UART_DR_FE)
+ {
+ usSerialState |= USB_CDC_SERIAL_STATE_FRAMING;
+ }
+
+ if(i32Errors & UART_DR_BE)
+ {
+ usSerialState |= USB_CDC_SERIAL_STATE_BREAK;
+ }
+
+ //
+ // Call the CDC driver to notify the state change.
+ //
+ USBDCDCSerialStateChange((void *)psDevice, usSerialState);
+ }
+}
+
+//****************************************************************************
+//
+// Read as many characters from the UART FIFO as we can and move them into
+// the CDC transmit buffer.
+//
+// \return Returns UART error flags read during data reception.
+//
+//****************************************************************************
+static int32_t
+ReadUARTData(void)
+{
+ int32_t i32Char, i32Errors;
+ uint8_t ucChar;
+ uint32_t ui32Space;
+
+ //
+ // Clear our error indicator.
+ //
+ i32Errors = 0;
+
+ //
+ // How much space do we have in the buffer?
+ //
+ ui32Space = USBBufferSpaceAvailable((tUSBBuffer *)&g_psTxBuffer[0]);
+
+ //
+ // Read data from the UART FIFO until there is none left or we run
+ // out of space in our receive buffer.
+ //
+ while(ui32Space && UARTCharsAvail(UART0_BASE))
+ {
+ //
+ // Read a character from the UART FIFO into the ring buffer if no
+ // errors are reported.
+ //
+ i32Char = UARTCharGetNonBlocking(UART0_BASE);
+
+ //
+ // If the character did not contain any error notifications,
+ // copy it to the output buffer.
+ //
+ if(!(i32Char & ~0xFF))
+ {
+ ucChar = (uint8_t)(i32Char & 0xFF);
+
+ USBBufferWrite((tUSBBuffer *)&g_psTxBuffer[0],
+ (uint8_t *)&ucChar, 1);
+
+ //
+ // Decrement the number of bytes we know the buffer can accept.
+ //
+ ui32Space--;
+ }
+ else
+ {
+ //
+ // Update our error accumulator.
+ //
+ i32Errors |= i32Char;
+ }
+
+ //
+ // Update our count of bytes received via the UART.
+ //
+ g_ui32UARTRxCount++;
+ }
+
+ //
+ // Pass back the accumulated error indicators.
+ //
+ return(i32Errors);
+}
+
+//****************************************************************************
+//
+// Take as many bytes from the transmit buffer as we have space for and move
+// them into the USB UART's transmit FIFO.
+//
+//****************************************************************************
+static void
+USBUARTPrimeTransmit(uint32_t ui32Base)
+{
+ uint32_t ui32Read;
+ uint8_t ucChar;
+
+ //
+ // If we are currently sending a break condition, don't receive any
+ // more data. We will resume transmission once the break is turned off.
+ //
+ if(g_bSendingBreak)
+ {
+ return;
+ }
+
+ //
+ // If there is space in the UART FIFO, try to read some characters
+ // from the receive buffer to fill it again.
+ //
+ while(UARTSpaceAvail(ui32Base))
+ {
+ //
+ // Get a character from the buffer.
+ //
+ ui32Read = USBBufferRead((tUSBBuffer *)&g_psRxBuffer[0], &ucChar, 1);
+
+ //
+ // Did we get a character?
+ //
+ if(ui32Read)
+ {
+ //
+ // Place the character in the UART transmit FIFO.
+ //
+ UARTCharPut(ui32Base, ucChar);
+
+ //
+ // Update our count of bytes transmitted via the UART.
+ //
+ g_ui32UARTTxCount++;
+ }
+ else
+ {
+ //
+ // We ran out of characters so exit the function.
+ //
+ return;
+ }
+ }
+}
+
+//****************************************************************************
+//
+// Interrupt handler for the system tick counter.
+//
+//****************************************************************************
+void
+SysTickIntHandler(void)
+{
+ //
+ // Update our system time.
+ //
+ g_ui32SysTickCount++;
+}
+
+//****************************************************************************
+//
+// Interrupt handler for the UART which we are redirecting via USB.
+//
+//****************************************************************************
+void
+USBUARTIntHandler(void)
+{
+ uint32_t ui32Ints;
+ int32_t i32Errors;
+
+ //
+ // Get and clear the current interrupt source(s)
+ //
+ ui32Ints = UARTIntStatus(UART0_BASE, true);
+ UARTIntClear(UART0_BASE, ui32Ints);
+
+ //
+ // Are we being interrupted because the TX FIFO has space available?
+ //
+ if(ui32Ints & UART_INT_TX)
+ {
+ //
+ // Move as many bytes as we can into the transmit FIFO.
+ //
+ USBUARTPrimeTransmit(UART0_BASE);
+
+ //
+ // If the output buffer is empty, turn off the transmit interrupt.
+ //
+ if(!USBBufferDataAvailable(&g_psRxBuffer[0]))
+ {
+ UARTIntDisable(UART0_BASE, UART_INT_TX);
+ }
+ }
+
+ //
+ // Handle receive interrupts.
+ //
+ if(ui32Ints & (UART_INT_RX | UART_INT_RT))
+ {
+ //
+ // Read the UART's characters into the buffer.
+ //
+ i32Errors = ReadUARTData();
+
+ //
+ // Check to see if we need to notify the host of any errors we just
+ // detected.
+ //
+ CheckForSerialStateChange(&g_psCDCDevice[0], i32Errors);
+ }
+}
+
+//****************************************************************************
+//
+// Set the state of the RS232 RTS and DTR signals. Handshaking is not
+// supported so this request will be ignored.
+//
+//****************************************************************************
+static void
+SetControlLineState(unsigned short usState)
+{
+}
+
+//****************************************************************************
+//
+// Set the communication parameters to use on the UART.
+//
+//****************************************************************************
+static bool
+SetLineCoding(tLineCoding *psLineCoding)
+{
+ uint32_t ui32Config;
+ bool bRetcode;
+
+ //
+ // Assume everything is OK until we detect any problem.
+ //
+ bRetcode = true;
+
+ //
+ // Word length. For invalid values, the default is to set 8 bits per
+ // character and return an error.
+ //
+ switch(psLineCoding->ui8Databits)
+ {
+ case 5:
+ {
+ ui32Config = UART_CONFIG_WLEN_5;
+ break;
+ }
+
+ case 6:
+ {
+ ui32Config = UART_CONFIG_WLEN_6;
+ break;
+ }
+
+ case 7:
+ {
+ ui32Config = UART_CONFIG_WLEN_7;
+ break;
+ }
+
+ case 8:
+ {
+ ui32Config = UART_CONFIG_WLEN_8;
+ break;
+ }
+
+ default:
+ {
+ ui32Config = UART_CONFIG_WLEN_8;
+ bRetcode = false;
+ break;
+ }
+ }
+
+ //
+ // Parity. For any invalid values, we set no parity and return an error.
+ //
+ switch(psLineCoding->ui8Parity)
+ {
+ case USB_CDC_PARITY_NONE:
+ {
+ ui32Config |= UART_CONFIG_PAR_NONE;
+ break;
+ }
+
+ case USB_CDC_PARITY_ODD:
+ {
+ ui32Config |= UART_CONFIG_PAR_ODD;
+ break;
+ }
+
+ case USB_CDC_PARITY_EVEN:
+ {
+ ui32Config |= UART_CONFIG_PAR_EVEN;
+ break;
+ }
+
+ case USB_CDC_PARITY_MARK:
+ {
+ ui32Config |= UART_CONFIG_PAR_ONE;
+ break;
+ }
+
+ case USB_CDC_PARITY_SPACE:
+ {
+ ui32Config |= UART_CONFIG_PAR_ZERO;
+ break;
+ }
+
+ default:
+ {
+ ui32Config |= UART_CONFIG_PAR_NONE;
+ bRetcode = false;
+ break;
+ }
+ }
+
+ //
+ // Stop bits. Our hardware only supports 1 or 2 stop bits whereas CDC
+ // allows the host to select 1.5 stop bits. If passed 1.5 (or any other
+ // invalid or unsupported value of ui8Stop, we set up for 1 stop bit but
+ // return an error in case the caller needs to Stall or otherwise report
+ // this back to the host.
+ //
+ switch(psLineCoding->ui8Stop)
+ {
+ //
+ // One stop bit requested.
+ //
+ case USB_CDC_STOP_BITS_1:
+ {
+ ui32Config |= UART_CONFIG_STOP_ONE;
+ break;
+ }
+
+ //
+ // Two stop bits requested.
+ //
+ case USB_CDC_STOP_BITS_2:
+ {
+ ui32Config |= UART_CONFIG_STOP_TWO;
+ break;
+ }
+
+ //
+ // Other cases are either invalid values of ui8Stop or values that we
+ // cannot support so set 1 stop bit but return an error.
+ //
+ default:
+ {
+ ui32Config = UART_CONFIG_STOP_ONE;
+ bRetcode |= false;
+ break;
+ }
+ }
+
+ //
+ // Set the UART mode appropriately.
+ //
+ UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, psLineCoding->ui32Rate,
+ ui32Config);
+
+ //
+ // Let the caller know if we had a problem or not.
+ //
+ return(bRetcode);
+}
+
+//****************************************************************************
+//
+// Get the communication parameters in use on the UART.
+//
+//****************************************************************************
+static void
+GetLineCoding(tLineCoding *psLineCoding)
+{
+ uint32_t ui32Config;
+ uint32_t ui32Rate;
+
+ //
+ // Get the current line coding set in the UART.
+ //
+ UARTConfigGetExpClk(UART0_BASE, g_ui32SysClock, &ui32Rate,
+ &ui32Config);
+ psLineCoding->ui32Rate = ui32Rate;
+
+ //
+ // Translate the configuration word length field into the format expected
+ // by the host.
+ //
+ switch(ui32Config & UART_CONFIG_WLEN_MASK)
+ {
+ case UART_CONFIG_WLEN_8:
+ {
+ psLineCoding->ui8Databits = 8;
+ break;
+ }
+
+ case UART_CONFIG_WLEN_7:
+ {
+ psLineCoding->ui8Databits = 7;
+ break;
+ }
+
+ case UART_CONFIG_WLEN_6:
+ {
+ psLineCoding->ui8Databits = 6;
+ break;
+ }
+
+ case UART_CONFIG_WLEN_5:
+ {
+ psLineCoding->ui8Databits = 5;
+ break;
+ }
+ }
+
+ //
+ // Translate the configuration parity field into the format expected
+ // by the host.
+ //
+ switch(ui32Config & UART_CONFIG_PAR_MASK)
+ {
+ case UART_CONFIG_PAR_NONE:
+ {
+ psLineCoding->ui8Parity = USB_CDC_PARITY_NONE;
+ break;
+ }
+
+ case UART_CONFIG_PAR_ODD:
+ {
+ psLineCoding->ui8Parity = USB_CDC_PARITY_ODD;
+ break;
+ }
+
+ case UART_CONFIG_PAR_EVEN:
+ {
+ psLineCoding->ui8Parity = USB_CDC_PARITY_EVEN;
+ break;
+ }
+
+ case UART_CONFIG_PAR_ONE:
+ {
+ psLineCoding->ui8Parity = USB_CDC_PARITY_MARK;
+ break;
+ }
+
+ case UART_CONFIG_PAR_ZERO:
+ {
+ psLineCoding->ui8Parity = USB_CDC_PARITY_SPACE;
+ break;
+ }
+ }
+
+ //
+ // Translate the configuration stop bits field into the format expected
+ // by the host.
+ //
+ switch(ui32Config & UART_CONFIG_STOP_MASK)
+ {
+ case UART_CONFIG_STOP_ONE:
+ {
+ psLineCoding->ui8Stop = USB_CDC_STOP_BITS_1;
+ break;
+ }
+
+ case UART_CONFIG_STOP_TWO:
+ {
+ psLineCoding->ui8Stop = USB_CDC_STOP_BITS_2;
+ break;
+ }
+ }
+}
+
+//****************************************************************************
+//
+// This function sets or clears a break condition on the redirected UART RX
+// line. A break is started when the function is called with \e bSend set to
+// \b true and persists until the function is called again with \e bSend set
+// to \b false.
+//
+//****************************************************************************
+static void
+SendBreak(bool bSend)
+{
+ //
+ // Are we being asked to start or stop the break condition?
+ //
+ if(!bSend)
+ {
+ //
+ // Remove the break condition on the line.
+ //
+ UARTBreakCtl(UART0_BASE, false);
+ g_bSendingBreak = false;
+ }
+ else
+ {
+ //
+ // Start sending a break condition on the line.
+ //
+ UARTBreakCtl(UART0_BASE, true);
+ g_bSendingBreak = true;
+ }
+}
+
+//****************************************************************************
+//
+// Handles CDC driver notifications related to control and setup of the
+// device.
+//
+// \param pvCBData is the client-supplied callback pointer for this channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to perform control-related
+// operations on behalf of the USB host. These functions include setting
+// and querying the serial communication parameters, setting handshake line
+// states and sending break conditions.
+//
+// \return The return value is event-specific.
+//
+//****************************************************************************
+uint32_t
+ControlHandler(void *pvCBData, uint32_t ui32Event,
+ uint32_t ui32MsgValue, void *pvMsgData)
+{
+ uint32_t ui32IntsOff;
+
+ //
+ // Which event are we being asked to process?
+ //
+ switch(ui32Event)
+ {
+ //
+ // We are connected to a host and communication is now possible.
+ //
+ case USB_EVENT_CONNECTED:
+ {
+ g_bUSBConfigured = true;
+
+ //
+ // Flush our buffers.
+ //
+ USBBufferFlush(&g_psTxBuffer[0]);
+ USBBufferFlush(&g_psRxBuffer[0]);
+
+ //
+ // Tell the main loop to update the display.
+ //
+ ui32IntsOff = IntMasterDisable();
+ g_pcStatus = "Host connected.";
+ g_ui32Flags |= COMMAND_STATUS_UPDATE;
+ if(!ui32IntsOff)
+ {
+ IntMasterEnable();
+ }
+ break;
+ }
+
+ //
+ // The host has disconnected.
+ //
+ case USB_EVENT_DISCONNECTED:
+ {
+ g_bUSBConfigured = false;
+ ui32IntsOff = IntMasterDisable();
+ g_pcStatus = "Host disconnected.";
+ g_ui32Flags |= COMMAND_STATUS_UPDATE;
+ if(!ui32IntsOff)
+ {
+ IntMasterEnable();
+ }
+ break;
+ }
+
+ //
+ // Return the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_GET_LINE_CODING:
+ {
+ GetLineCoding(pvMsgData);
+ break;
+ }
+
+ //
+ // Set the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_SET_LINE_CODING:
+ {
+ SetLineCoding(pvMsgData);
+ break;
+ }
+
+ //
+ // Set the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE:
+ {
+ SetControlLineState((unsigned short)ui32MsgValue);
+ break;
+ }
+
+ //
+ // Send a break condition on the serial line.
+ //
+ case USBD_CDC_EVENT_SEND_BREAK:
+ {
+ SendBreak(true);
+ break;
+ }
+
+ //
+ // Clear the break condition on the serial line.
+ //
+ case USBD_CDC_EVENT_CLEAR_BREAK:
+ {
+ SendBreak(false);
+ break;
+ }
+
+ //
+ // Ignore SUSPEND and RESUME for now.
+ //
+ case USB_EVENT_SUSPEND:
+ case USB_EVENT_RESUME:
+ {
+ break;
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+ break;
+ }
+ }
+
+ return(0);
+}
+
+//****************************************************************************
+//
+// Handles CDC driver notifications related to the transmit channel (data to
+// the USB host).
+//
+// \param ui32CBData is the client-supplied callback pointer for this channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the transmit data channel (the IN channel carrying
+// data to the USB host).
+//
+// \return The return value is event-specific.
+//
+//****************************************************************************
+uint32_t
+TxHandlerEcho(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
+ void *pvMsgData)
+{
+ //
+ // Which event have we been sent?
+ //
+ switch(ui32Event)
+ {
+ case USB_EVENT_TX_COMPLETE:
+ {
+ //
+ // Since we are using the USBBuffer, we don't need to do anything
+ // here.
+ //
+ break;
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+ break;
+ }
+ }
+ return(0);
+}
+
+//****************************************************************************
+//
+// Handles CDC driver notifications related to the transmit channel (data to
+// the USB host).
+//
+// \param ui32CBData is the client-supplied callback pointer for this channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the transmit data channel (the IN channel carrying
+// data to the USB host).
+//
+// \return The return value is event-specific.
+//
+//****************************************************************************
+uint32_t
+TxHandlerCmd(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
+ void *pvMsgData)
+{
+ //
+ // Which event have we been sent?
+ //
+ switch(ui32Event)
+ {
+ case USB_EVENT_TX_COMPLETE:
+ {
+ //
+ // Since we are using the USBBuffer, we don't need to do anything
+ // here.
+ //
+ break;
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+ break;
+ }
+ }
+ return(0);
+}
+
+//****************************************************************************
+//
+// Handles CDC driver notifications related to the receive channel (data from
+// the USB host).
+//
+// \param ui32CBData is the client-supplied callback data value for this
+// channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the receive data channel (the OUT channel carrying
+// data from the USB host).
+//
+// \return The return value is event-specific.
+//
+//****************************************************************************
+uint32_t
+RxHandlerEcho(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
+ void *pvMsgData)
+{
+ uint32_t ui32Count;
+
+ //
+ // Which event are we being sent?
+ //
+ switch(ui32Event)
+ {
+ //
+ // A new packet has been received.
+ //
+ case USB_EVENT_RX_AVAILABLE:
+ {
+ //
+ // Feed some characters into the UART TX FIFO and enable the
+ // interrupt so we are told when there is more space.
+ //
+ USBUARTPrimeTransmit(UART0_BASE);
+ UARTIntEnable(UART0_BASE, UART_INT_TX);
+ break;
+ }
+
+ //
+ // We are being asked how much unprocessed data we have still to
+ // process. We return 0 if the UART is currently idle or 1 if it is
+ // in the process of transmitting something. The actual number of
+ // bytes in the UART FIFO is not important here, merely whether or
+ // not everything previously sent to us has been transmitted.
+ //
+ case USB_EVENT_DATA_REMAINING:
+ {
+ //
+ // Get the number of bytes in the buffer and add 1 if some data
+ // still has to clear the transmitter.
+ //
+ ui32Count = UARTBusy(UART0_BASE) ? 1 : 0;
+ return(ui32Count);
+ }
+
+ //
+ // We are being asked to provide a buffer into which the next packet
+ // can be read. We do not support this mode of receiving data so let
+ // the driver know by returning 0. The CDC driver should not be
+ // sending this message but this is included just for illustration and
+ // completeness.
+ //
+ case USB_EVENT_REQUEST_BUFFER:
+ {
+ return(0);
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+ break;
+ }
+ }
+
+ return(0);
+}
+
+//****************************************************************************
+//
+// Handles CDC driver notifications related to the receive channel (data from
+// the USB host).
+//
+// \param ui32CBData is the client-supplied callback data value for this
+// channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the receive data channel (the OUT channel carrying
+// data from the USB host).
+//
+// \return The return value is event-specific.
+//
+//****************************************************************************
+uint32_t
+RxHandlerCmd(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
+ void *pvMsgData)
+{
+ uint8_t ucChar;
+ const tUSBDCDCDevice *psCDCDevice;
+ const tUSBBuffer *pBufferRx;
+ const tUSBBuffer *pBufferTx;
+
+ //
+ // Which event are we being sent?
+ //
+ switch(ui32Event)
+ {
+ //
+ // A new packet has been received.
+ //
+ case USB_EVENT_RX_AVAILABLE:
+ {
+ //
+ // Create a device pointer.
+ //
+ psCDCDevice = (const tUSBDCDCDevice *)pvCBData;
+ pBufferRx = (const tUSBBuffer *)psCDCDevice->pvRxCBData;
+ pBufferTx = (const tUSBBuffer *)psCDCDevice->pvTxCBData;
+
+ //
+ // Keep reading characters as long as there are more to receive.
+ //
+ while(USBBufferRead(pBufferRx,
+ (uint8_t *)&g_pcCmdBuf[ui32CmdIdx], 1))
+ {
+ //
+ // If this is a backspace character, erase the last thing typed
+ // assuming there's something there to type.
+ //
+ if(g_pcCmdBuf[ui32CmdIdx] == 0x08)
+ {
+ //
+ // If our current command buffer has any characters in it,
+ // erase the last one.
+ //
+ if(ui32CmdIdx)
+ {
+ //
+ // Delete the last character.
+ //
+ ui32CmdIdx--;
+
+ //
+ // Send a backspace, a space and a further backspace so
+ // that the character is erased from the terminal too.
+ //
+ USBBufferWrite(pBufferTx,
+ (uint8_t *)g_pcBackspace, 3);
+ }
+ }
+ //
+ // If this was a line feed then put out a carriage return as
+ // well.
+ //
+ else
+ {
+ //
+ // Feed the new characters into the UART TX FIFO.
+ //
+ USBBufferWrite(pBufferTx,
+ (uint8_t *)&g_pcCmdBuf[ui32CmdIdx], 1);
+
+ //
+ // Was this a carriage return?
+ //
+ if(g_pcCmdBuf[ui32CmdIdx] == 0xd)
+ {
+ //
+ // Set a line feed.
+ //
+ ucChar = 0xa;
+ USBBufferWrite(pBufferTx, &ucChar, 1);
+
+ //
+ // Indicate that a command has been received.
+ //
+ g_ui32Flags |= COMMAND_RECEIVED;
+
+ g_pcCmdBuf[ui32CmdIdx] = 0;
+
+ ui32CmdIdx = 0;
+ }
+
+ //
+ // Only increment if the index has not reached the end of
+ // the buffer and continually overwrite the last value if
+ // the buffer does attempt to overflow.
+ //
+ else if(ui32CmdIdx < CMD_BUF_SIZE)
+ {
+ ui32CmdIdx++;
+ }
+ }
+ }
+
+ break;
+ }
+
+ //
+ // We are being asked how much unprocessed data we have still to
+ // process. We return 0 if the UART is currently idle or 1 if it is
+ // in the process of transmitting something. The actual number of
+ // bytes in the UART FIFO is not important here, merely whether or
+ // not everything previously sent to us has been transmitted.
+ //
+ case USB_EVENT_DATA_REMAINING:
+ {
+ //
+ // Get the number of bytes in the buffer and add 1 if some data
+ // still has to clear the transmitter.
+ //
+ return(0);
+ }
+
+ //
+ // We are being asked to provide a buffer into which the next packet
+ // can be read. We do not support this mode of receiving data so let
+ // the driver know by returning 0. The CDC driver should not be
+ // sending this message but this is included just for illustration and
+ // completeness.
+ //
+ case USB_EVENT_REQUEST_BUFFER:
+ {
+ return(0);
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+ break;
+ }
+ }
+
+ return(0);
+}
+
+//****************************************************************************
+//
+// This command allows setting, clearing or toggling the Status LED.
+//
+// The first argument should be one of the following:
+// on - Turn on the LED.
+// off - Turn off the LED.
+// toggle - Toggle the current LED status.
+//
+//****************************************************************************
+int
+Cmd_led(int argc, char *argv[])
+{
+ //
+ // These values only check the second character since all parameters are
+ // different in that character.
+ //
+ if(argv[1][1] == 'n')
+ {
+ //
+ // Turn on the LED.
+ //
+ LEDOn();
+ }
+ else if(argv[1][1] == 'f')
+ {
+ //
+ // Turn off the LED.
+ //
+ LEDOff();
+ }
+ else if(argv[1][1] == 'o')
+ {
+ //
+ // Toggle the LED.
+ //
+ LEDToggle();
+ }
+ else
+ {
+ //
+ // The command format was not correct so print out some help.
+ //
+ CommandPrint("\nled <on|off|toggle>\n");
+ CommandPrint(" on - Turn on the LED.\n");
+ CommandPrint(" off - Turn off the LED.\n");
+ CommandPrint(" toggle - Toggle the LED state.\n");
+ }
+ return(0);
+}
+
+//****************************************************************************
+//
+// This is a stub that will not be called. It is here to echo the help string
+// but will be handled before being called by CmdLineProcess().
+//
+//****************************************************************************
+int
+Cmd_echo(int argc, char *argv[])
+{
+ return(0);
+}
+
+//****************************************************************************
+//
+// This function is called when "echo" command is issued so that the
+// CmdLineProcess() function does not attempt to split up the string based on
+// space delimiters.
+//
+//****************************************************************************
+int
+Echo(char *pucStr)
+{
+ uint32_t ui32Index;
+
+ //
+ // Fail the command if the "echo" command is not terminated with a space.
+ //
+ if(pucStr[4] != ' ')
+ {
+ return(-1);
+ }
+
+ //
+ // Put out a carriage return and line feed to both echo ports.
+ //
+ USBBufferWrite((tUSBBuffer *)&g_psTxBuffer[0], (uint8_t *)"\r\n", 2);
+ UARTCharPut(UART0_BASE, '\r');
+ UARTCharPut(UART0_BASE, '\n');
+
+ //
+ // Loop through the characters and print them to both echo ports.
+ //
+ for(ui32Index = 5; ui32Index < CMD_BUF_SIZE; ui32Index++)
+ {
+ //
+ // If a null is found then go to the next argument and replace the
+ // null with a space character.
+ //
+ if(pucStr[ui32Index] == 0)
+ {
+ break;
+ }
+
+ //
+ // Write out the character to both echo ports.
+ //
+ USBBufferWrite((tUSBBuffer *)&g_psTxBuffer[0],
+ (uint8_t *)&pucStr[ui32Index], 1);
+ UARTCharPut(UART0_BASE, pucStr[ui32Index]);
+ }
+ return(0);
+}
+
+//****************************************************************************
+//
+// This function implements the "help" command. It prints a simple list of
+// the available commands with a brief description.
+//
+//****************************************************************************
+int
+Cmd_help(int argc, char *argv[])
+{
+ tCmdLineEntry *pEntry;
+
+ //
+ // Print some header text.
+ //
+ CommandPrint("\nAvailable commands\n");
+ CommandPrint("------------------\n");
+
+ //
+ // Point at the beginning of the command table.
+ //
+ pEntry = &g_psCmdTable[0];
+
+ //
+ // Enter a loop to read each entry from the command table. The end of the
+ // table has been reached when the command name is NULL.
+ //
+ while(pEntry->pcCmd)
+ {
+ //
+ // Print the command name and the brief description.
+ //
+ CommandPrint(pEntry->pcCmd);
+ CommandPrint(pEntry->pcHelp);
+ CommandPrint("\n");
+
+ //
+ // Advance to the next entry in the table.
+ //
+ pEntry++;
+ }
+
+ //
+ // Return success.
+ //
+ return(0);
+}
+
+//****************************************************************************
+//
+// This is the table that holds the command names, implementing functions, and
+// brief description.
+//
+//****************************************************************************
+tCmdLineEntry g_psCmdTable[] =
+{
+ { "help", Cmd_help, " : Display list of commands" },
+ { "h", Cmd_help, " : alias for help" },
+ { "?", Cmd_help, " : alias for help" },
+ { "echo", Cmd_echo, " : Text will be displayed on all echo ports" },
+ { "led", Cmd_led, " : Turn on/off/toggle the Status LED" },
+ { 0, 0, 0 }
+};
+
+//****************************************************************************
+//
+// This is the main application entry function.
+//
+//****************************************************************************
+int
+main(void)
+{
+ uint32_t ui32TxCount;
+ uint32_t ui32RxCount;
+ int32_t i32Status;
+
+ //
+ // Run from the PLL at 120 MHz.
+ //
+ g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
+ SYSCTL_OSC_MAIN |
+ SYSCTL_USE_PLL |
+ SYSCTL_CFG_VCO_480), 120000000);
+
+ //
+ // Not configured initially.
+ //
+ g_bUSBConfigured = false;
+
+
+ //
+ // Enable the peripherals used in this example.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
+
+ //
+ // Configure the device pins.
+ //
+ PinoutSet(false, true);
+
+ //
+ // Turn off the LED.
+ //
+ LEDOff();
+
+ //
+ // Set the default UART configuration.
+ //
+ UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, DEFAULT_BIT_RATE,
+ DEFAULT_UART_CONFIG);
+ UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
+
+ //
+ // Configure and enable UART interrupts.
+ //
+ UARTIntClear(UART0_BASE, UARTIntStatus(UART0_BASE, false));
+ UARTIntEnable(UART0_BASE, (UART_INT_OE | UART_INT_BE | UART_INT_PE |
+ UART_INT_FE | UART_INT_RT | UART_INT_TX | UART_INT_RX));
+
+ //
+ // Enable the system tick.
+ //
+ SysTickPeriodSet(g_ui32SysClock / SYSTICKS_PER_SECOND);
+ SysTickIntEnable();
+ SysTickEnable();
+
+ //
+ // Initialize the transmit and receive buffers for first serial device.
+ //
+ USBBufferInit(&g_psTxBuffer[0]);
+ USBBufferInit(&g_psRxBuffer[0]);
+
+ //
+ // Initialize the first serial port instances that is part of this
+ // composite device.
+ //
+ g_sCompDevice.psDevices[0].pvInstance =
+ USBDCDCCompositeInit(0, &g_psCDCDevice[0], &g_psCompEntries[0]);
+
+ //
+ // Initialize the transmit and receive buffers for second serial device.
+ //
+ USBBufferInit(&g_psTxBuffer[1]);
+ USBBufferInit(&g_psRxBuffer[1]);
+
+ //
+ // Initialize the second serial port instances that is part of this
+ // composite device.
+ //
+ g_sCompDevice.psDevices[1].pvInstance =
+ USBDCDCCompositeInit(0, &g_psCDCDevice[1], &g_psCompEntries[1]);
+
+ //
+ // Pass the device information to the USB library and place the device
+ // on the bus.
+ //
+ USBDCompositeInit(0, &g_sCompDevice, DESCRIPTOR_DATA_SIZE,
+ g_pucDescriptorData);
+
+ //
+ // Clear our local byte counters.
+ //
+ ui32RxCount = 0;
+ ui32TxCount = 0;
+
+ //
+ // Set the command index to 0 to start out.
+ //
+ ui32CmdIdx = 0;
+
+ //
+ // Enable interrupts now that the application is ready to start.
+ //
+ IntEnable(INT_UART0);
+
+ //
+ // Main application loop.
+ //
+ while(1)
+ {
+ if(g_ui32Flags & COMMAND_RECEIVED)
+ {
+ //
+ // Clear the flag
+ //
+ g_ui32Flags &= ~COMMAND_RECEIVED;
+
+ //
+ // Check if this is the "echo" command, "echo" in hex is 0x6f686365
+ // this prevents a more complicated string compare.
+ //
+ if(0x6f686365 == *((uint32_t *)(g_pcCmdBuf)))
+ {
+ //
+ // Print out the string.
+ //
+ i32Status = Echo(g_pcCmdBuf);
+ }
+ else
+ {
+ //
+ // Process the command line.
+ //
+ i32Status = CmdLineProcess(g_pcCmdBuf);
+ }
+
+ //
+ // Handle the case of bad command.
+ //
+ if(i32Status == CMDLINE_BAD_CMD)
+ {
+ CommandPrint(g_pcCmdBuf);
+ CommandPrint(" is not a valid command!\n");
+ }
+ CommandPrint("\n> ");
+ }
+
+ //
+ // Have we been asked to update the status display?
+ //
+ if(g_ui32Flags & COMMAND_STATUS_UPDATE)
+ {
+ //
+ // Clear the command flag
+ //
+ IntMasterDisable();
+ g_ui32Flags &= ~COMMAND_STATUS_UPDATE;
+ IntMasterEnable();
+ }
+
+ //
+ // Has there been any transmit traffic since we last checked?
+ //
+ if(ui32TxCount != g_ui32UARTTxCount)
+ {
+ //
+ // Take a snapshot of the latest transmit count.
+ //
+ ui32TxCount = g_ui32UARTTxCount;
+ }
+
+ //
+ // Has there been any receive traffic since we last checked?
+ //
+ if(ui32RxCount != g_ui32UARTRxCount)
+ {
+ //
+ // Take a snapshot of the latest receive count.
+ //
+ ui32RxCount = g_ui32UARTRxCount;
+
+ }
+ }
+}