//***************************************************************************** -1-

Similar documents
UART. Introduction. Agenda

Variables Data types Variable I/O. C introduction. Variables. Variables 1 / 14

Programming I 2 S on the Stellaris Microcontroller

CS102: Standard I/O. %<flag(s)><width><precision><size>conversion-code

LM3S5732 ROM USER S GUIDE ROM-LM3S5732-UG-461. Copyright Texas Instruments Incorporated

DECLARATIONS. Character Set, Keywords, Identifiers, Constants, Variables. Designed by Parul Khurana, LIECA.

Arithmetic and Bitwise Operations on Binary Data

ITC213: STRUCTURED PROGRAMMING. Bhaskar Shrestha National College of Computer Studies Tribhuvan University

C How to Program, 6/e by Pearson Education, Inc. All Rights Reserved.

LM3S2D93 ROM USER S GUIDE ROM-LM3S2D93-UG-461. Copyright Texas Instruments Incorporated

Goals of C "" The Goals of C (cont.) "" Goals of this Lecture"" The Design of C: A Rational Reconstruction"

Programming in C++ 4. The lexical basis of C++

Binghamton University. CS-211 Fall Syntax. What the Compiler needs to understand your program

Preliminary File System User Manual

CYSE 411/AIT681 Secure Software Engineering Topic #12. Secure Coding: Formatted Output

2/9/18. CYSE 411/AIT681 Secure Software Engineering. Readings. Secure Coding. This lecture: String management Pointer Subterfuge

Version N 2.0. LaurTec. RS232 Terminal. Debugging Embedded Systems. Author : Mauro Laurenti ID: PJ11004-EN. Copyright Mauro Laurenti 1/33

Expressions and Data Types CSC 121 Spring 2015 Howard Rosenthal

ME 461 C review Session Fall 2009 S. Keres

Stream Model of I/O. Basic I/O in C

C Language Part 1 Digital Computer Concept and Practice Copyright 2012 by Jaejin Lee

TI ARM Lab 6 UART (without Interrupt)

LM3S9D81 ROM USER S GUIDE ROM-LM3S9D81-UG-461. Copyright Texas Instruments Incorporated

Unit 4. Input/Output Functions

ECE 598 Advanced Operating Systems Lecture 6

1602 SMART LCD DISPLAY MODULE HCMODU0122

ECE 598 Advanced Operating Systems Lecture 6

UNIT - I. Introduction to C Programming. BY A. Vijay Bharath

Rule 1-3: Use white space to break a function into paragraphs. Rule 1-5: Avoid very long statements. Use multiple shorter statements instead.

PICkit Serial DLL (PICkitS.dll) Function Prototypes

CMPT 102 Introduction to Scientific Computer Programming. Input and Output. Your first program

Arithmetic and Bitwise Operations on Binary Data

C OVERVIEW BASIC C PROGRAM STRUCTURE. C Overview. Basic C Program Structure

A Fast Review of C Essentials Part I

EDIABAS BEST/2 LANGUAGE DESCRIPTION. VERSION 6b. Electronic Diagnostic Basic System EDIABAS - BEST/2 LANGUAGE DESCRIPTION

C OVERVIEW. C Overview. Goals speed portability allow access to features of the architecture speed

PICkit Serial DLL (PICkitS.dll) Function Prototypes

Introduction to C Language

LM3S6G11 ROM USER S GUIDE ROM-LM3S6G11-UG-461. Copyright Texas Instruments Incorporated

InfoTag KE28xx Communications for 186 CPU Firmware Version 4

Lecture 02 C FUNDAMENTALS

Serial to Ethernet Converter

The Design of C: A Rational Reconstruction (cont.)

Outline. Computer Programming. Preprocessing in C. File inclusion. Preprocessing in C

C: How to Program. Week /Mar/05

Arduino Uno. Power & Interface. Arduino Part 1. Introductory Medical Device Prototyping. Digital I/O Pins. Reset Button. USB Interface.

AppHeader User s Guide Version 1.0

Why embedded systems?

Expressions and Data Types CSC 121 Fall 2015 Howard Rosenthal

Review of the C Programming Language for Principles of Operating Systems

CS16 Exam #1 7/17/ Minutes 100 Points total

The C Programming Language Guide for the Robot Course work Module

ICN12. I2C to UART Bridge, ADC,DAC and I/O

srl - shift right logical - 0 enters from left, bit drops off right end note: little-endian bit notation msb lsb "b" for bit

AWK - PRETTY PRINTING

Should you know scanf and printf?

printf( Please enter another number: ); scanf( %d, &num2);

Chapter 2 - Introduction to C Programming

Handout 7, Lex (5/30/2001)

AT03262: SAM D/R/L/C System Pin Multiplexer (SYSTEM PINMUX) Driver. Introduction. SMART ARM-based Microcontrollers APPLICATION NOTE

ISPV3 Programmer s Guide. This guide addresses the features, setup and operation of the CRD89C51xxx microcontrollers with ISPV3 firmware.

File Handling in C. EECS 2031 Fall October 27, 2014

GSE Scale Systems M660 CUSTOM TRANSMIT

Using printf with an AVR

Standard File Pointers

Introduction to C# Applications

PMBus Power System Management Protocol Specification Part I General Requirements, Transport And Electrical Interface

Room 3P16 Telephone: extension ~irjohnson/uqc146s1.html

Topic 6: A Quick Intro To C

Fundamentals of Programming. Lecture 11: C Characters and Strings

PCI GS or PCIe8 LX Time Distribution Board

C mini reference. 5 Binary numbers 12

C Fundamentals & Formatted Input/Output. adopted from KNK C Programming : A Modern Approach

Bits, Words, and Integers

Fundamental of Programming (C)

Basic program The following is a basic program in C++; Basic C++ Source Code Compiler Object Code Linker (with libraries) Executable

CS102: Variables and Expressions

BV4626 General Purpose I/O. Product specification. Mar 2010 V0.a. ByVac Page 1 of 13

Topic 6: A Quick Intro To C. Reading. "goto Considered Harmful" History

Using LPC11Axx EEPROM (with IAP)

Reserved Words and Identifiers

INTRODUCTION 1 AND REVIEW

VARIABLES AND CONSTANTS

Section 31. DMA Controller

Advanced C Programming Topics

AN5179. RS232 communications with a terminal using the STM8 Nucleo-64 boards. Application note. Introduction

LESSON 4. The DATA TYPE char

Network Working Group Request for Comments: 205 NIC: August 1971

Lecture 3. More About C

Syntax and Variables

Object oriented programming. Instructor: Masoud Asghari Web page: Ch: 3

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

CS164: Programming Assignment 2 Dlex Lexer Generator and Decaf Lexer

ANSI C Programming Simple Programs

An overview of Java, Data types and variables

SAM4 Reset Controller (RSTC)

The Design of C: A Rational Reconstruction (cont.)" Jennifer Rexford!

CS 33. Data Representation, Part 1. CS33 Intro to Computer Systems VII 1 Copyright 2017 Thomas W. Doeppner. All rights reserved.

Tools : The Java Compiler. The Java Interpreter. The Java Debugger

SAINT2. System Analysis Interface Tool 2. Emulation User Guide. Version 2.5. May 27, Copyright Delphi Automotive Systems Corporation 2009, 2010

Transcription:

***************************************************************************** uartstdio.c - Utility driver to provide simple UART console functions. Copyright (c) 2007-2011 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 8049 of the Stellaris Firmware Development Package. ***************************************************************************** #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 ***************************************************************************** -1-

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 tboolean g_bdisableecho; ***************************************************************************** Output ring buffer. Buffer is full if g_uluarttxreadindex is one ahead of g_uluarttxwriteindex. Buffer is empty if the two indices are the same. ***************************************************************************** static unsigned char g_pcuarttxbuffer[uart_tx_buffer_size]; static volatile unsigned long g_uluarttxwriteindex = 0; static volatile unsigned long g_uluarttxreadindex = 0; ***************************************************************************** Input ring buffer. Buffer is full if g_uluarttxreadindex is one ahead of g_uluarttxwriteindex. Buffer is empty if the two indices are the same. ***************************************************************************** static unsigned char g_pcuartrxbuffer[uart_rx_buffer_size]; static volatile unsigned long g_uluartrxwriteindex = 0; static volatile unsigned long g_uluartrxreadindex = 0; ***************************************************************************** Macros to determine number of free and used bytes in the transmit buffer. ***************************************************************************** #define TX_BUFFER_USED (GetBufferCount(&g_ulUARTTxReadIndex, \ &g_uluarttxwriteindex, \ UART_TX_BUFFER_SIZE)) #define TX_BUFFER_FREE (UART_TX_BUFFER_SIZE - TX_BUFFER_USED) #define TX_BUFFER_EMPTY (IsBufferEmpty(&g_ulUARTTxReadIndex, \ &g_uluarttxwriteindex)) #define TX_BUFFER_FULL (IsBufferFull(&g_ulUARTTxReadIndex, \ &g_uluarttxwriteindex, \ 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_ulUARTRxReadIndex, \ -2-

&g_uluartrxwriteindex, \ UART_RX_BUFFER_SIZE)) #define RX_BUFFER_FREE (UART_RX_BUFFER_SIZE - RX_BUFFER_USED) #define RX_BUFFER_EMPTY (IsBufferEmpty(&g_ulUARTRxReadIndex, \ &g_uluartrxwriteindex)) #define RX_BUFFER_FULL (IsBufferFull(&g_ulUARTRxReadIndex, \ &g_uluartrxwriteindex, \ UART_RX_BUFFER_SIZE)) #define ADVANCE_RX_BUFFER_INDEX(Index) \ (Index) = ((Index) + 1) % UART_RX_BUFFER_SIZE ***************************************************************************** The base address of the chosen UART. ***************************************************************************** static unsigned long g_ulbase = 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 unsigned long g_uluartbase[3] = UART0_BASE, UART1_BASE, UART2_BASE ; #ifdef UART_BUFFERED ***************************************************************************** The list of possible interrupts for the console UART. ***************************************************************************** static const unsigned long g_uluartint[3] = INT_UART0, INT_UART1, INT_UART2 ; ***************************************************************************** The port number in use. ***************************************************************************** -3-

static unsigned long g_ulportnum; ***************************************************************************** The list of UART peripherals. ***************************************************************************** static const unsigned long g_uluartperiph[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 pulread points to the read index for the buffer.! \param pulwrite points to the write index for the buffer.! \param ulsize 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 tboolean IsBufferFull(volatile unsigned long *pulread, volatile unsigned long *pulwrite, unsigned long ulsize) unsigned long ulwrite; unsigned long ulread; ulwrite = *pulwrite; ulread = *pulread; return((((ulwrite + 1) % ulsize) == ulread)? true : false); *****************************************************************************! Determines whether the ring buffer whose pointers and size are provided! is empty or not.!! \param pulread points to the read index for the buffer.! \param pulwrite points to the write index for the buffer.! -4-

! 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 tboolean IsBufferEmpty(volatile unsigned long *pulread, volatile unsigned long *pulwrite) unsigned long ulwrite; unsigned long ulread; ulwrite = *pulwrite; ulread = *pulread; return((ulwrite == ulread)? true : false); *****************************************************************************! Determines the number of bytes of data contained in a ring buffer.!! \param pulread points to the read index for the buffer.! \param pulwrite points to the write index for the buffer.! \param ulsize 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 unsigned long GetBufferCount(volatile unsigned long *pulread, volatile unsigned long *pulwrite, unsigned long ulsize) unsigned long ulwrite; unsigned long ulread; ulwrite = *pulwrite; ulread = *pulread; return((ulwrite >= ulread)? (ulwrite - ulread) : (ulsize - (ulread - ulwrite))); -5-

***************************************************************************** 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(unsigned long ulbase) 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_ulUARTInt[g_ulPortNum]); Yes - take some characters out of the transmit buffer and feed them to the UART transmit FIFO. while(map_uartspaceavail(ulbase) &&!TX_BUFFER_EMPTY) MAP_UARTCharPutNonBlocking(ulBase, g_pcuarttxbuffer[g_uluarttxreadindex]); ADVANCE_TX_BUFFER_INDEX(g_ulUARTTxReadIndex); Reenable the UART interrupt. MAP_IntEnable(g_ulUARTInt[g_ulPortNum]); *****************************************************************************! Initializes the UART console.!! \param ulportnum is the number of UART port to use for the serial console! (0-2)!! This function will initialize the specified serial port to be used as a! serial console. The serial parameters will be set to 115200, 8-N-1.! An application wishing to use a different baud rate may call! UARTStdioInitExpClk() instead of this function. -6-

!! This function or UARTStdioInitExpClk() must be called prior to using any! of the other UART console functions: UARTprintf() or UARTgets(). In order! for this function to work correctly, SysCtlClockSet() must be called prior! to calling this function.!! It is assumed that the caller has previously configured the relevant UART! pins for operation as a UART rather than as GPIOs.!! \return None. ***************************************************************************** void UARTStdioInit(unsigned long ulportnum) Pass this call on to the version of the function allowing the baud rate to be specified. UARTStdioInitExpClk(ulPortNum, 115200); *****************************************************************************! Initializes the UART console and allows the baud rate to be selected.!! \param ulportnum is the number of UART port to use for the serial console! (0-2)! \param ulbaud is the bit rate that the UART is to be configured to use.!! This function will initialize the specified serial port to be used as a! serial console. The serial parameters will be set to 8-N-1 and the bit! rate set according to the value of the \e ulbaud parameter.!! This function or UARTStdioInit() must be called prior to using any of the! other UART console functions: UARTprintf() or UARTgets(). In order for! this function to work correctly, SysCtlClockSet() must be called prior to! calling this function. An application wishing to use 115,200 baud may call! UARTStdioInit() instead of this function but should not call both! functions.!! It is assumed that the caller has previously configured the relevant UART! pins for operation as a UART rather than as GPIOs.!! \return None. ***************************************************************************** void UARTStdioInitExpClk(unsigned long ulportnum, unsigned long ulbaud) Check the arguments. -7-

ASSERT((ulPortNum == 0) (ulportnum == 1) (ulportnum == 2)); #ifdef UART_BUFFERED In buffered mode, we only allow a single instance to be opened. ASSERT(g_ulBase == 0); Check to make sure the UART peripheral is present. if(!map_sysctlperipheralpresent(g_uluartperiph[ulportnum])) return; Select the base address of the UART. g_ulbase = g_uluartbase[ulportnum]; Enable the UART peripheral for use. MAP_SysCtlPeripheralEnable(g_ulUARTPeriph[ulPortNum]); Configure the UART for 115200, n, 8, 1 MAP_UARTConfigSetExpClk(g_ulBase, MAP_SysCtlClockGet(), ulbaud, (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_ulBase, UART_FIFO_TX1_8, UART_FIFO_RX1_8); Flush both the buffers. UARTFlushRx(); UARTFlushTx(true); Remember which interrupt we are dealing with. g_ulportnum = ulportnum; -8-

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_ulBase, 0xFFFFFFFF); MAP_UARTIntEnable(g_ulBase, UART_INT_RX UART_INT_RT); MAP_IntEnable(g_ulUARTInt[ulPortNum]); Enable the UART operation. MAP_UARTEnable(g_ulBase); *****************************************************************************! Writes a string of characters to the UART output.!! \param pcbuf points to a buffer containing the string to transmit.! \param ullen 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 ullen 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 ullen 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, unsigned long ullen) #ifdef UART_BUFFERED unsigned int uidx; Check for valid arguments. ASSERT(pcBuf!= 0); -9-

ASSERT(g_ulBase!= 0); Send the characters for(uidx = 0; uidx < ullen; 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_uluarttxwriteindex] = '\r'; ADVANCE_TX_BUFFER_INDEX(g_ulUARTTxWriteIndex); else Buffer is full - discard remaining characters and return. break; Send the character to the UART output. if(!tx_buffer_full) g_pcuarttxbuffer[g_uluarttxwriteindex] = pcbuf[uidx]; ADVANCE_TX_BUFFER_INDEX(g_ulUARTTxWriteIndex); 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_ulBase); MAP_UARTIntEnable(g_ulBase, UART_INT_TX); -10-

Return the number of characters written. return(uidx); #else unsigned int uidx; Check for valid UART base address, and valid arguments. ASSERT(g_ulBase!= 0); ASSERT(pcBuf!= 0); Send the characters for(uidx = 0; uidx < ullen; 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_ulBase, '\r'); Send the character to the UART output. MAP_UARTCharPut(g_ulBase, pcbuf[uidx]); Return the number of characters written. return(uidx); *****************************************************************************! 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 ullen 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 -11-

! 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, unsigned long ullen) #ifdef UART_BUFFERED unsigned long ulcount = 0; char cchar; Check the arguments. ASSERT(pcBuf!= 0); ASSERT(ulLen!= 0); ASSERT(g_ulBase!= 0); Adjust the length back by 1 to leave space for the trailing null terminator. ullen--; 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_uluartrxreadindex]; ADVANCE_RX_BUFFER_INDEX(g_ulUARTRxReadIndex); See if a newline or escape character was received. -12-

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(ulcount < ullen) Store the character in the caller supplied buffer. pcbuf[ulcount] = cchar; Increment the count of characters received. ulcount++; Add a null termination to the string. pcbuf[ulcount] = 0; Return the count of chars in the buffer, not counting the trailing 0. return(ulcount); #else unsigned long ulcount = 0; char cchar; static char blastwascr = 0; Check the arguments. ASSERT(pcBuf!= 0); ASSERT(ulLen!= 0); ASSERT(g_ulBase!= 0); Adjust the length back by 1 to leave space for the trailing null terminator. -13-

ullen--; Process characters until a newline is received. while(1) Read the next character from the console. cchar = MAP_UARTCharGet(g_ulBase); See if the backspace key was pressed. if(cchar == '\b') If there are any characters already in the buffer, then delete the last. if(ulcount) Rub out the previous character. UARTwrite("\b \b", 3); Decrement the number of characters in the buffer. ulcount--; 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. -14-

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(ulcount < ullen) Store the character in the caller supplied buffer. pcbuf[ulcount] = cchar; Increment the count of characters received. ulcount++; Reflect the character back to the user. MAP_UARTCharPut(g_ulBase, cchar); Add a null termination to the string. pcbuf[ulcount] = 0; Send a CRLF pair to the terminal to end the line. UARTwrite("\r\n", 2); -15-

Return the count of chars in the buffer, not counting the trailing 0. return(ulcount); *****************************************************************************! 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_uluartrxreadindex]; ADVANCE_RX_BUFFER_INDEX(g_ulUARTRxReadIndex); Return the character to the caller. return(cchar); #else Block until a character is received by the UART then return it to the caller. -16-

return(map_uartcharget(g_ulbase)); *****************************************************************************! 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 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, \%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,...) unsigned long ulidx, ulvalue, ulpos, ulcount, ulbase, ulneg; char *pcstr, pcbuf[16], cfill; va_list vaargp; Check the arguments. -17-

ASSERT(pcString!= 0); Start the varargs processing. va_start(vaargp, pcstring); Loop while there are more characters in the string. while(*pcstring) Find the first non-% character, or the end of the string. for(ulidx = 0; (pcstring[ulidx]!= '%') && (pcstring[ulidx]!= '\0'); ulidx++) Write this portion of the string. UARTwrite(pcString, ulidx); Skip the portion of the string that was written. pcstring += ulidx; See if the next character is a %. if(*pcstring == '%') Skip the %. pcstring++; Set the digit count to zero, and the fill character to space (i.e. to the defaults). ulcount = 0; cfill = ' '; again: 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. -18-

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') && (ulcount == 0)) cfill = '0'; Update the digit count. ulcount *= 10; ulcount += pcstring[-1] - '0'; Get the next character. goto again; Handle the %c command. case 'c': Get the value from the varargs. ulvalue = va_arg(vaargp, unsigned long); Print out the character. -19-

UARTwrite((char *)&ulvalue, 1); This command has been handled. break; Handle the %d command. case 'd': Get the value from the varargs. ulvalue = va_arg(vaargp, unsigned long); Reset the buffer position. ulpos = 0; If the value is negative, make it positive and indicate that a minus sign is needed. if((long)ulvalue < 0) Make the value positive. ulvalue = -(long)ulvalue; Indicate that the value is negative. ulneg = 1; else Indicate that the value is positive so that a minus sign isn't inserted. ulneg = 0; Set the base to 10. ulbase = 10; -20-

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(ulidx = 0; pcstr[ulidx]!= '\0'; ulidx++) Write the string. UARTwrite(pcStr, ulidx); Write any required padding spaces if(ulcount > ulidx) ulcount -= ulidx; while(ulcount--) UARTwrite(" ", 1); This command has been handled. break; Handle the %u command. case 'u': Get the value from the varargs. -21-

ulvalue = va_arg(vaargp, unsigned long); Reset the buffer position. ulpos = 0; Set the base to 10. ulbase = 10; Indicate that the value is positive so that a minus sign isn't inserted. ulneg = 0; Convert the value to ASCII. goto convert; Handle the %x and %X commands. Note that they are treated identically; i.e. %X will use lower case letters for a-f instead of the upper case letters is should use. We also alias %p to %x. case 'x': case 'X': case 'p': Get the value from the varargs. ulvalue = va_arg(vaargp, unsigned long); Reset the buffer position. ulpos = 0; Set the base to 16. ulbase = 16; Indicate that the value is positive so that a minus sign isn't inserted. -22-

ulneg = 0; convert: Determine the number of digits in the string version of the value. for(ulidx = 1; (((ulidx * ulbase) <= ulvalue) && (((ulidx * ulbase) / ulbase) == ulidx)); ulidx *= ulbase, ulcount--) If the value is negative, reduce the count of padding characters needed. if(ulneg) ulcount--; If the value is negative and the value is padded with zeros, then place the minus sign before the padding. if(ulneg && (cfill == '0')) Place the minus sign in the output buffer. pcbuf[ulpos++] = '-'; The minus sign has been placed, so turn off the negative flag. ulneg = 0; Provide additional padding at the beginning of the string conversion if needed. if((ulcount > 1) && (ulcount < 16)) for(ulcount--; ulcount; ulcount--) pcbuf[ulpos++] = cfill; -23-

If the value is negative, then place the minus sign before the number. if(ulneg) Place the minus sign in the output buffer. pcbuf[ulpos++] = '-'; Convert the value into a string. for(; ulidx; ulidx /= ulbase) pcbuf[ulpos++] = g_pchex[(ulvalue / ulidx) % ulbase]; Write the string. UARTwrite(pcBuf, ulpos); 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: -24-

Indicate an error. UARTwrite("ERROR", 5); This command has been handled. break; End the varargs processing. 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); #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) -25-

return(tx_buffer_free); *****************************************************************************! 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; unsigned long ulreadindex; How many characters are there in the receive buffer? iavail = (int)rx_buffer_used; ulreadindex = g_uluartrxreadindex; Check all the unread characters looking for the one passed. for(icount = 0; icount < iavail; icount++) if(g_pcuartrxbuffer[ulreadindex] == ucchar) We found it so return the index return(icount); else -26-

This one didn't match so move on to the next character. ADVANCE_RX_BUFFER_INDEX(ulReadIndex); If we drop out of the loop, we didn't find the character in the receive buffer. return(-1); *****************************************************************************! 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) unsigned long ulint; Temporarily turn off interrupts. ulint = MAP_IntMasterDisable(); Flush the receive buffer. g_uluartrxreadindex = 0; g_uluartrxwriteindex = 0; If interrupts were enabled when we turned them off, turn them back on again. if(!ulint) MAP_IntMasterEnable(); -27-

*****************************************************************************! 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(tBoolean bdiscard) unsigned long ulint; Should the remaining data be discarded or transmitted? if(bdiscard) The remaining data should be discarded, so temporarily turn off interrupts. ulint = MAP_IntMasterDisable(); Flush the transmit buffer. g_uluarttxreadindex = 0; g_uluarttxwriteindex = 0; If interrupts were enabled when we turned them off, turn them back on again. if(!ulint) MAP_IntMasterEnable(); else Wait for all remaining data to be transmitted before returning. -28-

while(!tx_buffer_empty) *****************************************************************************! 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(tBoolean benable) g_bdisableecho =!benable; *****************************************************************************! 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) unsigned long ulints; char cchar; -29-

long lchar; static tboolean blastwascr = false; Get and clear the current interrupt source(s) ulints = MAP_UARTIntStatus(g_ulBase, true); MAP_UARTIntClear(g_ulBase, ulints); Are we being interrupted because the TX FIFO has space available? if(ulints & UART_INT_TX) Move as many bytes as we can into the transmit FIFO. UARTPrimeTransmit(g_ulBase); If the output buffer is empty, turn off the transmit interrupt. if(tx_buffer_empty) MAP_UARTIntDisable(g_ulBase, UART_INT_TX); Are we being interrupted due to a received character? if(ulints & (UART_INT_RX UART_INT_RT)) Get all the available characters from the UART. while(map_uartcharsavail(g_ulbase)) Read a character lchar = MAP_UARTCharGetNonBlocking(g_ulBase); cchar = (unsigned char)(lchar & 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. -30-

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_uluartrxwriteindex == 0) g_uluartrxwriteindex = UART_RX_BUFFER_SIZE - 1; else g_uluartrxwriteindex--; 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 -31-

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_uluartrxwriteindex] = (unsigned char)(lchar & 0xFF); ADVANCE_RX_BUFFER_INDEX(g_ulUARTRxWriteIndex); If echo is enabled, write the character to the transmit buffer so that the user gets some immediate feedback. if(!g_bdisableecho) UARTwrite(&cChar, 1); If we wrote anything to the transmit buffer, make sure it actually gets transmitted. UARTPrimeTransmit(g_ulBase); MAP_UARTIntEnable(g_ulBase, UART_INT_TX); -32-

***************************************************************************** Close the Doxygen group.! @ ***************************************************************************** -33-