From 98f9d442b44dbe2e3e4b3c8296be7e78d5d05450 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 24 Jul 2011 09:39:28 +0200 Subject: initial import of the usb ccid example for the sam7s --- at91lib/utility/assert.h | 114 +++++++++++ at91lib/utility/led.c | 162 +++++++++++++++ at91lib/utility/led.h | 70 +++++++ at91lib/utility/math.c | 91 +++++++++ at91lib/utility/math.h | 45 +++++ at91lib/utility/stdio.c | 512 +++++++++++++++++++++++++++++++++++++++++++++++ at91lib/utility/trace.h | 236 ++++++++++++++++++++++ 7 files changed, 1230 insertions(+) create mode 100644 at91lib/utility/assert.h create mode 100644 at91lib/utility/led.c create mode 100644 at91lib/utility/led.h create mode 100644 at91lib/utility/math.c create mode 100644 at91lib/utility/math.h create mode 100644 at91lib/utility/stdio.c create mode 100644 at91lib/utility/trace.h (limited to 'at91lib/utility') diff --git a/at91lib/utility/assert.h b/at91lib/utility/assert.h new file mode 100644 index 0000000..5cccb61 --- /dev/null +++ b/at91lib/utility/assert.h @@ -0,0 +1,114 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Definition of the ASSERT() and SANITY_CHECK() macros, which are used for +/// runtime condition & parameter verifying. +/// +/// !Usage +/// +/// -# Use ASSERT() in your code to check the value of function parameters, +/// return values, etc. *Warning:* the ASSERT() condition must not have +/// any side-effect; otherwise, the program may not work properly +/// anymore when assertions are disabled. +/// -# Use SANITY_CHECK() to perform checks with a default error message +/// (outputs the file and line number where the error occured). This +/// reduces memory overhead caused by assertion error strings. +/// -# Initialize the dbgu to see failed assertions at run-time. +/// -# Assertions can be entirely disabled by defining the NOASSERT symbol +/// at compilation time. +//------------------------------------------------------------------------------ + +#ifndef ASSERT_H +#define ASSERT_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include +#include "trace.h" + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +#if defined(NOASSERT) + #define ASSERT(...) + #define SANITY_CHECK(...) +#else + + #if (TRACE_LEVEL == 0) + /// Checks that the given condition is true, + /// otherwise stops the program execution. + /// \param condition Condition to verify. + #define ASSERT(condition, ...) { \ + if (!(condition)) { \ + while (1); \ + } \ + } + + /// Performs the same duty as the ASSERT() macro + /// \param condition Condition to verify. + #define SANITY_CHECK(condition) ASSERT(condition, ...) + + #else + /// Checks that the given condition is true, otherwise displays an error + /// message and stops the program execution. + /// \param condition Condition to verify. + #define ASSERT(condition, ...) { \ + if (!(condition)) { \ + printf("-F- ASSERT: "); \ + printf(__VA_ARGS__); \ + while (1); \ + } \ + } + #define SANITY_ERROR "Sanity check failed at %s:%d\n\r" + + /// Performs the same duty as the ASSERT() macro, except a default error + /// message is output if the condition is false. + /// \param condition Condition to verify. + #define SANITY_CHECK(condition) ASSERT(condition, SANITY_ERROR, __FILE__, __LINE__) + #endif +#endif + + + + + + + + + + +#endif //#ifndef ASSERT_H + diff --git a/at91lib/utility/led.c b/at91lib/utility/led.c new file mode 100644 index 0000000..7048b2a --- /dev/null +++ b/at91lib/utility/led.c @@ -0,0 +1,162 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "led.h" +#include +#include + +//------------------------------------------------------------------------------ +// Local Variables +//------------------------------------------------------------------------------ + +#ifdef PINS_LEDS +static const Pin pinsLeds[] = {PINS_LEDS}; +static const unsigned int numLeds = PIO_LISTSIZE(pinsLeds); +#endif + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Configures the pin associated with the given LED number. If the LED does +/// not exist on the board, the function does nothing. +/// \param led Number of the LED to configure. +/// \return 1 if the LED exists and has been configured; otherwise 0. +//------------------------------------------------------------------------------ +unsigned char LED_Configure(unsigned int led) +{ +#ifdef PINS_LEDS + // Check that LED exists + if (led >= numLeds) { + + return 0; + } + + // Configure LED + return (PIO_Configure(&pinsLeds[led], 1)); +#else + return 0; +#endif +} + +//------------------------------------------------------------------------------ +/// Turns the given LED on if it exists; otherwise does nothing. +/// \param led Number of the LED to turn on. +/// \return 1 if the LED has been turned on; 0 otherwise. +//------------------------------------------------------------------------------ +unsigned char LED_Set(unsigned int led) +{ +#ifdef PINS_LEDS + // Check if LED exists + if (led >= numLeds) { + + return 0; + } + + // Turn LED on + if (pinsLeds[led].type == PIO_OUTPUT_0) { + + PIO_Set(&pinsLeds[led]); + } + else { + + PIO_Clear(&pinsLeds[led]); + } + + return 1; +#else + return 0; +#endif +} + +//------------------------------------------------------------------------------ +/// Turns a LED off. +/// \param led Number of the LED to turn off. +/// \param 1 if the LED has been turned off; 0 otherwise. +//------------------------------------------------------------------------------ +unsigned char LED_Clear(unsigned int led) +{ +#ifdef PINS_LEDS + // Check if LED exists + if (led >= numLeds) { + + return 0; + } + + // Turn LED off + if (pinsLeds[led].type == PIO_OUTPUT_0) { + + PIO_Clear(&pinsLeds[led]); + } + else { + + PIO_Set(&pinsLeds[led]); + } + + return 1; +#else + return 0; +#endif +} + +//------------------------------------------------------------------------------ +/// Toggles the current state of a LED. +/// \param led Number of the LED to toggle. +/// \return 1 if the LED has been toggled; otherwise 0. +//------------------------------------------------------------------------------ +unsigned char LED_Toggle(unsigned int led) +{ +#ifdef PINS_LEDS + // Check if LED exists + if (led >= numLeds) { + + return 0; + } + + // Toggle LED + if (PIO_GetOutputDataStatus(&pinsLeds[led])) { + + PIO_Clear(&pinsLeds[led]); + } + else { + + PIO_Set(&pinsLeds[led]); + } + + return 1; +#else + return 0; +#endif +} + diff --git a/at91lib/utility/led.h b/at91lib/utility/led.h new file mode 100644 index 0000000..3f4878f --- /dev/null +++ b/at91lib/utility/led.h @@ -0,0 +1,70 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Small set of functions for simple and portable LED usage. +/// +/// !Usage +/// +/// -# Configure one or more LEDs using LED_Configure and +/// LED_ConfigureAll. +/// -# Set, clear and toggle LEDs using LED_Set, LED_Clear and +/// LED_Toggle. +/// +/// LEDs are numbered starting from 0; the number of LEDs depend on the +/// board being used. All the functions defined here will compile properly +/// regardless of whether the LED is defined or not; they will simply +/// return 0 when a LED which does not exist is given as an argument. +/// Also, these functions take into account how each LED is connected on to +/// board; thus, might change the level on the corresponding pin +/// to 0 or 1, but it will always light the LED on; same thing for the other +/// methods. +//------------------------------------------------------------------------------ + +#ifndef LED_H +#define LED_H + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +extern unsigned char LED_Configure(unsigned int led); + +extern unsigned char LED_Set(unsigned int led); + +extern unsigned char LED_Clear(unsigned int led); + +extern unsigned char LED_Toggle(unsigned int led); + +#endif //#ifndef LED_H + diff --git a/at91lib/utility/math.c b/at91lib/utility/math.c new file mode 100644 index 0000000..6012385 --- /dev/null +++ b/at91lib/utility/math.c @@ -0,0 +1,91 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "math.h" +#include "trace.h" + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Returns the minimum value between two integers. +/// \param a First integer to compare. +/// \param b Second integer to compare. +//------------------------------------------------------------------------------ +unsigned int min(unsigned int a, unsigned int b) +{ + if (a < b) { + + return a; + } + else { + + return b; + } +} + +//------------------------------------------------------------------------------ +/// Returns the absolute value of an integer. +/// \param value Integer value. +//------------------------------------------------------------------------------ +// Do not call this function "abs", problem with gcc ! +unsigned int absv(signed int value) +{ + if (value < 0) { + + return -value; + } + else { + + return value; + } +} + +//------------------------------------------------------------------------------ +/// Computes and returns x power of y. +/// \param x Value. +/// \param y Power. +//------------------------------------------------------------------------------ +unsigned int power(unsigned int x, unsigned int y) +{ + unsigned int result = 1; + + while (y > 0) { + + result *= x; + y--; + } + return result; +} + diff --git a/at91lib/utility/math.h b/at91lib/utility/math.h new file mode 100644 index 0000000..3406075 --- /dev/null +++ b/at91lib/utility/math.h @@ -0,0 +1,45 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +#ifndef MATH_H +#define MATH_H + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +extern unsigned int min(unsigned int a, unsigned int b); +extern unsigned int absv(signed int value); +#if defined(__ARMCC_VERSION) +extern unsigned int pow(unsigned int x, unsigned int y); +#else +extern unsigned int power(unsigned int x, unsigned int y); +#endif +#endif //#ifndef MATH_H + diff --git a/at91lib/utility/stdio.c b/at91lib/utility/stdio.c new file mode 100644 index 0000000..3e76ddc --- /dev/null +++ b/at91lib/utility/stdio.c @@ -0,0 +1,512 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Implementation of several stdio.h methods, such as printf(), sprintf() and +/// so on. This reduces the memory footprint of the binary when using those +/// methods, compared to the libc implementation. +/// +/// !Usage +/// +/// Adds stdio.c to the list of file to compile for the project. This will +/// automatically replace libc methods by the custom ones. +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include +#include + +//------------------------------------------------------------------------------ +// Local Definitions +//------------------------------------------------------------------------------ + +// Maximum string size allowed (in bytes). +#define MAX_STRING_SIZE 100 + +//------------------------------------------------------------------------------ +// Global Variables +//------------------------------------------------------------------------------ + +// Required for proper compilation. +struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0}; +struct _reent *_impure_ptr = &r; + +//------------------------------------------------------------------------------ +// Local Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Writes a character inside the given string. Returns 1. +// \param pStr Storage string. +// \param c Character to write. +//------------------------------------------------------------------------------ +signed int PutChar(char *pStr, char c) +{ + *pStr = c; + return 1; +} + +//------------------------------------------------------------------------------ +// Writes a string inside the given string. +// Returns the size of the written +// string. +// \param pStr Storage string. +// \param pSource Source string. +//------------------------------------------------------------------------------ +signed int PutString(char *pStr, const char *pSource) +{ + signed int num = 0; + + while (*pSource != 0) { + + *pStr++ = *pSource++; + num++; + } + + return num; +} + +//------------------------------------------------------------------------------ +// Writes an unsigned int inside the given string, using the provided fill & +// width parameters. +// Returns the size in characters of the written integer. +// \param pStr Storage string. +// \param fill Fill character. +// \param width Minimum integer width. +// \param value Integer value. +//------------------------------------------------------------------------------ +signed int PutUnsignedInt( + char *pStr, + char fill, + signed int width, + unsigned int value) +{ + signed int num = 0; + + // Take current digit into account when calculating width + width--; + + // Recursively write upper digits + if ((value / 10) > 0) { + + num = PutUnsignedInt(pStr, fill, width, value / 10); + pStr += num; + } + // Write filler characters + else { + + while (width > 0) { + + PutChar(pStr, fill); + pStr++; + num++; + width--; + } + } + + // Write lower digit + num += PutChar(pStr, (value % 10) + '0'); + + return num; +} + +//------------------------------------------------------------------------------ +// Writes a signed int inside the given string, using the provided fill & width +// parameters. +// Returns the size of the written integer. +// \param pStr Storage string. +// \param fill Fill character. +// \param width Minimum integer width. +// \param value Signed integer value. +//------------------------------------------------------------------------------ +signed int PutSignedInt( + char *pStr, + char fill, + signed int width, + signed int value) +{ + signed int num = 0; + unsigned int absolute; + + // Compute absolute value + if (value < 0) { + + absolute = -value; + } + else { + + absolute = value; + } + + // Take current digit into account when calculating width + width--; + + // Recursively write upper digits + if ((absolute / 10) > 0) { + + if (value < 0) { + + num = PutSignedInt(pStr, fill, width, -(absolute / 10)); + } + else { + + num = PutSignedInt(pStr, fill, width, absolute / 10); + } + pStr += num; + } + else { + + // Reserve space for sign + if (value < 0) { + + width--; + } + + // Write filler characters + while (width > 0) { + + PutChar(pStr, fill); + pStr++; + num++; + width--; + } + + // Write sign + if (value < 0) { + + num += PutChar(pStr, '-'); + pStr++; + } + } + + // Write lower digit + num += PutChar(pStr, (absolute % 10) + '0'); + + return num; +} + +//------------------------------------------------------------------------------ +// Writes an hexadecimal value into a string, using the given fill, width & +// capital parameters. +// Returns the number of char written. +// \param pStr Storage string. +// \param fill Fill character. +// \param width Minimum integer width. +// \param maj Indicates if the letters must be printed in lower- or upper-case. +// \param value Hexadecimal value. +//------------------------------------------------------------------------------ +signed int PutHexa( + char *pStr, + char fill, + signed int width, + unsigned char maj, + unsigned int value) +{ + signed int num = 0; + + // Decrement width + width--; + + // Recursively output upper digits + if ((value >> 4) > 0) { + + num += PutHexa(pStr, fill, width, maj, value >> 4); + pStr += num; + } + // Write filler chars + else { + + while (width > 0) { + + PutChar(pStr, fill); + pStr++; + num++; + width--; + } + } + + // Write current digit + if ((value & 0xF) < 10) { + + PutChar(pStr, (value & 0xF) + '0'); + } + else if (maj) { + + PutChar(pStr, (value & 0xF) - 10 + 'A'); + } + else { + + PutChar(pStr, (value & 0xF) - 10 + 'a'); + } + num++; + + return num; +} + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Stores the result of a formatted string into another string. Format +/// arguments are given in a va_list instance. +/// Return the number of characters written. +/// \param pStr Destination string. +/// \param length Length of Destination string. +/// \param pFormat Format string. +/// \param ap Argument list. +//------------------------------------------------------------------------------ +signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap) +{ + char fill; + unsigned char width; + signed int num = 0; + signed int size = 0; + + // Clear the string + if (pStr) { + + *pStr = 0; + } + + // Phase string + while (*pFormat != 0 && size < length) { + + // Normal character + if (*pFormat != '%') { + + *pStr++ = *pFormat++; + size++; + } + // Escaped '%' + else if (*(pFormat+1) == '%') { + + *pStr++ = '%'; + pFormat += 2; + size++; + } + // Token delimiter + else { + + fill = ' '; + width = 0; + pFormat++; + + // Parse filler + if (*pFormat == '0') { + + fill = '0'; + pFormat++; + } + + // Parse width + while ((*pFormat >= '0') && (*pFormat <= '9')) { + + width = (width*10) + *pFormat-'0'; + pFormat++; + } + + // Check if there is enough space + if (size + width > length) { + + width = length - size; + } + + // Parse type + switch (*pFormat) { + case 'd': + case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break; + case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break; + case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break; + case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break; + case 's': num = PutString(pStr, va_arg(ap, char *)); break; + case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break; + default: + return EOF; + } + + pFormat++; + pStr += num; + size += num; + } + } + + // NULL-terminated (final \0 is not counted) + if (size < length) { + + *pStr = 0; + } + else { + + *(--pStr) = 0; + size--; + } + + return size; +} + +//------------------------------------------------------------------------------ +/// Stores the result of a formatted string into another string. Format +/// arguments are given in a va_list instance. +/// Return the number of characters written. +/// \param pString Destination string. +/// \param length Length of Destination string. +/// \param pFormat Format string. +/// \param ... Other arguments +//------------------------------------------------------------------------------ +signed int snprintf(char *pString, size_t length, const char *pFormat, ...) +{ + va_list ap; + signed int rc; + + va_start(ap, pFormat); + rc = vsnprintf(pString, length, pFormat, ap); + va_end(ap); + + return rc; +} + +//------------------------------------------------------------------------------ +/// Stores the result of a formatted string into another string. Format +/// arguments are given in a va_list instance. +/// Return the number of characters written. +/// \param pString Destination string. +/// \param pFormat Format string. +/// \param ap Argument list. +//------------------------------------------------------------------------------ +signed int vsprintf(char *pString, const char *pFormat, va_list ap) +{ + return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap); +} + +//------------------------------------------------------------------------------ +/// Outputs a formatted string on the given stream. Format arguments are given +/// in a va_list instance. +/// \param pStream Output stream. +/// \param pFormat Format string +/// \param ap Argument list. +//------------------------------------------------------------------------------ +signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap) +{ + char pStr[MAX_STRING_SIZE]; + char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r"; + + // Write formatted string in buffer + if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) { + + fputs(pError, stderr); + while (1); // Increase MAX_STRING_SIZE + } + + // Display string + return fputs(pStr, pStream); +} + +//------------------------------------------------------------------------------ +/// Outputs a formatted string on the DBGU stream. Format arguments are given +/// in a va_list instance. +/// \param pFormat Format string +/// \param ap Argument list. +//------------------------------------------------------------------------------ +signed int vprintf(const char *pFormat, va_list ap) +{ + return vfprintf(stdout, pFormat, ap); +} + +//------------------------------------------------------------------------------ +/// Outputs a formatted string on the given stream, using a variable number of +/// arguments. +/// \param pStream Output stream. +/// \param pFormat Format string. +//------------------------------------------------------------------------------ +signed int fprintf(FILE *pStream, const char *pFormat, ...) +{ + va_list ap; + signed int result; + + // Forward call to vfprintf + va_start(ap, pFormat); + result = vfprintf(pStream, pFormat, ap); + va_end(ap); + + return result; +} + +//------------------------------------------------------------------------------ +/// Outputs a formatted string on the DBGU stream, using a variable number of +/// arguments. +/// \param pFormat Format string. +//------------------------------------------------------------------------------ +signed int printf(const char *pFormat, ...) +{ + va_list ap; + signed int result; + + // Forward call to vprintf + va_start(ap, pFormat); + result = vprintf(pFormat, ap); + va_end(ap); + + return result; +} + +//------------------------------------------------------------------------------ +/// Writes a formatted string inside another string. +/// \param pStr Storage string. +/// \param pFormat Format string. +//------------------------------------------------------------------------------ +signed int sprintf(char *pStr, const char *pFormat, ...) +{ + va_list ap; + signed int result; + + // Forward call to vsprintf + va_start(ap, pFormat); + result = vsprintf(pStr, pFormat, ap); + va_end(ap); + + return result; +} + +//------------------------------------------------------------------------------ +/// Outputs a string on stdout. +/// \param pStr String to output. +//------------------------------------------------------------------------------ +signed int puts(const char *pStr) +{ + return fputs(pStr, stdout); +} + diff --git a/at91lib/utility/trace.h b/at91lib/utility/trace.h new file mode 100644 index 0000000..d996dcd --- /dev/null +++ b/at91lib/utility/trace.h @@ -0,0 +1,236 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Standard output methods for reporting debug information, warnings and +/// errors, which can be easily be turned on/off. +/// +/// !Usage +/// -# Initialize the DBGU using TRACE_CONFIGURE() if you intend to eventually +/// disable ALL traces; otherwise use DBGU_Configure(). +/// -# Uses the TRACE_DEBUG(), TRACE_INFO(), TRACE_WARNING(), TRACE_ERROR() +/// TRACE_FATAL() macros to output traces throughout the program. +/// -# Each type of trace has a level : Debug 5, Info 4, Warning 3, Error 2 +/// and Fatal 1. Disable a group of traces by changing the value of +/// TRACE_LEVEL during compilation; traces with a level bigger than TRACE_LEVEL +/// are not generated. To generate no trace, use the reserved value 0. +/// -# Trace disabling can be static or dynamic. If dynamic disabling is selected +/// the trace level can be modified in runtime. If static disabling is selected +/// the disabled traces are not compiled. +/// +/// !Trace level description +/// -# TRACE_DEBUG (5): Traces whose only purpose is for debugging the program, +/// and which do not produce meaningful information otherwise. +/// -# TRACE_INFO (4): Informational trace about the program execution. Should +/// enable the user to see the execution flow. +/// -# TRACE_WARNING (3): Indicates that a minor error has happened. In most case +/// it can be discarded safely; it may even be expected. +/// -# TRACE_ERROR (2): Indicates an error which may not stop the program execution, +/// but which indicates there is a problem with the code. +/// -# TRACE_FATAL (1): Indicates a major error which prevents the program from going +/// any further. + +//------------------------------------------------------------------------------ + +#ifndef TRACE_H +#define TRACE_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global Definitions +//------------------------------------------------------------------------------ + +/// Softpack Version +#define SOFTPACK_VERSION "1.5" + +#define TRACE_LEVEL_DEBUG 5 +#define TRACE_LEVEL_INFO 4 +#define TRACE_LEVEL_WARNING 3 +#define TRACE_LEVEL_ERROR 2 +#define TRACE_LEVEL_FATAL 1 +#define TRACE_LEVEL_NO_TRACE 0 + +// By default, all traces are output except the debug one. +#if !defined(TRACE_LEVEL) +#define TRACE_LEVEL TRACE_LEVEL_INFO +#endif + +// By default, trace level is static (not dynamic) +#if !defined(DYN_TRACES) +#define DYN_TRACES 0 +#endif + +#if defined(NOTRACE) +#error "Error: NOTRACE has to be not defined !" +#endif + +#undef NOTRACE +#if (TRACE_LEVEL == TRACE_LEVEL_NO_TRACE) +#define NOTRACE +#endif + + + +//------------------------------------------------------------------------------ +// Global Macros +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the DBGU +/// \param mode DBGU mode. +/// \param baudrate DBGU baudrate. +/// \param mck Master clock frequency. +//------------------------------------------------------------------------------ +#define TRACE_CONFIGURE(mode, baudrate, mck) { \ + const Pin pinsDbgu[] = {PINS_DBGU}; \ + PIO_Configure(pinsDbgu, PIO_LISTSIZE(pinsDbgu)); \ + DBGU_Configure(mode, baudrate, mck); \ + } + +//------------------------------------------------------------------------------ +/// Initializes the DBGU for ISP project +/// \param mode DBGU mode. +/// \param baudrate DBGU baudrate. +/// \param mck Master clock frequency. +//------------------------------------------------------------------------------ +#if (TRACE_LEVEL==0) && (DYNTRACE==0) +#define TRACE_CONFIGURE_ISP(mode, baudrate, mck) {} +#else +#define TRACE_CONFIGURE_ISP(mode, baudrate, mck) { \ + const Pin pinsDbgu[] = {PINS_DBGU}; \ + PIO_Configure(pinsDbgu, PIO_LISTSIZE(pinsDbgu)); \ + DBGU_Configure(mode, baudrate, mck); \ + } +#endif + +//------------------------------------------------------------------------------ +/// Outputs a formatted string using if the log level is high +/// enough. Can be disabled by defining TRACE_LEVEL=0 during compilation. +/// \param format Formatted string to output. +/// \param ... Additional parameters depending on formatted string. +//------------------------------------------------------------------------------ +#if defined(NOTRACE) + +// Empty macro +#define TRACE_DEBUG(...) { } +#define TRACE_INFO(...) { } +#define TRACE_WARNING(...) { } +#define TRACE_ERROR(...) { } +#define TRACE_FATAL(...) { while(1); } + +#define TRACE_DEBUG_WP(...) { } +#define TRACE_INFO_WP(...) { } +#define TRACE_WARNING_WP(...) { } +#define TRACE_ERROR_WP(...) { } +#define TRACE_FATAL_WP(...) { while(1); } + +#elif (DYN_TRACES == 1) + +// Trace output depends on traceLevel value +#define TRACE_DEBUG(...) { if (traceLevel >= TRACE_LEVEL_DEBUG) { printf("-D- " __VA_ARGS__); } } +#define TRACE_INFO(...) { if (traceLevel >= TRACE_LEVEL_INFO) { printf("-I- " __VA_ARGS__); } } +#define TRACE_WARNING(...) { if (traceLevel >= TRACE_LEVEL_WARNING) { printf("-W- " __VA_ARGS__); } } +#define TRACE_ERROR(...) { if (traceLevel >= TRACE_LEVEL_ERROR) { printf("-E- " __VA_ARGS__); } } +#define TRACE_FATAL(...) { if (traceLevel >= TRACE_LEVEL_FATAL) { printf("-F- " __VA_ARGS__); while(1); } } + +#define TRACE_DEBUG_WP(...) { if (traceLevel >= TRACE_LEVEL_DEBUG) { printf(__VA_ARGS__); } } +#define TRACE_INFO_WP(...) { if (traceLevel >= TRACE_LEVEL_INFO) { printf(__VA_ARGS__); } } +#define TRACE_WARNING_WP(...) { if (traceLevel >= TRACE_LEVEL_WARNING) { printf(__VA_ARGS__); } } +#define TRACE_ERROR_WP(...) { if (traceLevel >= TRACE_LEVEL_ERROR) { printf(__VA_ARGS__); } } +#define TRACE_FATAL_WP(...) { if (traceLevel >= TRACE_LEVEL_FATAL) { printf(__VA_ARGS__); while(1); } } + +#else + +// Trace compilation depends on TRACE_LEVEL value +#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) +#define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); } +#define TRACE_DEBUG_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_DEBUG(...) { } +#define TRACE_DEBUG_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_INFO) +#define TRACE_INFO(...) { printf("-I- " __VA_ARGS__); } +#define TRACE_INFO_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_INFO(...) { } +#define TRACE_INFO_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_WARNING) +#define TRACE_WARNING(...) { printf("-W- " __VA_ARGS__); } +#define TRACE_WARNING_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_WARNING(...) { } +#define TRACE_WARNING_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_ERROR) +#define TRACE_ERROR(...) { printf("-E- " __VA_ARGS__); } +#define TRACE_ERROR_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_ERROR(...) { } +#define TRACE_ERROR_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_FATAL) +#define TRACE_FATAL(...) { printf("-F- " __VA_ARGS__); while(1); } +#define TRACE_FATAL_WP(...) { printf(__VA_ARGS__); while(1); } +#else +#define TRACE_FATAL(...) { while(1); } +#define TRACE_FATAL_WP(...) { while(1); } +#endif + +#endif + + +//------------------------------------------------------------------------------ +// Exported variables +//------------------------------------------------------------------------------ +// Depending on DYN_TRACES, traceLevel is a modifable runtime variable +// or a define +#if !defined(NOTRACE) && (DYN_TRACES == 1) + extern unsigned int traceLevel; +#endif + +#endif //#ifndef TRACE_H + -- cgit v1.2.3