Update repo
This commit is contained in:
@@ -0,0 +1,716 @@
|
||||
//##############################################################################
|
||||
//
|
||||
// FILE: scistdio.c
|
||||
//
|
||||
// TITLE: Utility driver to provide simple SCI console functions.
|
||||
//
|
||||
//##############################################################################
|
||||
//
|
||||
// $Release Date: $
|
||||
// $Copyright:
|
||||
// Copyright (C) 2014-2024 Texas Instruments Incorporated - http://www.ti.com/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
//
|
||||
// Neither the name of Texas Instruments Incorporated nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// $
|
||||
//##############################################################################
|
||||
|
||||
//
|
||||
// Included Files
|
||||
//
|
||||
#include "scistdio.h"
|
||||
|
||||
//******************************************************************************
|
||||
//
|
||||
//! \addtogroup SCIstdio_api
|
||||
//! @{
|
||||
//
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// The base address of the chosen SCI.
|
||||
//
|
||||
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";
|
||||
|
||||
//******************************************************************************
|
||||
//
|
||||
//! Configures the SCI console.
|
||||
//!
|
||||
//! \param base is the base address of SCI.
|
||||
//! \param ui32Baud is the bit rate that the SCI is to be configured to use.
|
||||
//! \param ui32SrcClock is the frequency of the source clock for the SCI
|
||||
//! module.
|
||||
//!
|
||||
//! 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 SCI console
|
||||
//! functions: SCIprintf() or SCIgets(). This function assumes that the
|
||||
//! caller has previously configured the relevant SCI pins for operation as a
|
||||
//! SCI rather than as GPIOs.
|
||||
//!
|
||||
//! \return None.
|
||||
//
|
||||
//******************************************************************************
|
||||
void
|
||||
SCIStdioConfig(uint32_t base, uint32_t ui32Baud, uint32_t ui32SrcClock)
|
||||
{
|
||||
//
|
||||
// Select the base address of the SCI.
|
||||
//
|
||||
g_ui32Base = base;
|
||||
|
||||
//
|
||||
// Configure the SCI for 115200, n, 8, 1
|
||||
//
|
||||
SCI_setConfig(g_ui32Base, ui32SrcClock, ui32Baud,
|
||||
(SCI_CONFIG_PAR_NONE | SCI_CONFIG_STOP_ONE |
|
||||
SCI_CONFIG_WLEN_8));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//
|
||||
//! Writes a string of characters to the SCI 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 SCI 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 SCI, 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 SCI 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
|
||||
SCIwrite(const char *pcBuf, uint32_t ui32Len)
|
||||
{
|
||||
|
||||
unsigned int uIdx;
|
||||
|
||||
//
|
||||
// Check for valid SCI 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 SCI is \n, then add a \r before it so that
|
||||
// \n is translated to \n\r in the output.
|
||||
//
|
||||
if(pcBuf[uIdx] == '\n')
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(g_ui32Base, '\r');
|
||||
}
|
||||
|
||||
//
|
||||
// Send the character to the SCI output.
|
||||
//
|
||||
SCI_writeCharBlockingNonFIFO(g_ui32Base, pcBuf[uIdx]);
|
||||
}
|
||||
|
||||
//
|
||||
// Return the number of characters written.
|
||||
//
|
||||
return(uIdx);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! A simple SCI 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 SCI. Only the following formatting
|
||||
//! characters are supported:
|
||||
//!
|
||||
//! - \%c to print a character
|
||||
//! - \%d or \%i to print a decimal value
|
||||
//! - \%l to print a long 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
|
||||
SCIvprintf(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.
|
||||
//
|
||||
SCIwrite(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.
|
||||
//
|
||||
SCIwrite((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 %l command.
|
||||
//
|
||||
case 'l':
|
||||
{
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
SCIwrite(pcStr, ui32Idx);
|
||||
|
||||
//
|
||||
// Write any required padding spaces
|
||||
//
|
||||
if(ui32Count > ui32Idx)
|
||||
{
|
||||
ui32Count -= ui32Idx;
|
||||
while(ui32Count--)
|
||||
{
|
||||
SCIwrite(" ", 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.
|
||||
//
|
||||
SCIwrite(pcBuf, ui32Pos);
|
||||
|
||||
//
|
||||
// This command has been handled.
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle the %% command.
|
||||
//
|
||||
case '%':
|
||||
{
|
||||
//
|
||||
// Simply write a single %.
|
||||
//
|
||||
SCIwrite(pcString - 1, 1);
|
||||
|
||||
//
|
||||
// This command has been handled.
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle all other commands.
|
||||
//
|
||||
default:
|
||||
{
|
||||
//
|
||||
// Indicate an error.
|
||||
//
|
||||
SCIwrite("ERROR", 5);
|
||||
|
||||
//
|
||||
// This command has been handled.
|
||||
//
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! A simple SCI 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 SCI. 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
|
||||
SCIprintf(const char *pcString, ...)
|
||||
{
|
||||
va_list vaArgP;
|
||||
|
||||
//
|
||||
// Start the varargs processing.
|
||||
//
|
||||
va_start(vaArgP, pcString);
|
||||
|
||||
SCIvprintf(pcString, vaArgP);
|
||||
|
||||
//
|
||||
// We're finished with the varargs now.
|
||||
//
|
||||
va_end(vaArgP);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Close the Doxygen group.
|
||||
//! @}
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//
|
||||
// End of file
|
||||
//
|
||||
Reference in New Issue
Block a user