add synchronous UART transmission and use it in exceptions

The default ISR (particularly the HardFault handler) print information,
but this information was not displayed on the console because the UART
IRQ is lower than some default blocking IRQ.
Allowing to set synchronous transfer corrects this.

The underlying Atmel exception library had to be modified to use the
synchronous output.

Making UART_PutChar always synchronous when called from an ISR is not
desired because we use TRACE_ macros is some ISR. The synchronous
output must be set explicitly.

Change-Id: I1b4ace5185cf2dc32684934ed12bf6a8682e9bad
diff --git a/firmware/libcommon/include/stdio.h b/firmware/libcommon/include/stdio.h
index 7695d20..258c7ab 100644
--- a/firmware/libcommon/include/stdio.h
+++ b/firmware/libcommon/include/stdio.h
@@ -52,9 +52,14 @@
 signed int sprintf(char *pStr, const char *pFormat, ...);
 signed int puts(const char *pStr);
 
-
 int fputc(int c, FILE *stream);
 int fputs(const char *s, FILE *stream);
 
 #define putc(c, stream) fputc(c, stream)
 #define putchar(c) fputc(c, stdout)
+
+signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap);
+signed int vprintf_sync(const char *pFormat, va_list ap);
+signed int printf_sync(const char *pFormat, ...);
+int fputc_sync(int c, FILE *stream);
+int fputs_sync(const char *s, FILE *stream);
diff --git a/firmware/libcommon/source/fputs.c b/firmware/libcommon/source/fputs.c
index ca6f851..110f68e 100644
--- a/firmware/libcommon/source/fputs.c
+++ b/firmware/libcommon/source/fputs.c
@@ -26,6 +26,19 @@
 int fputs(const char *s, FILE *stream)
 {
 	while (*s != '\0')
-		UART_PutChar(*s++);
+		fputc(*s++, stream);
+	return 0;
+}
+
+int fputc_sync(int c, FILE *stream)
+{
+	UART_PutChar_Sync(c);
+	return c;
+}
+
+int fputs_sync(const char *s, FILE *stream)
+{
+	while (*s != '\0')
+		fputc_sync(*s++, stream);
 	return 0;
 }
diff --git a/firmware/libcommon/source/stdio.c b/firmware/libcommon/source/stdio.c
index 505c895..06ad611 100644
--- a/firmware/libcommon/source/stdio.c
+++ b/firmware/libcommon/source/stdio.c
@@ -2,6 +2,7 @@
  *         ATMEL Microcontroller Software Support 
  * ----------------------------------------------------------------------------
  * Copyright (c) 2008, Atmel Corporation
+ * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
  *
  * All rights reserved.
  *
@@ -436,6 +437,32 @@
 }
 
 //------------------------------------------------------------------------------
+/// Outputs a formatted string on the given stream. Format arguments are given
+/// in a va_list instance.
+/// \note This function is synchronous (i.e. blocks until the print completes)
+/// \param pStream  Output stream.
+/// \param pFormat  Format string
+/// \param ap  Argument list.
+//------------------------------------------------------------------------------
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+signed int vfprintf_sync(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_sync(pError, stderr);
+	}
+
+	// Display string
+	return fputs_sync(pStr, pStream);
+}
+#pragma GCC diagnostic pop
+
+//------------------------------------------------------------------------------
 /// Outputs a formatted string on the DBGU stream. Format arguments are given
 /// in a va_list instance.
 /// \param pFormat  Format string
@@ -447,6 +474,18 @@
 }
 
 //------------------------------------------------------------------------------
+/// Outputs a formatted string on the DBGU stream. Format arguments are given
+/// in a va_list instance.
+/// \note This function is synchronous (i.e. blocks until the print completes)
+/// \param pFormat  Format string
+/// \param ap  Argument list.
+//------------------------------------------------------------------------------
+signed int vprintf_sync(const char *pFormat, va_list ap)
+{
+	return vfprintf_sync(stdout, pFormat, ap);
+}
+
+//------------------------------------------------------------------------------
 /// Outputs a formatted string on the given stream, using a variable number of
 /// arguments.
 /// \param pStream  Output stream.
@@ -484,6 +523,25 @@
 }
 
 //------------------------------------------------------------------------------
+/// Outputs a formatted string on the DBGU stream, using a variable number of
+/// arguments.
+/// \note This function is synchronous (i.e. blocks until the print completes)
+/// \param pFormat  Format string.
+//------------------------------------------------------------------------------
+signed int printf_sync(const char *pFormat, ...)
+{
+	va_list ap;
+	signed int result;
+
+	// Forward call to vprintf
+	va_start(ap, pFormat);
+	result = vprintf_sync(pFormat, ap);
+	va_end(ap);
+
+	return result;
+}
+
+//------------------------------------------------------------------------------
 /// Writes a formatted string inside another string.
 /// \param pStr  Storage string.
 /// \param pFormat  Format string.