diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2014-03-16 14:41:11 +0200 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2014-03-16 14:41:11 +0200 |
| commit | 990090a4cc9070837d31e66b58d40f0c3d038741 (patch) | |
| tree | cf1b905082c364e9b223e0c5058566103138dae5 /utils/uartstdio.c | |
| parent | 7f4da522479c0f00126219f0c23b804c3a93d7a6 (diff) | |
Add usblib and utils
Diffstat (limited to 'utils/uartstdio.c')
| -rw-r--r-- | utils/uartstdio.c | 1720 |
1 files changed, 1720 insertions, 0 deletions
diff --git a/utils/uartstdio.c b/utils/uartstdio.c new file mode 100644 index 0000000..8ec2eaa --- /dev/null +++ b/utils/uartstdio.c @@ -0,0 +1,1720 @@ +//*****************************************************************************
+//
+// uartstdio.c - Utility driver to provide simple UART console functions.
+//
+// Copyright (c) 2007-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 Tiva Utility Library.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdarg.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/interrupt.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/uart.h"
+#include "utils/uartstdio.h"
+
+//*****************************************************************************
+//
+//! \addtogroup uartstdio_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// If buffered mode is defined, set aside RX and TX buffers and read/write
+// pointers to control them.
+//
+//*****************************************************************************
+#ifdef UART_BUFFERED
+
+//*****************************************************************************
+//
+// This global controls whether or not we are echoing characters back to the
+// transmitter. By default, echo is enabled but if using this module as a
+// convenient method of implementing a buffered serial interface over which
+// you will be running an application protocol, you are likely to want to
+// disable echo by calling UARTEchoSet(false).
+//
+//*****************************************************************************
+static bool g_bDisableEcho;
+
+//*****************************************************************************
+//
+// Output ring buffer. Buffer is full if g_ui32UARTTxReadIndex is one ahead of
+// g_ui32UARTTxWriteIndex. Buffer is empty if the two indices are the same.
+//
+//*****************************************************************************
+static unsigned char g_pcUARTTxBuffer[UART_TX_BUFFER_SIZE];
+static volatile uint32_t g_ui32UARTTxWriteIndex = 0;
+static volatile uint32_t g_ui32UARTTxReadIndex = 0;
+
+//*****************************************************************************
+//
+// Input ring buffer. Buffer is full if g_ui32UARTTxReadIndex is one ahead of
+// g_ui32UARTTxWriteIndex. Buffer is empty if the two indices are the same.
+//
+//*****************************************************************************
+static unsigned char g_pcUARTRxBuffer[UART_RX_BUFFER_SIZE];
+static volatile uint32_t g_ui32UARTRxWriteIndex = 0;
+static volatile uint32_t g_ui32UARTRxReadIndex = 0;
+
+//*****************************************************************************
+//
+// Macros to determine number of free and used bytes in the transmit buffer.
+//
+//*****************************************************************************
+#define TX_BUFFER_USED (GetBufferCount(&g_ui32UARTTxReadIndex, \
+ &g_ui32UARTTxWriteIndex, \
+ UART_TX_BUFFER_SIZE))
+#define TX_BUFFER_FREE (UART_TX_BUFFER_SIZE - TX_BUFFER_USED)
+#define TX_BUFFER_EMPTY (IsBufferEmpty(&g_ui32UARTTxReadIndex, \
+ &g_ui32UARTTxWriteIndex))
+#define TX_BUFFER_FULL (IsBufferFull(&g_ui32UARTTxReadIndex, \
+ &g_ui32UARTTxWriteIndex, \
+ UART_TX_BUFFER_SIZE))
+#define ADVANCE_TX_BUFFER_INDEX(Index) \
+ (Index) = ((Index) + 1) % UART_TX_BUFFER_SIZE
+
+//*****************************************************************************
+//
+// Macros to determine number of free and used bytes in the receive buffer.
+//
+//*****************************************************************************
+#define RX_BUFFER_USED (GetBufferCount(&g_ui32UARTRxReadIndex, \
+ &g_ui32UARTRxWriteIndex, \
+ UART_RX_BUFFER_SIZE))
+#define RX_BUFFER_FREE (UART_RX_BUFFER_SIZE - RX_BUFFER_USED)
+#define RX_BUFFER_EMPTY (IsBufferEmpty(&g_ui32UARTRxReadIndex, \
+ &g_ui32UARTRxWriteIndex))
+#define RX_BUFFER_FULL (IsBufferFull(&g_ui32UARTRxReadIndex, \
+ &g_ui32UARTRxWriteIndex, \
+ UART_RX_BUFFER_SIZE))
+#define ADVANCE_RX_BUFFER_INDEX(Index) \
+ (Index) = ((Index) + 1) % UART_RX_BUFFER_SIZE
+#endif
+
+//*****************************************************************************
+//
+// The base address of the chosen UART.
+//
+//*****************************************************************************
+static uint32_t g_ui32Base = 0;
+
+//*****************************************************************************
+//
+// A mapping from an integer between 0 and 15 to its ASCII character
+// equivalent.
+//
+//*****************************************************************************
+static const char * const g_pcHex = "0123456789abcdef";
+
+//*****************************************************************************
+//
+// The list of possible base addresses for the console UART.
+//
+//*****************************************************************************
+static const uint32_t g_ui32UARTBase[3] =
+{
+ UART0_BASE, UART1_BASE, UART2_BASE
+};
+
+#ifdef UART_BUFFERED
+//*****************************************************************************
+//
+// The list of possible interrupts for the console UART.
+//
+//*****************************************************************************
+static const uint32_t g_ui32UARTInt[3] =
+{
+ INT_UART0, INT_UART1, INT_UART2
+};
+
+//*****************************************************************************
+//
+// The port number in use.
+//
+//*****************************************************************************
+static uint32_t g_ui32PortNum;
+#endif
+
+//*****************************************************************************
+//
+// The list of UART peripherals.
+//
+//*****************************************************************************
+static const uint32_t g_ui32UARTPeriph[3] =
+{
+ SYSCTL_PERIPH_UART0, SYSCTL_PERIPH_UART1, SYSCTL_PERIPH_UART2
+};
+
+//*****************************************************************************
+//
+//! Determines whether the ring buffer whose pointers and size are provided
+//! is full or not.
+//!
+//! \param pui32Read points to the read index for the buffer.
+//! \param pui32Write points to the write index for the buffer.
+//! \param ui32Size is the size of the buffer in bytes.
+//!
+//! This function is used to determine whether or not a given ring buffer is
+//! full. The structure of the code is specifically to ensure that we do not
+//! see warnings from the compiler related to the order of volatile accesses
+//! being undefined.
+//!
+//! \return Returns \b true if the buffer is full or \b false otherwise.
+//
+//*****************************************************************************
+#ifdef UART_BUFFERED
+static bool
+IsBufferFull(volatile uint32_t *pui32Read,
+ volatile uint32_t *pui32Write, uint32_t ui32Size)
+{
+ uint32_t ui32Write;
+ uint32_t ui32Read;
+
+ ui32Write = *pui32Write;
+ ui32Read = *pui32Read;
+
+ return((((ui32Write + 1) % ui32Size) == ui32Read) ? true : false);
+}
+#endif
+
+//*****************************************************************************
+//
+//! Determines whether the ring buffer whose pointers and size are provided
+//! is empty or not.
+//!
+//! \param pui32Read points to the read index for the buffer.
+//! \param pui32Write points to the write index for the buffer.
+//!
+//! This function is used to determine whether or not a given ring buffer is
+//! empty. The structure of the code is specifically to ensure that we do not
+//! see warnings from the compiler related to the order of volatile accesses
+//! being undefined.
+//!
+//! \return Returns \b true if the buffer is empty or \b false otherwise.
+//
+//*****************************************************************************
+#ifdef UART_BUFFERED
+static bool
+IsBufferEmpty(volatile uint32_t *pui32Read,
+ volatile uint32_t *pui32Write)
+{
+ uint32_t ui32Write;
+ uint32_t ui32Read;
+
+ ui32Write = *pui32Write;
+ ui32Read = *pui32Read;
+
+ return((ui32Write == ui32Read) ? true : false);
+}
+#endif
+
+//*****************************************************************************
+//
+//! Determines the number of bytes of data contained in a ring buffer.
+//!
+//! \param pui32Read points to the read index for the buffer.
+//! \param pui32Write points to the write index for the buffer.
+//! \param ui32Size is the size of the buffer in bytes.
+//!
+//! This function is used to determine how many bytes of data a given ring
+//! buffer currently contains. The structure of the code is specifically to
+//! ensure that we do not see warnings from the compiler related to the order
+//! of volatile accesses being undefined.
+//!
+//! \return Returns the number of bytes of data currently in the buffer.
+//
+//*****************************************************************************
+#ifdef UART_BUFFERED
+static uint32_t
+GetBufferCount(volatile uint32_t *pui32Read,
+ volatile uint32_t *pui32Write, uint32_t ui32Size)
+{
+ uint32_t ui32Write;
+ uint32_t ui32Read;
+
+ ui32Write = *pui32Write;
+ ui32Read = *pui32Read;
+
+ return((ui32Write >= ui32Read) ? (ui32Write - ui32Read) :
+ (ui32Size - (ui32Read - ui32Write)));
+}
+#endif
+
+//*****************************************************************************
+//
+// Take as many bytes from the transmit buffer as we have space for and move
+// them into the UART transmit FIFO.
+//
+//*****************************************************************************
+#ifdef UART_BUFFERED
+static void
+UARTPrimeTransmit(uint32_t ui32Base)
+{
+ //
+ // Do we have any data to transmit?
+ //
+ if(!TX_BUFFER_EMPTY)
+ {
+ //
+ // Disable the UART interrupt. If we don't do this there is a race
+ // condition which can cause the read index to be corrupted.
+ //
+ MAP_IntDisable(g_ui32UARTInt[g_ui32PortNum]);
+
+ //
+ // Yes - take some characters out of the transmit buffer and feed
+ // them to the UART transmit FIFO.
+ //
+ while(MAP_UARTSpaceAvail(ui32Base) && !TX_BUFFER_EMPTY)
+ {
+ MAP_UARTCharPutNonBlocking(ui32Base,
+ g_pcUARTTxBuffer[g_ui32UARTTxReadIndex]);
+ ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxReadIndex);
+ }
+
+ //
+ // Reenable the UART interrupt.
+ //
+ MAP_IntEnable(g_ui32UARTInt[g_ui32PortNum]);
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+//! Configures the UART console.
+//!
+//! \param ui32PortNum is the number of UART port to use for the serial console
+//! (0-2)
+//! \param ui32Baud is the bit rate that the UART is to be configured to use.
+//! \param ui32SrcClock is the frequency of the source clock for the UART
+//! module.
+//!
+//! This function will configure the specified serial port to be used as a
+//! serial console. The serial parameters are set to the baud rate
+//! specified by the \e ui32Baud parameter and use 8 bit, no parity, and 1 stop
+//! bit.
+//!
+//! This function must be called prior to using any of the other UART console
+//! functions: UARTprintf() or UARTgets(). This function assumes that the
+//! caller has previously configured the relevant UART pins for operation as a
+//! UART rather than as GPIOs.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTStdioConfig(uint32_t ui32PortNum, uint32_t ui32Baud, uint32_t ui32SrcClock)
+{
+ //
+ // Check the arguments.
+ //
+ ASSERT((ui32PortNum == 0) || (ui32PortNum == 1) ||
+ (ui32PortNum == 2));
+
+#ifdef UART_BUFFERED
+ //
+ // In buffered mode, we only allow a single instance to be opened.
+ //
+ ASSERT(g_ui32Base == 0);
+#endif
+
+ //
+ // Check to make sure the UART peripheral is present.
+ //
+ if(!MAP_SysCtlPeripheralPresent(g_ui32UARTPeriph[ui32PortNum]))
+ {
+ return;
+ }
+
+ //
+ // Select the base address of the UART.
+ //
+ g_ui32Base = g_ui32UARTBase[ui32PortNum];
+
+ //
+ // Enable the UART peripheral for use.
+ //
+ MAP_SysCtlPeripheralEnable(g_ui32UARTPeriph[ui32PortNum]);
+
+ //
+ // Configure the UART for 115200, n, 8, 1
+ //
+ MAP_UARTConfigSetExpClk(g_ui32Base, ui32SrcClock, ui32Baud,
+ (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
+ UART_CONFIG_WLEN_8));
+
+#ifdef UART_BUFFERED
+ //
+ // Set the UART to interrupt whenever the TX FIFO is almost empty or
+ // when any character is received.
+ //
+ MAP_UARTFIFOLevelSet(g_ui32Base, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
+
+ //
+ // Flush both the buffers.
+ //
+ UARTFlushRx();
+ UARTFlushTx(true);
+
+ //
+ // Remember which interrupt we are dealing with.
+ //
+ g_ui32PortNum = ui32PortNum;
+
+ //
+ // We are configured for buffered output so enable the master interrupt
+ // for this UART and the receive interrupts. We don't actually enable the
+ // transmit interrupt in the UART itself until some data has been placed
+ // in the transmit buffer.
+ //
+ MAP_UARTIntDisable(g_ui32Base, 0xFFFFFFFF);
+ MAP_UARTIntEnable(g_ui32Base, UART_INT_RX | UART_INT_RT);
+ MAP_IntEnable(g_ui32UARTInt[ui32PortNum]);
+#endif
+
+ //
+ // Enable the UART operation.
+ //
+ MAP_UARTEnable(g_ui32Base);
+}
+
+//*****************************************************************************
+//
+//! Writes a string of characters to the UART output.
+//!
+//! \param pcBuf points to a buffer containing the string to transmit.
+//! \param ui32Len is the length of the string to transmit.
+//!
+//! This function will transmit the string to the UART output. The number of
+//! characters transmitted is determined by the \e ui32Len parameter. This
+//! function does no interpretation or translation of any characters. Since
+//! the output is sent to a UART, any LF (/n) characters encountered will be
+//! replaced with a CRLF pair.
+//!
+//! Besides using the \e ui32Len parameter to stop transmitting the string, if
+//! a null character (0) is encountered, then no more characters will be
+//! transmitted and the function will return.
+//!
+//! In non-buffered mode, this function is blocking and will not return until
+//! all the characters have been written to the output FIFO. In buffered mode,
+//! the characters are written to the UART transmit buffer and the call returns
+//! immediately. If insufficient space remains in the transmit buffer,
+//! additional characters are discarded.
+//!
+//! \return Returns the count of characters written.
+//
+//*****************************************************************************
+int
+UARTwrite(const char *pcBuf, uint32_t ui32Len)
+{
+#ifdef UART_BUFFERED
+ unsigned int uIdx;
+
+ //
+ // Check for valid arguments.
+ //
+ ASSERT(pcBuf != 0);
+ ASSERT(g_ui32Base != 0);
+
+ //
+ // Send the characters
+ //
+ for(uIdx = 0; uIdx < ui32Len; uIdx++)
+ {
+ //
+ // If the character to the UART is \n, then add a \r before it so that
+ // \n is translated to \n\r in the output.
+ //
+ if(pcBuf[uIdx] == '\n')
+ {
+ if(!TX_BUFFER_FULL)
+ {
+ g_pcUARTTxBuffer[g_ui32UARTTxWriteIndex] = '\r';
+ ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxWriteIndex);
+ }
+ else
+ {
+ //
+ // Buffer is full - discard remaining characters and return.
+ //
+ break;
+ }
+ }
+
+ //
+ // Send the character to the UART output.
+ //
+ if(!TX_BUFFER_FULL)
+ {
+ g_pcUARTTxBuffer[g_ui32UARTTxWriteIndex] = pcBuf[uIdx];
+ ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxWriteIndex);
+ }
+ else
+ {
+ //
+ // Buffer is full - discard remaining characters and return.
+ //
+ break;
+ }
+ }
+
+ //
+ // If we have anything in the buffer, make sure that the UART is set
+ // up to transmit it.
+ //
+ if(!TX_BUFFER_EMPTY)
+ {
+ UARTPrimeTransmit(g_ui32Base);
+ MAP_UARTIntEnable(g_ui32Base, UART_INT_TX);
+ }
+
+ //
+ // Return the number of characters written.
+ //
+ return(uIdx);
+#else
+ unsigned int uIdx;
+
+ //
+ // Check for valid UART base address, and valid arguments.
+ //
+ ASSERT(g_ui32Base != 0);
+ ASSERT(pcBuf != 0);
+
+ //
+ // Send the characters
+ //
+ for(uIdx = 0; uIdx < ui32Len; uIdx++)
+ {
+ //
+ // If the character to the UART is \n, then add a \r before it so that
+ // \n is translated to \n\r in the output.
+ //
+ if(pcBuf[uIdx] == '\n')
+ {
+ MAP_UARTCharPut(g_ui32Base, '\r');
+ }
+
+ //
+ // Send the character to the UART output.
+ //
+ MAP_UARTCharPut(g_ui32Base, pcBuf[uIdx]);
+ }
+
+ //
+ // Return the number of characters written.
+ //
+ return(uIdx);
+#endif
+}
+
+//*****************************************************************************
+//
+//! A simple UART based get string function, with some line processing.
+//!
+//! \param pcBuf points to a buffer for the incoming string from the UART.
+//! \param ui32Len is the length of the buffer for storage of the string,
+//! including the trailing 0.
+//!
+//! This function will receive a string from the UART input and store the
+//! characters in the buffer pointed to by \e pcBuf. The characters will
+//! continue to be stored until a termination character is received. The
+//! termination characters are CR, LF, or ESC. A CRLF pair is treated as a
+//! single termination character. The termination characters are not stored in
+//! the string. The string will be terminated with a 0 and the function will
+//! return.
+//!
+//! In both buffered and unbuffered modes, this function will block until
+//! a termination character is received. If non-blocking operation is required
+//! in buffered mode, a call to UARTPeek() may be made to determine whether
+//! a termination character already exists in the receive buffer prior to
+//! calling UARTgets().
+//!
+//! Since the string will be null terminated, the user must ensure that the
+//! buffer is sized to allow for the additional null character.
+//!
+//! \return Returns the count of characters that were stored, not including
+//! the trailing 0.
+//
+//*****************************************************************************
+int
+UARTgets(char *pcBuf, uint32_t ui32Len)
+{
+#ifdef UART_BUFFERED
+ uint32_t ui32Count = 0;
+ int8_t cChar;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(pcBuf != 0);
+ ASSERT(ui32Len != 0);
+ ASSERT(g_ui32Base != 0);
+
+ //
+ // Adjust the length back by 1 to leave space for the trailing
+ // null terminator.
+ //
+ ui32Len--;
+
+ //
+ // Process characters until a newline is received.
+ //
+ while(1)
+ {
+ //
+ // Read the next character from the receive buffer.
+ //
+ if(!RX_BUFFER_EMPTY)
+ {
+ cChar = g_pcUARTRxBuffer[g_ui32UARTRxReadIndex];
+ ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxReadIndex);
+
+ //
+ // See if a newline or escape character was received.
+ //
+ if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b))
+ {
+ //
+ // Stop processing the input and end the line.
+ //
+ break;
+ }
+
+ //
+ // Process the received character as long as we are not at the end
+ // of the buffer. If the end of the buffer has been reached then
+ // all additional characters are ignored until a newline is
+ // received.
+ //
+ if(ui32Count < ui32Len)
+ {
+ //
+ // Store the character in the caller supplied buffer.
+ //
+ pcBuf[ui32Count] = cChar;
+
+ //
+ // Increment the count of characters received.
+ //
+ ui32Count++;
+ }
+ }
+ }
+
+ //
+ // Add a null termination to the string.
+ //
+ pcBuf[ui32Count] = 0;
+
+ //
+ // Return the count of int8_ts in the buffer, not counting the trailing 0.
+ //
+ return(ui32Count);
+#else
+ uint32_t ui32Count = 0;
+ int8_t cChar;
+ static int8_t bLastWasCR = 0;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(pcBuf != 0);
+ ASSERT(ui32Len != 0);
+ ASSERT(g_ui32Base != 0);
+
+ //
+ // Adjust the length back by 1 to leave space for the trailing
+ // null terminator.
+ //
+ ui32Len--;
+
+ //
+ // Process characters until a newline is received.
+ //
+ while(1)
+ {
+ //
+ // Read the next character from the console.
+ //
+ cChar = MAP_UARTCharGet(g_ui32Base);
+
+ //
+ // See if the backspace key was pressed.
+ //
+ if(cChar == '\b')
+ {
+ //
+ // If there are any characters already in the buffer, then delete
+ // the last.
+ //
+ if(ui32Count)
+ {
+ //
+ // Rub out the previous character.
+ //
+ UARTwrite("\b \b", 3);
+
+ //
+ // Decrement the number of characters in the buffer.
+ //
+ ui32Count--;
+ }
+
+ //
+ // Skip ahead to read the next character.
+ //
+ continue;
+ }
+
+ //
+ // If this character is LF and last was CR, then just gobble up the
+ // character because the EOL processing was taken care of with the CR.
+ //
+ if((cChar == '\n') && bLastWasCR)
+ {
+ bLastWasCR = 0;
+ continue;
+ }
+
+ //
+ // See if a newline or escape character was received.
+ //
+ if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b))
+ {
+ //
+ // If the character is a CR, then it may be followed by a LF which
+ // should be paired with the CR. So remember that a CR was
+ // received.
+ //
+ if(cChar == '\r')
+ {
+ bLastWasCR = 1;
+ }
+
+ //
+ // Stop processing the input and end the line.
+ //
+ break;
+ }
+
+ //
+ // Process the received character as long as we are not at the end of
+ // the buffer. If the end of the buffer has been reached then all
+ // additional characters are ignored until a newline is received.
+ //
+ if(ui32Count < ui32Len)
+ {
+ //
+ // Store the character in the caller supplied buffer.
+ //
+ pcBuf[ui32Count] = cChar;
+
+ //
+ // Increment the count of characters received.
+ //
+ ui32Count++;
+
+ //
+ // Reflect the character back to the user.
+ //
+ MAP_UARTCharPut(g_ui32Base, cChar);
+ }
+ }
+
+ //
+ // Add a null termination to the string.
+ //
+ pcBuf[ui32Count] = 0;
+
+ //
+ // Send a CRLF pair to the terminal to end the line.
+ //
+ UARTwrite("\r\n", 2);
+
+ //
+ // Return the count of int8_ts in the buffer, not counting the trailing 0.
+ //
+ return(ui32Count);
+#endif
+}
+
+//*****************************************************************************
+//
+//! Read a single character from the UART, blocking if necessary.
+//!
+//! This function will receive a single character from the UART and store it at
+//! the supplied address.
+//!
+//! In both buffered and unbuffered modes, this function will block until a
+//! character is received. If non-blocking operation is required in buffered
+//! mode, a call to UARTRxAvail() may be made to determine whether any
+//! characters are currently available for reading.
+//!
+//! \return Returns the character read.
+//
+//*****************************************************************************
+unsigned char
+UARTgetc(void)
+{
+#ifdef UART_BUFFERED
+ unsigned char cChar;
+
+ //
+ // Wait for a character to be received.
+ //
+ while(RX_BUFFER_EMPTY)
+ {
+ //
+ // Block waiting for a character to be received (if the buffer is
+ // currently empty).
+ //
+ }
+
+ //
+ // Read a character from the buffer.
+ //
+ cChar = g_pcUARTRxBuffer[g_ui32UARTRxReadIndex];
+ ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxReadIndex);
+
+ //
+ // Return the character to the caller.
+ //
+ return(cChar);
+#else
+ //
+ // Block until a character is received by the UART then return it to
+ // the caller.
+ //
+ return(MAP_UARTCharGet(g_ui32Base));
+#endif
+}
+
+//*****************************************************************************
+//
+//! A simple UART based vprintf function supporting \%c, \%d, \%p, \%s, \%u,
+//! \%x, and \%X.
+//!
+//! \param pcString is the format string.
+//! \param vaArgP is a variable argument list pointer whose content will depend
+//! upon the format string passed in \e pcString.
+//!
+//! This function is very similar to the C library <tt>vprintf()</tt> function.
+//! All of its output will be sent to the UART. Only the following formatting
+//! characters are supported:
+//!
+//! - \%c to print a character
+//! - \%d or \%i to print a decimal value
+//! - \%s to print a string
+//! - \%u to print an unsigned decimal value
+//! - \%x to print a hexadecimal value using lower case letters
+//! - \%X to print a hexadecimal value using lower case letters (not upper case
+//! letters as would typically be used)
+//! - \%p to print a pointer as a hexadecimal value
+//! - \%\% to print out a \% character
+//!
+//! For \%s, \%d, \%i, \%u, \%p, \%x, and \%X, an optional number may reside
+//! between the \% and the format character, which specifies the minimum number
+//! of characters to use for that value; if preceded by a 0 then the extra
+//! characters will be filled with zeros instead of spaces. For example,
+//! ``\%8d'' will use eight characters to print the decimal value with spaces
+//! added to reach eight; ``\%08d'' will use eight characters as well but will
+//! add zeroes instead of spaces.
+//!
+//! The type of the arguments in the variable arguments list must match the
+//! requirements of the format string. For example, if an integer was passed
+//! where a string was expected, an error of some kind will most likely occur.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTvprintf(const char *pcString, va_list vaArgP)
+{
+ uint32_t ui32Idx, ui32Value, ui32Pos, ui32Count, ui32Base, ui32Neg;
+ char *pcStr, pcBuf[16], cFill;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(pcString != 0);
+
+ //
+ // Loop while there are more characters in the string.
+ //
+ while(*pcString)
+ {
+ //
+ // Find the first non-% character, or the end of the string.
+ //
+ for(ui32Idx = 0;
+ (pcString[ui32Idx] != '%') && (pcString[ui32Idx] != '\0');
+ ui32Idx++)
+ {
+ }
+
+ //
+ // Write this portion of the string.
+ //
+ UARTwrite(pcString, ui32Idx);
+
+ //
+ // Skip the portion of the string that was written.
+ //
+ pcString += ui32Idx;
+
+ //
+ // See if the next character is a %.
+ //
+ if(*pcString == '%')
+ {
+ //
+ // Skip the %.
+ //
+ pcString++;
+
+ //
+ // Set the digit count to zero, and the fill character to space
+ // (in other words, to the defaults).
+ //
+ ui32Count = 0;
+ cFill = ' ';
+
+ //
+ // It may be necessary to get back here to process more characters.
+ // Goto's aren't pretty, but effective. I feel extremely dirty for
+ // using not one but two of the beasts.
+ //
+again:
+
+ //
+ // Determine how to handle the next character.
+ //
+ switch(*pcString++)
+ {
+ //
+ // Handle the digit characters.
+ //
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ //
+ // If this is a zero, and it is the first digit, then the
+ // fill character is a zero instead of a space.
+ //
+ if((pcString[-1] == '0') && (ui32Count == 0))
+ {
+ cFill = '0';
+ }
+
+ //
+ // Update the digit count.
+ //
+ ui32Count *= 10;
+ ui32Count += pcString[-1] - '0';
+
+ //
+ // Get the next character.
+ //
+ goto again;
+ }
+
+ //
+ // Handle the %c command.
+ //
+ case 'c':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ui32Value = va_arg(vaArgP, uint32_t);
+
+ //
+ // Print out the character.
+ //
+ UARTwrite((char *)&ui32Value, 1);
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %d and %i commands.
+ //
+ case 'd':
+ case 'i':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ui32Value = va_arg(vaArgP, uint32_t);
+
+ //
+ // Reset the buffer position.
+ //
+ ui32Pos = 0;
+
+ //
+ // If the value is negative, make it positive and indicate
+ // that a minus sign is needed.
+ //
+ if((int32_t)ui32Value < 0)
+ {
+ //
+ // Make the value positive.
+ //
+ ui32Value = -(int32_t)ui32Value;
+
+ //
+ // Indicate that the value is negative.
+ //
+ ui32Neg = 1;
+ }
+ else
+ {
+ //
+ // Indicate that the value is positive so that a minus
+ // sign isn't inserted.
+ //
+ ui32Neg = 0;
+ }
+
+ //
+ // Set the base to 10.
+ //
+ ui32Base = 10;
+
+ //
+ // Convert the value to ASCII.
+ //
+ goto convert;
+ }
+
+ //
+ // Handle the %s command.
+ //
+ case 's':
+ {
+ //
+ // Get the string pointer from the varargs.
+ //
+ pcStr = va_arg(vaArgP, char *);
+
+ //
+ // Determine the length of the string.
+ //
+ for(ui32Idx = 0; pcStr[ui32Idx] != '\0'; ui32Idx++)
+ {
+ }
+
+ //
+ // Write the string.
+ //
+ UARTwrite(pcStr, ui32Idx);
+
+ //
+ // Write any required padding spaces
+ //
+ if(ui32Count > ui32Idx)
+ {
+ ui32Count -= ui32Idx;
+ while(ui32Count--)
+ {
+ UARTwrite(" ", 1);
+ }
+ }
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %u command.
+ //
+ case 'u':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ui32Value = va_arg(vaArgP, uint32_t);
+
+ //
+ // Reset the buffer position.
+ //
+ ui32Pos = 0;
+
+ //
+ // Set the base to 10.
+ //
+ ui32Base = 10;
+
+ //
+ // Indicate that the value is positive so that a minus sign
+ // isn't inserted.
+ //
+ ui32Neg = 0;
+
+ //
+ // Convert the value to ASCII.
+ //
+ goto convert;
+ }
+
+ //
+ // Handle the %x and %X commands. Note that they are treated
+ // identically; in other words, %X will use lower case letters
+ // for a-f instead of the upper case letters it should use. We
+ // also alias %p to %x.
+ //
+ case 'x':
+ case 'X':
+ case 'p':
+ {
+ //
+ // Get the value from the varargs.
+ //
+ ui32Value = va_arg(vaArgP, uint32_t);
+
+ //
+ // Reset the buffer position.
+ //
+ ui32Pos = 0;
+
+ //
+ // Set the base to 16.
+ //
+ ui32Base = 16;
+
+ //
+ // Indicate that the value is positive so that a minus sign
+ // isn't inserted.
+ //
+ ui32Neg = 0;
+
+ //
+ // Determine the number of digits in the string version of
+ // the value.
+ //
+convert:
+ for(ui32Idx = 1;
+ (((ui32Idx * ui32Base) <= ui32Value) &&
+ (((ui32Idx * ui32Base) / ui32Base) == ui32Idx));
+ ui32Idx *= ui32Base, ui32Count--)
+ {
+ }
+
+ //
+ // If the value is negative, reduce the count of padding
+ // characters needed.
+ //
+ if(ui32Neg)
+ {
+ ui32Count--;
+ }
+
+ //
+ // If the value is negative and the value is padded with
+ // zeros, then place the minus sign before the padding.
+ //
+ if(ui32Neg && (cFill == '0'))
+ {
+ //
+ // Place the minus sign in the output buffer.
+ //
+ pcBuf[ui32Pos++] = '-';
+
+ //
+ // The minus sign has been placed, so turn off the
+ // negative flag.
+ //
+ ui32Neg = 0;
+ }
+
+ //
+ // Provide additional padding at the beginning of the
+ // string conversion if needed.
+ //
+ if((ui32Count > 1) && (ui32Count < 16))
+ {
+ for(ui32Count--; ui32Count; ui32Count--)
+ {
+ pcBuf[ui32Pos++] = cFill;
+ }
+ }
+
+ //
+ // If the value is negative, then place the minus sign
+ // before the number.
+ //
+ if(ui32Neg)
+ {
+ //
+ // Place the minus sign in the output buffer.
+ //
+ pcBuf[ui32Pos++] = '-';
+ }
+
+ //
+ // Convert the value into a string.
+ //
+ for(; ui32Idx; ui32Idx /= ui32Base)
+ {
+ pcBuf[ui32Pos++] =
+ g_pcHex[(ui32Value / ui32Idx) % ui32Base];
+ }
+
+ //
+ // Write the string.
+ //
+ UARTwrite(pcBuf, ui32Pos);
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle the %% command.
+ //
+ case '%':
+ {
+ //
+ // Simply write a single %.
+ //
+ UARTwrite(pcString - 1, 1);
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+
+ //
+ // Handle all other commands.
+ //
+ default:
+ {
+ //
+ // Indicate an error.
+ //
+ UARTwrite("ERROR", 5);
+
+ //
+ // This command has been handled.
+ //
+ break;
+ }
+ }
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! A simple UART based printf function supporting \%c, \%d, \%p, \%s, \%u,
+//! \%x, and \%X.
+//!
+//! \param pcString is the format string.
+//! \param ... are the optional arguments, which depend on the contents of the
+//! format string.
+//!
+//! This function is very similar to the C library <tt>fprintf()</tt> function.
+//! All of its output will be sent to the UART. Only the following formatting
+//! characters are supported:
+//!
+//! - \%c to print a character
+//! - \%d or \%i to print a decimal value
+//! - \%s to print a string
+//! - \%u to print an unsigned decimal value
+//! - \%x to print a hexadecimal value using lower case letters
+//! - \%X to print a hexadecimal value using lower case letters (not upper case
+//! letters as would typically be used)
+//! - \%p to print a pointer as a hexadecimal value
+//! - \%\% to print out a \% character
+//!
+//! For \%s, \%d, \%i, \%u, \%p, \%x, and \%X, an optional number may reside
+//! between the \% and the format character, which specifies the minimum number
+//! of characters to use for that value; if preceded by a 0 then the extra
+//! characters will be filled with zeros instead of spaces. For example,
+//! ``\%8d'' will use eight characters to print the decimal value with spaces
+//! added to reach eight; ``\%08d'' will use eight characters as well but will
+//! add zeroes instead of spaces.
+//!
+//! The type of the arguments after \e pcString must match the requirements of
+//! the format string. For example, if an integer was passed where a string
+//! was expected, an error of some kind will most likely occur.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTprintf(const char *pcString, ...)
+{
+ va_list vaArgP;
+
+ //
+ // Start the varargs processing.
+ //
+ va_start(vaArgP, pcString);
+
+ UARTvprintf(pcString, vaArgP);
+
+ //
+ // We're finished with the varargs now.
+ //
+ va_end(vaArgP);
+}
+
+//*****************************************************************************
+//
+//! Returns the number of bytes available in the receive buffer.
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to determine the number
+//! of bytes of data currently available in the receive buffer.
+//!
+//! \return Returns the number of available bytes.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+int
+UARTRxBytesAvail(void)
+{
+ return(RX_BUFFER_USED);
+}
+#endif
+
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+//*****************************************************************************
+//
+//! Returns the number of bytes free in the transmit buffer.
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to determine the amount
+//! of space currently available in the transmit buffer.
+//!
+//! \return Returns the number of free bytes.
+//
+//*****************************************************************************
+int
+UARTTxBytesFree(void)
+{
+ return(TX_BUFFER_FREE);
+}
+#endif
+
+//*****************************************************************************
+//
+//! Looks ahead in the receive buffer for a particular character.
+//!
+//! \param ucChar is the character that is to be searched for.
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to look ahead in the
+//! receive buffer for a particular character and report its position if found.
+//! It is typically used to determine whether a complete line of user input is
+//! available, in which case ucChar should be set to CR ('\\r') which is used
+//! as the line end marker in the receive buffer.
+//!
+//! \return Returns -1 to indicate that the requested character does not exist
+//! in the receive buffer. Returns a non-negative number if the character was
+//! found in which case the value represents the position of the first instance
+//! of \e ucChar relative to the receive buffer read pointer.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+int
+UARTPeek(unsigned char ucChar)
+{
+ int iCount;
+ int iAvail;
+ uint32_t ui32ReadIndex;
+
+ //
+ // How many characters are there in the receive buffer?
+ //
+ iAvail = (int)RX_BUFFER_USED;
+ ui32ReadIndex = g_ui32UARTRxReadIndex;
+
+ //
+ // Check all the unread characters looking for the one passed.
+ //
+ for(iCount = 0; iCount < iAvail; iCount++)
+ {
+ if(g_pcUARTRxBuffer[ui32ReadIndex] == ucChar)
+ {
+ //
+ // We found it so return the index
+ //
+ return(iCount);
+ }
+ else
+ {
+ //
+ // This one didn't match so move on to the next character.
+ //
+ ADVANCE_RX_BUFFER_INDEX(ui32ReadIndex);
+ }
+ }
+
+ //
+ // If we drop out of the loop, we didn't find the character in the receive
+ // buffer.
+ //
+ return(-1);
+}
+#endif
+
+//*****************************************************************************
+//
+//! Flushes the receive buffer.
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to discard any data
+//! received from the UART but not yet read using UARTgets().
+//!
+//! \return None.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+void
+UARTFlushRx(void)
+{
+ uint32_t ui32Int;
+
+ //
+ // Temporarily turn off interrupts.
+ //
+ ui32Int = MAP_IntMasterDisable();
+
+ //
+ // Flush the receive buffer.
+ //
+ g_ui32UARTRxReadIndex = 0;
+ g_ui32UARTRxWriteIndex = 0;
+
+ //
+ // If interrupts were enabled when we turned them off, turn them
+ // back on again.
+ //
+ if(!ui32Int)
+ {
+ MAP_IntMasterEnable();
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+//! Flushes the transmit buffer.
+//!
+//! \param bDiscard indicates whether any remaining data in the buffer should
+//! be discarded (\b true) or transmitted (\b false).
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to flush the transmit
+//! buffer, either discarding or transmitting any data received via calls to
+//! UARTprintf() that is waiting to be transmitted. On return, the transmit
+//! buffer will be empty.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+void
+UARTFlushTx(bool bDiscard)
+{
+ uint32_t ui32Int;
+
+ //
+ // Should the remaining data be discarded or transmitted?
+ //
+ if(bDiscard)
+ {
+ //
+ // The remaining data should be discarded, so temporarily turn off
+ // interrupts.
+ //
+ ui32Int = MAP_IntMasterDisable();
+
+ //
+ // Flush the transmit buffer.
+ //
+ g_ui32UARTTxReadIndex = 0;
+ g_ui32UARTTxWriteIndex = 0;
+
+ //
+ // If interrupts were enabled when we turned them off, turn them
+ // back on again.
+ //
+ if(!ui32Int)
+ {
+ MAP_IntMasterEnable();
+ }
+ }
+ else
+ {
+ //
+ // Wait for all remaining data to be transmitted before returning.
+ //
+ while(!TX_BUFFER_EMPTY)
+ {
+ }
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+//! Enables or disables echoing of received characters to the transmitter.
+//!
+//! \param bEnable must be set to \b true to enable echo or \b false to
+//! disable it.
+//!
+//! This function, available only when the module is built to operate in
+//! buffered mode using \b UART_BUFFERED, may be used to control whether or not
+//! received characters are automatically echoed back to the transmitter. By
+//! default, echo is enabled and this is typically the desired behavior if
+//! the module is being used to support a serial command line. In applications
+//! where this module is being used to provide a convenient, buffered serial
+//! interface over which application-specific binary protocols are being run,
+//! however, echo may be undesirable and this function can be used to disable
+//! it.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+void
+UARTEchoSet(bool bEnable)
+{
+ g_bDisableEcho = !bEnable;
+}
+#endif
+
+//*****************************************************************************
+//
+//! Handles UART interrupts.
+//!
+//! This function handles interrupts from the UART. It will copy data from the
+//! transmit buffer to the UART transmit FIFO if space is available, and it
+//! will copy data from the UART receive FIFO to the receive buffer if data is
+//! available.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#if defined(UART_BUFFERED) || defined(DOXYGEN)
+void
+UARTStdioIntHandler(void)
+{
+ uint32_t ui32Ints;
+ int8_t cChar;
+ int32_t i32Char;
+ static bool bLastWasCR = false;
+
+ //
+ // Get and clear the current interrupt source(s)
+ //
+ ui32Ints = MAP_UARTIntStatus(g_ui32Base, true);
+ MAP_UARTIntClear(g_ui32Base, 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.
+ //
+ UARTPrimeTransmit(g_ui32Base);
+
+ //
+ // If the output buffer is empty, turn off the transmit interrupt.
+ //
+ if(TX_BUFFER_EMPTY)
+ {
+ MAP_UARTIntDisable(g_ui32Base, UART_INT_TX);
+ }
+ }
+
+ //
+ // Are we being interrupted due to a received character?
+ //
+ if(ui32Ints & (UART_INT_RX | UART_INT_RT))
+ {
+ //
+ // Get all the available characters from the UART.
+ //
+ while(MAP_UARTCharsAvail(g_ui32Base))
+ {
+ //
+ // Read a character
+ //
+ i32Char = MAP_UARTCharGetNonBlocking(g_ui32Base);
+ cChar = (unsigned char)(i32Char & 0xFF);
+
+ //
+ // If echo is disabled, we skip the various text filtering
+ // operations that would typically be required when supporting a
+ // command line.
+ //
+ if(!g_bDisableEcho)
+ {
+ //
+ // Handle backspace by erasing the last character in the
+ // buffer.
+ //
+ if(cChar == '\b')
+ {
+ //
+ // If there are any characters already in the buffer, then
+ // delete the last.
+ //
+ if(!RX_BUFFER_EMPTY)
+ {
+ //
+ // Rub out the previous character on the users
+ // terminal.
+ //
+ UARTwrite("\b \b", 3);
+
+ //
+ // Decrement the number of characters in the buffer.
+ //
+ if(g_ui32UARTRxWriteIndex == 0)
+ {
+ g_ui32UARTRxWriteIndex = UART_RX_BUFFER_SIZE - 1;
+ }
+ else
+ {
+ g_ui32UARTRxWriteIndex--;
+ }
+ }
+
+ //
+ // Skip ahead to read the next character.
+ //
+ continue;
+ }
+
+ //
+ // If this character is LF and last was CR, then just gobble up
+ // the character since we already echoed the previous CR and we
+ // don't want to store 2 characters in the buffer if we don't
+ // need to.
+ //
+ if((cChar == '\n') && bLastWasCR)
+ {
+ bLastWasCR = false;
+ continue;
+ }
+
+ //
+ // See if a newline or escape character was received.
+ //
+ if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b))
+ {
+ //
+ // If the character is a CR, then it may be followed by an
+ // LF which should be paired with the CR. So remember that
+ // a CR was received.
+ //
+ if(cChar == '\r')
+ {
+ bLastWasCR = 1;
+ }
+
+ //
+ // Regardless of the line termination character received,
+ // put a CR in the receive buffer as a marker telling
+ // UARTgets() where the line ends. We also send an
+ // additional LF to ensure that the local terminal echo
+ // receives both CR and LF.
+ //
+ cChar = '\r';
+ UARTwrite("\n", 1);
+ }
+ }
+
+ //
+ // If there is space in the receive buffer, put the character
+ // there, otherwise throw it away.
+ //
+ if(!RX_BUFFER_FULL)
+ {
+ //
+ // Store the new character in the receive buffer
+ //
+ g_pcUARTRxBuffer[g_ui32UARTRxWriteIndex] =
+ (unsigned char)(i32Char & 0xFF);
+ ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxWriteIndex);
+
+ //
+ // If echo is enabled, write the character to the transmit
+ // buffer so that the user gets some immediate feedback.
+ //
+ if(!g_bDisableEcho)
+ {
+ UARTwrite((const char *)&cChar, 1);
+ }
+ }
+ }
+
+ //
+ // If we wrote anything to the transmit buffer, make sure it actually
+ // gets transmitted.
+ //
+ UARTPrimeTransmit(g_ui32Base);
+ MAP_UARTIntEnable(g_ui32Base, UART_INT_TX);
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
|
