<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10313">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add synchronous UART transmission and use it in exceptions<br><br>The default ISR (particularly the HardFault handler) print information,<br>but this information was not displayed on the console because the UART<br>IRQ is lower than some default blocking IRQ.<br>Allowing to set synchronous transfer corrects this.<br><br>The underlying Atmel exception library had to be modified to use the<br>synchronous output.<br><br>Making UART_PutChar always synchronous when called from an ISR is not<br>desired because we use TRACE_ macros is some ISR. The synchronous<br>output must be set explicitly.<br><br>Change-Id: I1b4ace5185cf2dc32684934ed12bf6a8682e9bad<br>---<br>M firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c<br>M firmware/libboard/common/include/uart_console.h<br>M firmware/libboard/common/source/uart_console.c<br>M firmware/libcommon/include/stdio.h<br>M firmware/libcommon/source/fputs.c<br>M firmware/libcommon/source/stdio.c<br>6 files changed, 108 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c</span><br><span>index 74e0fbd..6d2a135 100644</span><br><span>--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c</span><br><span>+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span>  *         ATMEL Microcontroller Software Support</span><br><span>  * ----------------------------------------------------------------------------</span><br><span>  * Copyright (c) 2009, Atmel Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de></span><br><span>  *</span><br><span>  * All rights reserved.</span><br><span>  *</span><br><span>@@ -41,6 +42,7 @@</span><br><span>  *        Headers</span><br><span>  *----------------------------------------------------------------------------*/</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define printf printf_sync</span><br><span> #include "chip.h"</span><br><span> </span><br><span> /*----------------------------------------------------------------------------</span><br><span>diff --git a/firmware/libboard/common/include/uart_console.h b/firmware/libboard/common/include/uart_console.h</span><br><span>index c0ee3a7..70425bc 100644</span><br><span>--- a/firmware/libboard/common/include/uart_console.h</span><br><span>+++ b/firmware/libboard/common/include/uart_console.h</span><br><span>@@ -29,16 +29,15 @@</span><br><span>  */</span><br><span> #ifndef _UART_CONSOLE_</span><br><span> #define _UART_CONSOLE_</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #include <stdint.h></span><br><span> </span><br><span> extern void UART_Configure( uint32_t dwBaudrate, uint32_t dwMasterClock ) ;</span><br><span style="color: hsl(0, 100%, 40%);">-extern void UART_Exit(void) ;</span><br><span style="color: hsl(120, 100%, 40%);">+extern void UART_Exit( void ) ;</span><br><span> extern void UART_PutChar( uint8_t uc ) ;</span><br><span style="color: hsl(120, 100%, 40%);">+extern void UART_PutChar_Sync( uint8_t uc ) ;</span><br><span> extern uint32_t UART_GetChar( void ) ;</span><br><span> extern uint32_t UART_IsRxReady( void ) ;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) ;</span><br><span> extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) ;</span><br><span> extern uint32_t UART_GetInteger( uint32_t* pdwValue ) ;</span><br><span>diff --git a/firmware/libboard/common/source/uart_console.c b/firmware/libboard/common/source/uart_console.c</span><br><span>index 3ce7331..3a00e49 100644</span><br><span>--- a/firmware/libboard/common/source/uart_console.c</span><br><span>+++ b/firmware/libboard/common/source/uart_console.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span>  *         ATMEL Microcontroller Software Support</span><br><span>  * ----------------------------------------------------------------------------</span><br><span>  * Copyright (c) 2009, Atmel Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de></span><br><span>  *</span><br><span>  * All rights reserved.</span><br><span>  *</span><br><span>@@ -135,10 +136,10 @@</span><br><span> /**</span><br><span>  * \brief Outputs a character on the UART line.</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * \note This function is synchronous (i.e. uses polling).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note This function is asynchronous (i.e. uses a buffer and interrupt to complete the transfer).</span><br><span>  * \param c  Character to send.</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-extern void UART_PutChar( uint8_t c )</span><br><span style="color: hsl(120, 100%, 40%);">+void UART_PutChar( uint8_t uc )</span><br><span> {</span><br><span>      Uart *pUart = CONSOLE_UART ;</span><br><span> </span><br><span>@@ -148,9 +149,8 @@</span><br><span>               UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Only store input if buffer is not full, else drop it */</span><br><span>   if (!rbuf_is_full(&uart_tx_buffer)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               rbuf_write(&uart_tx_buffer, c);</span><br><span style="color: hsl(120, 100%, 40%);">+           rbuf_write(&uart_tx_buffer, uc);</span><br><span>                 if (!(pUart->UART_IMR & UART_IMR_TXRDY)) {</span><br><span>                    pUart->UART_IER = UART_IER_TXRDY;</span><br><span>                         CONSOLE_ISR();</span><br><span>@@ -159,6 +159,28 @@</span><br><span> }</span><br><span> </span><br><span> /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Outputs a character on the UART line.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note This function is synchronous (i.e. uses polling and blocks until the transfer is complete).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param c  Character to send.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void UART_PutChar_Sync( uint8_t uc )</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       Uart *pUart = CONSOLE_UART ;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Initialize console is not already done */</span><br><span style="color: hsl(120, 100%, 40%);">+  if ( !_ucIsConsoleInitialized )</span><br><span style="color: hsl(120, 100%, 40%);">+       {</span><br><span style="color: hsl(120, 100%, 40%);">+             UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to be empty */</span><br><span style="color: hsl(120, 100%, 40%);">+  pUart->UART_THR = uc; /* Send data to UART peripheral */</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to transferred to shift register */</span><br><span style="color: hsl(120, 100%, 40%);">+     while (!(pUart->UART_SR & UART_SR_TXEMPTY)); /* Wait for transfer shift register to be empty (i.e. transfer is complete) */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span>  * \brief Input a character from the UART line.</span><br><span>  *</span><br><span>  * \note This function is synchronous</span><br><span>diff --git a/firmware/libcommon/include/stdio.h b/firmware/libcommon/include/stdio.h</span><br><span>index 7695d20..258c7ab 100644</span><br><span>--- a/firmware/libcommon/include/stdio.h</span><br><span>+++ b/firmware/libcommon/include/stdio.h</span><br><span>@@ -52,9 +52,14 @@</span><br><span> signed int sprintf(char *pStr, const char *pFormat, ...);</span><br><span> signed int puts(const char *pStr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int fputc(int c, FILE *stream);</span><br><span> int fputs(const char *s, FILE *stream);</span><br><span> </span><br><span> #define putc(c, stream) fputc(c, stream)</span><br><span> #define putchar(c) fputc(c, stdout)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap);</span><br><span style="color: hsl(120, 100%, 40%);">+signed int vprintf_sync(const char *pFormat, va_list ap);</span><br><span style="color: hsl(120, 100%, 40%);">+signed int printf_sync(const char *pFormat, ...);</span><br><span style="color: hsl(120, 100%, 40%);">+int fputc_sync(int c, FILE *stream);</span><br><span style="color: hsl(120, 100%, 40%);">+int fputs_sync(const char *s, FILE *stream);</span><br><span>diff --git a/firmware/libcommon/source/fputs.c b/firmware/libcommon/source/fputs.c</span><br><span>index ca6f851..110f68e 100644</span><br><span>--- a/firmware/libcommon/source/fputs.c</span><br><span>+++ b/firmware/libcommon/source/fputs.c</span><br><span>@@ -26,6 +26,19 @@</span><br><span> int fputs(const char *s, FILE *stream)</span><br><span> {</span><br><span>     while (*s != '\0')</span><br><span style="color: hsl(0, 100%, 40%);">-              UART_PutChar(*s++);</span><br><span style="color: hsl(120, 100%, 40%);">+           fputc(*s++, stream);</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int fputc_sync(int c, FILE *stream)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        UART_PutChar_Sync(c);</span><br><span style="color: hsl(120, 100%, 40%);">+ return c;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int fputs_sync(const char *s, FILE *stream)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        while (*s != '\0')</span><br><span style="color: hsl(120, 100%, 40%);">+            fputc_sync(*s++, stream);</span><br><span>    return 0;</span><br><span> }</span><br><span>diff --git a/firmware/libcommon/source/stdio.c b/firmware/libcommon/source/stdio.c</span><br><span>index 505c895..06ad611 100644</span><br><span>--- a/firmware/libcommon/source/stdio.c</span><br><span>+++ b/firmware/libcommon/source/stdio.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span>  *         ATMEL Microcontroller Software Support </span><br><span>  * ----------------------------------------------------------------------------</span><br><span>  * Copyright (c) 2008, Atmel Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de></span><br><span>  *</span><br><span>  * All rights reserved.</span><br><span>  *</span><br><span>@@ -436,6 +437,32 @@</span><br><span> }</span><br><span> </span><br><span> //------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+/// Outputs a formatted string on the given stream. Format arguments are given</span><br><span style="color: hsl(120, 100%, 40%);">+/// in a va_list instance.</span><br><span style="color: hsl(120, 100%, 40%);">+/// \note This function is synchronous (i.e. blocks until the print completes)</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param pStream  Output stream.</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param pFormat  Format string</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param ap  Argument list.</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma GCC diagnostic push</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"</span><br><span style="color: hsl(120, 100%, 40%);">+signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char pStr[MAX_STRING_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+   char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  // Write formatted string in buffer</span><br><span style="color: hsl(120, 100%, 40%);">+   if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            fputs_sync(pError, stderr);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // Display string</span><br><span style="color: hsl(120, 100%, 40%);">+     return fputs_sync(pStr, pStream);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma GCC diagnostic pop</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span> /// Outputs a formatted string on the DBGU stream. Format arguments are given</span><br><span> /// in a va_list instance.</span><br><span> /// \param pFormat  Format string</span><br><span>@@ -447,6 +474,18 @@</span><br><span> }</span><br><span> </span><br><span> //------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+/// Outputs a formatted string on the DBGU stream. Format arguments are given</span><br><span style="color: hsl(120, 100%, 40%);">+/// in a va_list instance.</span><br><span style="color: hsl(120, 100%, 40%);">+/// \note This function is synchronous (i.e. blocks until the print completes)</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param pFormat  Format string</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param ap  Argument list.</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+signed int vprintf_sync(const char *pFormat, va_list ap)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return vfprintf_sync(stdout, pFormat, ap);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span> /// Outputs a formatted string on the given stream, using a variable number of</span><br><span> /// arguments.</span><br><span> /// \param pStream  Output stream.</span><br><span>@@ -484,6 +523,25 @@</span><br><span> }</span><br><span> </span><br><span> //------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+/// Outputs a formatted string on the DBGU stream, using a variable number of</span><br><span style="color: hsl(120, 100%, 40%);">+/// arguments.</span><br><span style="color: hsl(120, 100%, 40%);">+/// \note This function is synchronous (i.e. blocks until the print completes)</span><br><span style="color: hsl(120, 100%, 40%);">+/// \param pFormat  Format string.</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+signed int printf_sync(const char *pFormat, ...)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     va_list ap;</span><br><span style="color: hsl(120, 100%, 40%);">+   signed int result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  // Forward call to vprintf</span><br><span style="color: hsl(120, 100%, 40%);">+    va_start(ap, pFormat);</span><br><span style="color: hsl(120, 100%, 40%);">+        result = vprintf_sync(pFormat, ap);</span><br><span style="color: hsl(120, 100%, 40%);">+   va_end(ap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return result;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//------------------------------------------------------------------------------</span><br><span> /// Writes a formatted string inside another string.</span><br><span> /// \param pStr  Storage string.</span><br><span> /// \param pFormat  Format string.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10313">change 10313</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/10313"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: simtrace2 </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I1b4ace5185cf2dc32684934ed12bf6a8682e9bad </div>
<div style="display:none"> Gerrit-Change-Number: 10313 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Kévin Redon <kredon@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: Kévin Redon <kredon@sysmocom.de> </div>