xref: /btstack/3rd-party/segger-rtt/SEGGER_RTT.c (revision a20be900c96e687639c0a9cb764edb04e3d5e483)
17dc86dfdSMatthias Ringwald /*********************************************************************
2779af47bSMatthias Ringwald *                    SEGGER Microcontroller GmbH                     *
3779af47bSMatthias Ringwald *                        The Embedded Experts                        *
47dc86dfdSMatthias Ringwald **********************************************************************
57dc86dfdSMatthias Ringwald *                                                                    *
6779af47bSMatthias Ringwald *            (c) 1995 - 2019 SEGGER Microcontroller GmbH             *
77dc86dfdSMatthias Ringwald *                                                                    *
87dc86dfdSMatthias Ringwald *       www.segger.com     Support: [email protected]               *
97dc86dfdSMatthias Ringwald *                                                                    *
107dc86dfdSMatthias Ringwald **********************************************************************
117dc86dfdSMatthias Ringwald *                                                                    *
127dc86dfdSMatthias Ringwald *       SEGGER RTT * Real Time Transfer for embedded targets         *
137dc86dfdSMatthias Ringwald *                                                                    *
147dc86dfdSMatthias Ringwald **********************************************************************
157dc86dfdSMatthias Ringwald *                                                                    *
167dc86dfdSMatthias Ringwald * All rights reserved.                                               *
177dc86dfdSMatthias Ringwald *                                                                    *
187dc86dfdSMatthias Ringwald * SEGGER strongly recommends to not make any changes                 *
197dc86dfdSMatthias Ringwald * to or modify the source code of this software in order to stay     *
207dc86dfdSMatthias Ringwald * compatible with the RTT protocol and J-Link.                       *
217dc86dfdSMatthias Ringwald *                                                                    *
227dc86dfdSMatthias Ringwald * Redistribution and use in source and binary forms, with or         *
237dc86dfdSMatthias Ringwald * without modification, are permitted provided that the following    *
247dc86dfdSMatthias Ringwald * conditions are met:                                                *
257dc86dfdSMatthias Ringwald *                                                                    *
267dc86dfdSMatthias Ringwald * o Redistributions of source code must retain the above copyright   *
277dc86dfdSMatthias Ringwald *   notice, this list of conditions and the following disclaimer.    *
287dc86dfdSMatthias Ringwald *                                                                    *
297dc86dfdSMatthias Ringwald * o Redistributions in binary form must reproduce the above          *
307dc86dfdSMatthias Ringwald *   copyright notice, this list of conditions and the following      *
317dc86dfdSMatthias Ringwald *   disclaimer in the documentation and/or other materials provided  *
327dc86dfdSMatthias Ringwald *   with the distribution.                                           *
337dc86dfdSMatthias Ringwald *                                                                    *
34779af47bSMatthias Ringwald * o Neither the name of SEGGER Microcontroller GmbH                  *
357dc86dfdSMatthias Ringwald *   nor the names of its contributors may be used to endorse or      *
367dc86dfdSMatthias Ringwald *   promote products derived from this software without specific     *
377dc86dfdSMatthias Ringwald *   prior written permission.                                        *
387dc86dfdSMatthias Ringwald *                                                                    *
397dc86dfdSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
407dc86dfdSMatthias Ringwald * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
417dc86dfdSMatthias Ringwald * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
427dc86dfdSMatthias Ringwald * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
437dc86dfdSMatthias Ringwald * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
447dc86dfdSMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
457dc86dfdSMatthias Ringwald * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
467dc86dfdSMatthias Ringwald * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
477dc86dfdSMatthias Ringwald * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
487dc86dfdSMatthias Ringwald * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
497dc86dfdSMatthias Ringwald * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
507dc86dfdSMatthias Ringwald * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
517dc86dfdSMatthias Ringwald * DAMAGE.                                                            *
527dc86dfdSMatthias Ringwald *                                                                    *
537dc86dfdSMatthias Ringwald **********************************************************************
547dc86dfdSMatthias Ringwald ---------------------------END-OF-HEADER------------------------------
557dc86dfdSMatthias Ringwald File    : SEGGER_RTT.c
567dc86dfdSMatthias Ringwald Purpose : Implementation of SEGGER real-time transfer (RTT) which
577dc86dfdSMatthias Ringwald           allows real-time communication on targets which support
587dc86dfdSMatthias Ringwald           debugger memory accesses while the CPU is running.
59779af47bSMatthias Ringwald Revision: $Rev: 14765 $
607dc86dfdSMatthias Ringwald 
617dc86dfdSMatthias Ringwald Additional information:
627dc86dfdSMatthias Ringwald           Type "int" is assumed to be 32-bits in size
637dc86dfdSMatthias Ringwald           H->T    Host to target communication
647dc86dfdSMatthias Ringwald           T->H    Target to host communication
657dc86dfdSMatthias Ringwald 
667dc86dfdSMatthias Ringwald           RTT channel 0 is always present and reserved for Terminal usage.
677dc86dfdSMatthias Ringwald           Name is fixed to "Terminal"
687dc86dfdSMatthias Ringwald 
697dc86dfdSMatthias Ringwald           Effective buffer size: SizeOfBuffer - 1
707dc86dfdSMatthias Ringwald 
717dc86dfdSMatthias Ringwald           WrOff == RdOff:       Buffer is empty
727dc86dfdSMatthias Ringwald           WrOff == (RdOff - 1): Buffer is full
737dc86dfdSMatthias Ringwald           WrOff >  RdOff:       Free space includes wrap-around
747dc86dfdSMatthias Ringwald           WrOff <  RdOff:       Used space includes wrap-around
757dc86dfdSMatthias Ringwald           (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):
767dc86dfdSMatthias Ringwald                                 Buffer full and wrap-around after next byte
777dc86dfdSMatthias Ringwald 
787dc86dfdSMatthias Ringwald 
797dc86dfdSMatthias Ringwald ----------------------------------------------------------------------
807dc86dfdSMatthias Ringwald */
817dc86dfdSMatthias Ringwald 
827dc86dfdSMatthias Ringwald #include "SEGGER_RTT.h"
837dc86dfdSMatthias Ringwald 
847dc86dfdSMatthias Ringwald #include <string.h>                 // for memcpy
857dc86dfdSMatthias Ringwald 
867dc86dfdSMatthias Ringwald /*********************************************************************
877dc86dfdSMatthias Ringwald *
887dc86dfdSMatthias Ringwald *       Configuration, default values
897dc86dfdSMatthias Ringwald *
907dc86dfdSMatthias Ringwald **********************************************************************
917dc86dfdSMatthias Ringwald */
927dc86dfdSMatthias Ringwald 
937dc86dfdSMatthias Ringwald #ifndef   BUFFER_SIZE_UP
947dc86dfdSMatthias Ringwald   #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
957dc86dfdSMatthias Ringwald #endif
967dc86dfdSMatthias Ringwald 
977dc86dfdSMatthias Ringwald #ifndef   BUFFER_SIZE_DOWN
987dc86dfdSMatthias Ringwald   #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
997dc86dfdSMatthias Ringwald #endif
1007dc86dfdSMatthias Ringwald 
1017dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
1027dc86dfdSMatthias Ringwald   #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
1037dc86dfdSMatthias Ringwald #endif
1047dc86dfdSMatthias Ringwald 
1057dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
1067dc86dfdSMatthias Ringwald   #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
1077dc86dfdSMatthias Ringwald #endif
1087dc86dfdSMatthias Ringwald 
1097dc86dfdSMatthias Ringwald #ifndef SEGGER_RTT_BUFFER_SECTION
1107dc86dfdSMatthias Ringwald   #if defined(SEGGER_RTT_SECTION)
1117dc86dfdSMatthias Ringwald     #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
1127dc86dfdSMatthias Ringwald   #endif
1137dc86dfdSMatthias Ringwald #endif
1147dc86dfdSMatthias Ringwald 
1157dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_ALIGNMENT
1167dc86dfdSMatthias Ringwald   #define SEGGER_RTT_ALIGNMENT                            0
1177dc86dfdSMatthias Ringwald #endif
1187dc86dfdSMatthias Ringwald 
1197dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_BUFFER_ALIGNMENT
1207dc86dfdSMatthias Ringwald   #define SEGGER_RTT_BUFFER_ALIGNMENT                     0
1217dc86dfdSMatthias Ringwald #endif
1227dc86dfdSMatthias Ringwald 
1237dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_MODE_DEFAULT
1247dc86dfdSMatthias Ringwald   #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
1257dc86dfdSMatthias Ringwald #endif
1267dc86dfdSMatthias Ringwald 
1277dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_LOCK
1287dc86dfdSMatthias Ringwald   #define SEGGER_RTT_LOCK()
1297dc86dfdSMatthias Ringwald #endif
1307dc86dfdSMatthias Ringwald 
1317dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_UNLOCK
1327dc86dfdSMatthias Ringwald   #define SEGGER_RTT_UNLOCK()
1337dc86dfdSMatthias Ringwald #endif
1347dc86dfdSMatthias Ringwald 
1357dc86dfdSMatthias Ringwald #ifndef   STRLEN
1367dc86dfdSMatthias Ringwald   #define STRLEN(a)                                       strlen((a))
1377dc86dfdSMatthias Ringwald #endif
1387dc86dfdSMatthias Ringwald 
1397dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_MEMCPY_USE_BYTELOOP
1407dc86dfdSMatthias Ringwald   #define SEGGER_RTT_MEMCPY_USE_BYTELOOP                  0
1417dc86dfdSMatthias Ringwald #endif
1427dc86dfdSMatthias Ringwald 
1437dc86dfdSMatthias Ringwald #ifndef   SEGGER_RTT_MEMCPY
1447dc86dfdSMatthias Ringwald   #ifdef  MEMCPY
1457dc86dfdSMatthias Ringwald     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      MEMCPY((pDest), (pSrc), (NumBytes))
1467dc86dfdSMatthias Ringwald   #else
1477dc86dfdSMatthias Ringwald     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      memcpy((pDest), (pSrc), (NumBytes))
1487dc86dfdSMatthias Ringwald   #endif
1497dc86dfdSMatthias Ringwald #endif
1507dc86dfdSMatthias Ringwald 
1517dc86dfdSMatthias Ringwald #ifndef   MIN
1527dc86dfdSMatthias Ringwald   #define MIN(a, b)         (((a) < (b)) ? (a) : (b))
1537dc86dfdSMatthias Ringwald #endif
1547dc86dfdSMatthias Ringwald 
1557dc86dfdSMatthias Ringwald #ifndef   MAX
1567dc86dfdSMatthias Ringwald   #define MAX(a, b)         (((a) > (b)) ? (a) : (b))
1577dc86dfdSMatthias Ringwald #endif
1587dc86dfdSMatthias Ringwald //
1597dc86dfdSMatthias Ringwald // For some environments, NULL may not be defined until certain headers are included
1607dc86dfdSMatthias Ringwald //
1617dc86dfdSMatthias Ringwald #ifndef NULL
1627dc86dfdSMatthias Ringwald   #define NULL 0
1637dc86dfdSMatthias Ringwald #endif
1647dc86dfdSMatthias Ringwald 
1657dc86dfdSMatthias Ringwald /*********************************************************************
1667dc86dfdSMatthias Ringwald *
1677dc86dfdSMatthias Ringwald *       Defines, fixed
1687dc86dfdSMatthias Ringwald *
1697dc86dfdSMatthias Ringwald **********************************************************************
1707dc86dfdSMatthias Ringwald */
1717dc86dfdSMatthias Ringwald #if (defined __ICCARM__) || (defined __ICCRX__)
1727dc86dfdSMatthias Ringwald   #define RTT_PRAGMA(P) _Pragma(#P)
1737dc86dfdSMatthias Ringwald #endif
1747dc86dfdSMatthias Ringwald 
1757dc86dfdSMatthias Ringwald #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
1767dc86dfdSMatthias Ringwald   #if (defined __GNUC__)
1777dc86dfdSMatthias Ringwald     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
1787dc86dfdSMatthias Ringwald   #elif (defined __ICCARM__) || (defined __ICCRX__)
1797dc86dfdSMatthias Ringwald     #define PRAGMA(A) _Pragma(#A)
1807dc86dfdSMatthias Ringwald #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
1817dc86dfdSMatthias Ringwald                                   Var
1827dc86dfdSMatthias Ringwald   #elif (defined __CC_ARM)
1837dc86dfdSMatthias Ringwald     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
1847dc86dfdSMatthias Ringwald   #else
1857dc86dfdSMatthias Ringwald     #error "Alignment not supported for this compiler."
1867dc86dfdSMatthias Ringwald   #endif
1877dc86dfdSMatthias Ringwald #else
1887dc86dfdSMatthias Ringwald   #define SEGGER_RTT_ALIGN(Var, Alignment) Var
1897dc86dfdSMatthias Ringwald #endif
1907dc86dfdSMatthias Ringwald 
1917dc86dfdSMatthias Ringwald #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
1927dc86dfdSMatthias Ringwald   #if (defined __GNUC__)
1937dc86dfdSMatthias Ringwald     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
1947dc86dfdSMatthias Ringwald   #elif (defined __ICCARM__) || (defined __ICCRX__)
1957dc86dfdSMatthias Ringwald #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
1967dc86dfdSMatthias Ringwald                                         Var
1977dc86dfdSMatthias Ringwald   #elif (defined __CC_ARM)
1987dc86dfdSMatthias Ringwald     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init))  Var
1997dc86dfdSMatthias Ringwald   #else
2007dc86dfdSMatthias Ringwald     #error "Section placement not supported for this compiler."
2017dc86dfdSMatthias Ringwald   #endif
2027dc86dfdSMatthias Ringwald #else
2037dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
2047dc86dfdSMatthias Ringwald #endif
2057dc86dfdSMatthias Ringwald 
2067dc86dfdSMatthias Ringwald 
2077dc86dfdSMatthias Ringwald #if SEGGER_RTT_ALIGNMENT
2087dc86dfdSMatthias Ringwald   #define SEGGER_RTT_CB_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
2097dc86dfdSMatthias Ringwald #else
2107dc86dfdSMatthias Ringwald   #define SEGGER_RTT_CB_ALIGN(Var)  Var
2117dc86dfdSMatthias Ringwald #endif
2127dc86dfdSMatthias Ringwald 
2137dc86dfdSMatthias Ringwald #if SEGGER_RTT_BUFFER_ALIGNMENT
2147dc86dfdSMatthias Ringwald   #define SEGGER_RTT_BUFFER_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
2157dc86dfdSMatthias Ringwald #else
2167dc86dfdSMatthias Ringwald   #define SEGGER_RTT_BUFFER_ALIGN(Var)  Var
2177dc86dfdSMatthias Ringwald #endif
2187dc86dfdSMatthias Ringwald 
2197dc86dfdSMatthias Ringwald 
2207dc86dfdSMatthias Ringwald #if defined(SEGGER_RTT_SECTION)
2217dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
2227dc86dfdSMatthias Ringwald #else
2237dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
2247dc86dfdSMatthias Ringwald #endif
2257dc86dfdSMatthias Ringwald 
2267dc86dfdSMatthias Ringwald #if defined(SEGGER_RTT_BUFFER_SECTION)
2277dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
2287dc86dfdSMatthias Ringwald #else
2297dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
2307dc86dfdSMatthias Ringwald #endif
2317dc86dfdSMatthias Ringwald 
2327dc86dfdSMatthias Ringwald /*********************************************************************
2337dc86dfdSMatthias Ringwald *
2347dc86dfdSMatthias Ringwald *       Static const data
2357dc86dfdSMatthias Ringwald *
2367dc86dfdSMatthias Ringwald **********************************************************************
2377dc86dfdSMatthias Ringwald */
2387dc86dfdSMatthias Ringwald 
2397dc86dfdSMatthias Ringwald static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2407dc86dfdSMatthias Ringwald 
2417dc86dfdSMatthias Ringwald /*********************************************************************
2427dc86dfdSMatthias Ringwald *
2437dc86dfdSMatthias Ringwald *       Static data
2447dc86dfdSMatthias Ringwald *
2457dc86dfdSMatthias Ringwald **********************************************************************
2467dc86dfdSMatthias Ringwald */
2477dc86dfdSMatthias Ringwald //
2487dc86dfdSMatthias Ringwald // RTT Control Block and allocate buffers for channel 0
2497dc86dfdSMatthias Ringwald //
2507dc86dfdSMatthias Ringwald SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
2517dc86dfdSMatthias Ringwald 
2527dc86dfdSMatthias Ringwald SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer  [BUFFER_SIZE_UP]));
2537dc86dfdSMatthias Ringwald SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
2547dc86dfdSMatthias Ringwald 
255779af47bSMatthias Ringwald static unsigned char _ActiveTerminal;
2567dc86dfdSMatthias Ringwald 
2577dc86dfdSMatthias Ringwald /*********************************************************************
2587dc86dfdSMatthias Ringwald *
2597dc86dfdSMatthias Ringwald *       Static functions
2607dc86dfdSMatthias Ringwald *
2617dc86dfdSMatthias Ringwald **********************************************************************
2627dc86dfdSMatthias Ringwald */
2637dc86dfdSMatthias Ringwald 
2647dc86dfdSMatthias Ringwald /*********************************************************************
2657dc86dfdSMatthias Ringwald *
2667dc86dfdSMatthias Ringwald *       _DoInit()
2677dc86dfdSMatthias Ringwald *
2687dc86dfdSMatthias Ringwald *  Function description
2697dc86dfdSMatthias Ringwald *    Initializes the control block an buffers.
2707dc86dfdSMatthias Ringwald *    May only be called via INIT() to avoid overriding settings.
2717dc86dfdSMatthias Ringwald *
2727dc86dfdSMatthias Ringwald */
2737dc86dfdSMatthias Ringwald #define INIT()  do {                                            \
2747dc86dfdSMatthias Ringwald                   if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); }  \
2757dc86dfdSMatthias Ringwald                 } while (0)
2767dc86dfdSMatthias Ringwald static void _DoInit(void) {
2777dc86dfdSMatthias Ringwald   SEGGER_RTT_CB* p;
2787dc86dfdSMatthias Ringwald   //
2797dc86dfdSMatthias Ringwald   // Initialize control block
2807dc86dfdSMatthias Ringwald   //
2817dc86dfdSMatthias Ringwald   p = &_SEGGER_RTT;
2827dc86dfdSMatthias Ringwald   p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
2837dc86dfdSMatthias Ringwald   p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
2847dc86dfdSMatthias Ringwald   //
2857dc86dfdSMatthias Ringwald   // Initialize up buffer 0
2867dc86dfdSMatthias Ringwald   //
2877dc86dfdSMatthias Ringwald   p->aUp[0].sName         = "Terminal";
2887dc86dfdSMatthias Ringwald   p->aUp[0].pBuffer       = _acUpBuffer;
2897dc86dfdSMatthias Ringwald   p->aUp[0].SizeOfBuffer  = sizeof(_acUpBuffer);
2907dc86dfdSMatthias Ringwald   p->aUp[0].RdOff         = 0u;
2917dc86dfdSMatthias Ringwald   p->aUp[0].WrOff         = 0u;
2927dc86dfdSMatthias Ringwald   p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
2937dc86dfdSMatthias Ringwald   //
2947dc86dfdSMatthias Ringwald   // Initialize down buffer 0
2957dc86dfdSMatthias Ringwald   //
2967dc86dfdSMatthias Ringwald   p->aDown[0].sName         = "Terminal";
2977dc86dfdSMatthias Ringwald   p->aDown[0].pBuffer       = _acDownBuffer;
2987dc86dfdSMatthias Ringwald   p->aDown[0].SizeOfBuffer  = sizeof(_acDownBuffer);
2997dc86dfdSMatthias Ringwald   p->aDown[0].RdOff         = 0u;
3007dc86dfdSMatthias Ringwald   p->aDown[0].WrOff         = 0u;
3017dc86dfdSMatthias Ringwald   p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
3027dc86dfdSMatthias Ringwald   //
3037dc86dfdSMatthias Ringwald   // Finish initialization of the control block.
3047dc86dfdSMatthias Ringwald   // Copy Id string in three steps to make sure "SEGGER RTT" is not found
3057dc86dfdSMatthias Ringwald   // in initializer memory (usually flash) by J-Link
3067dc86dfdSMatthias Ringwald   //
3077dc86dfdSMatthias Ringwald   strcpy(&p->acID[7], "RTT");
3087dc86dfdSMatthias Ringwald   strcpy(&p->acID[0], "SEGGER");
3097dc86dfdSMatthias Ringwald   p->acID[6] = ' ';
3107dc86dfdSMatthias Ringwald }
3117dc86dfdSMatthias Ringwald 
3127dc86dfdSMatthias Ringwald /*********************************************************************
3137dc86dfdSMatthias Ringwald *
3147dc86dfdSMatthias Ringwald *       _WriteBlocking()
3157dc86dfdSMatthias Ringwald *
3167dc86dfdSMatthias Ringwald *  Function description
3177dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT ring buffer
3187dc86dfdSMatthias Ringwald *    and updates the associated write pointer which is periodically
3197dc86dfdSMatthias Ringwald *    read by the host.
3207dc86dfdSMatthias Ringwald *    The caller is responsible for managing the write chunk sizes as
3217dc86dfdSMatthias Ringwald *    _WriteBlocking() will block until all data has been posted successfully.
3227dc86dfdSMatthias Ringwald *
3237dc86dfdSMatthias Ringwald *  Parameters
3247dc86dfdSMatthias Ringwald *    pRing        Ring buffer to post to.
3257dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
3267dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
3277dc86dfdSMatthias Ringwald *
3287dc86dfdSMatthias Ringwald *  Return value
3297dc86dfdSMatthias Ringwald *    >= 0 - Number of bytes written into buffer.
3307dc86dfdSMatthias Ringwald */
3317dc86dfdSMatthias Ringwald static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
3327dc86dfdSMatthias Ringwald   unsigned NumBytesToWrite;
3337dc86dfdSMatthias Ringwald   unsigned NumBytesWritten;
3347dc86dfdSMatthias Ringwald   unsigned RdOff;
3357dc86dfdSMatthias Ringwald   unsigned WrOff;
3367dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
3377dc86dfdSMatthias Ringwald   char*    pDst;
3387dc86dfdSMatthias Ringwald #endif
3397dc86dfdSMatthias Ringwald   //
3407dc86dfdSMatthias Ringwald   // Write data to buffer and handle wrap-around if necessary
3417dc86dfdSMatthias Ringwald   //
3427dc86dfdSMatthias Ringwald   NumBytesWritten = 0u;
3437dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff;
3447dc86dfdSMatthias Ringwald   do {
3457dc86dfdSMatthias Ringwald     RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
3467dc86dfdSMatthias Ringwald     if (RdOff > WrOff) {
3477dc86dfdSMatthias Ringwald       NumBytesToWrite = RdOff - WrOff - 1u;
3487dc86dfdSMatthias Ringwald     } else {
3497dc86dfdSMatthias Ringwald       NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
3507dc86dfdSMatthias Ringwald     }
3517dc86dfdSMatthias Ringwald     NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
3527dc86dfdSMatthias Ringwald     NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
3537dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
3547dc86dfdSMatthias Ringwald     pDst = pRing->pBuffer + WrOff;
3557dc86dfdSMatthias Ringwald     NumBytesWritten += NumBytesToWrite;
3567dc86dfdSMatthias Ringwald     NumBytes        -= NumBytesToWrite;
3577dc86dfdSMatthias Ringwald     WrOff           += NumBytesToWrite;
3587dc86dfdSMatthias Ringwald     while (NumBytesToWrite--) {
3597dc86dfdSMatthias Ringwald       *pDst++ = *pBuffer++;
3607dc86dfdSMatthias Ringwald     };
3617dc86dfdSMatthias Ringwald #else
3627dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
3637dc86dfdSMatthias Ringwald     NumBytesWritten += NumBytesToWrite;
3647dc86dfdSMatthias Ringwald     pBuffer         += NumBytesToWrite;
3657dc86dfdSMatthias Ringwald     NumBytes        -= NumBytesToWrite;
3667dc86dfdSMatthias Ringwald     WrOff           += NumBytesToWrite;
3677dc86dfdSMatthias Ringwald #endif
3687dc86dfdSMatthias Ringwald     if (WrOff == pRing->SizeOfBuffer) {
3697dc86dfdSMatthias Ringwald       WrOff = 0u;
3707dc86dfdSMatthias Ringwald     }
3717dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff;
3727dc86dfdSMatthias Ringwald   } while (NumBytes);
3737dc86dfdSMatthias Ringwald   //
3747dc86dfdSMatthias Ringwald   return NumBytesWritten;
3757dc86dfdSMatthias Ringwald }
3767dc86dfdSMatthias Ringwald 
3777dc86dfdSMatthias Ringwald /*********************************************************************
3787dc86dfdSMatthias Ringwald *
3797dc86dfdSMatthias Ringwald *       _WriteNoCheck()
3807dc86dfdSMatthias Ringwald *
3817dc86dfdSMatthias Ringwald *  Function description
3827dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT ring buffer
3837dc86dfdSMatthias Ringwald *    and updates the associated write pointer which is periodically
3847dc86dfdSMatthias Ringwald *    read by the host.
3857dc86dfdSMatthias Ringwald *    It is callers responsibility to make sure data actually fits in buffer.
3867dc86dfdSMatthias Ringwald *
3877dc86dfdSMatthias Ringwald *  Parameters
3887dc86dfdSMatthias Ringwald *    pRing        Ring buffer to post to.
3897dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
3907dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
3917dc86dfdSMatthias Ringwald *
3927dc86dfdSMatthias Ringwald *  Notes
3937dc86dfdSMatthias Ringwald *    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
3947dc86dfdSMatthias Ringwald */
3957dc86dfdSMatthias Ringwald static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
3967dc86dfdSMatthias Ringwald   unsigned NumBytesAtOnce;
3977dc86dfdSMatthias Ringwald   unsigned WrOff;
3987dc86dfdSMatthias Ringwald   unsigned Rem;
3997dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
4007dc86dfdSMatthias Ringwald   char*    pDst;
4017dc86dfdSMatthias Ringwald #endif
4027dc86dfdSMatthias Ringwald 
4037dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff;
4047dc86dfdSMatthias Ringwald   Rem = pRing->SizeOfBuffer - WrOff;
4057dc86dfdSMatthias Ringwald   if (Rem > NumBytes) {
4067dc86dfdSMatthias Ringwald     //
4077dc86dfdSMatthias Ringwald     // All data fits before wrap around
4087dc86dfdSMatthias Ringwald     //
4097dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
4107dc86dfdSMatthias Ringwald     pDst = pRing->pBuffer + WrOff;
4117dc86dfdSMatthias Ringwald     WrOff += NumBytes;
4127dc86dfdSMatthias Ringwald     while (NumBytes--) {
4137dc86dfdSMatthias Ringwald       *pDst++ = *pData++;
4147dc86dfdSMatthias Ringwald     };
4157dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff;
4167dc86dfdSMatthias Ringwald #else
4177dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
4187dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff + NumBytes;
4197dc86dfdSMatthias Ringwald #endif
4207dc86dfdSMatthias Ringwald   } else {
4217dc86dfdSMatthias Ringwald     //
4227dc86dfdSMatthias Ringwald     // We reach the end of the buffer, so need to wrap around
4237dc86dfdSMatthias Ringwald     //
4247dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
4257dc86dfdSMatthias Ringwald     pDst = pRing->pBuffer + WrOff;
4267dc86dfdSMatthias Ringwald     NumBytesAtOnce = Rem;
4277dc86dfdSMatthias Ringwald     while (NumBytesAtOnce--) {
4287dc86dfdSMatthias Ringwald       *pDst++ = *pData++;
4297dc86dfdSMatthias Ringwald     };
4307dc86dfdSMatthias Ringwald     pDst = pRing->pBuffer;
4317dc86dfdSMatthias Ringwald     NumBytesAtOnce = NumBytes - Rem;
4327dc86dfdSMatthias Ringwald     while (NumBytesAtOnce--) {
4337dc86dfdSMatthias Ringwald       *pDst++ = *pData++;
4347dc86dfdSMatthias Ringwald     };
4357dc86dfdSMatthias Ringwald     pRing->WrOff = NumBytes - Rem;
4367dc86dfdSMatthias Ringwald #else
4377dc86dfdSMatthias Ringwald     NumBytesAtOnce = Rem;
4387dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
4397dc86dfdSMatthias Ringwald     NumBytesAtOnce = NumBytes - Rem;
4407dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
4417dc86dfdSMatthias Ringwald     pRing->WrOff = NumBytesAtOnce;
4427dc86dfdSMatthias Ringwald #endif
4437dc86dfdSMatthias Ringwald   }
4447dc86dfdSMatthias Ringwald }
4457dc86dfdSMatthias Ringwald 
4467dc86dfdSMatthias Ringwald /*********************************************************************
4477dc86dfdSMatthias Ringwald *
4487dc86dfdSMatthias Ringwald *       _PostTerminalSwitch()
4497dc86dfdSMatthias Ringwald *
4507dc86dfdSMatthias Ringwald *  Function description
4517dc86dfdSMatthias Ringwald *    Switch terminal to the given terminal ID.  It is the caller's
4527dc86dfdSMatthias Ringwald *    responsibility to ensure the terminal ID is correct and there is
4537dc86dfdSMatthias Ringwald *    enough space in the buffer for this to complete successfully.
4547dc86dfdSMatthias Ringwald *
4557dc86dfdSMatthias Ringwald *  Parameters
4567dc86dfdSMatthias Ringwald *    pRing        Ring buffer to post to.
4577dc86dfdSMatthias Ringwald *    TerminalId   Terminal ID to switch to.
4587dc86dfdSMatthias Ringwald */
4597dc86dfdSMatthias Ringwald static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
460779af47bSMatthias Ringwald   unsigned char ac[2];
4617dc86dfdSMatthias Ringwald 
4627dc86dfdSMatthias Ringwald   ac[0] = 0xFFu;
4637dc86dfdSMatthias Ringwald   ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
464779af47bSMatthias Ringwald   _WriteBlocking(pRing, (const char*)ac, 2u);
4657dc86dfdSMatthias Ringwald }
4667dc86dfdSMatthias Ringwald 
4677dc86dfdSMatthias Ringwald /*********************************************************************
4687dc86dfdSMatthias Ringwald *
4697dc86dfdSMatthias Ringwald *       _GetAvailWriteSpace()
4707dc86dfdSMatthias Ringwald *
4717dc86dfdSMatthias Ringwald *  Function description
4727dc86dfdSMatthias Ringwald *    Returns the number of bytes that can be written to the ring
4737dc86dfdSMatthias Ringwald *    buffer without blocking.
4747dc86dfdSMatthias Ringwald *
4757dc86dfdSMatthias Ringwald *  Parameters
4767dc86dfdSMatthias Ringwald *    pRing        Ring buffer to check.
4777dc86dfdSMatthias Ringwald *
4787dc86dfdSMatthias Ringwald *  Return value
4797dc86dfdSMatthias Ringwald *    Number of bytes that are free in the buffer.
4807dc86dfdSMatthias Ringwald */
4817dc86dfdSMatthias Ringwald static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
4827dc86dfdSMatthias Ringwald   unsigned RdOff;
4837dc86dfdSMatthias Ringwald   unsigned WrOff;
4847dc86dfdSMatthias Ringwald   unsigned r;
4857dc86dfdSMatthias Ringwald   //
4867dc86dfdSMatthias Ringwald   // Avoid warnings regarding volatile access order.  It's not a problem
4877dc86dfdSMatthias Ringwald   // in this case, but dampen compiler enthusiasm.
4887dc86dfdSMatthias Ringwald   //
4897dc86dfdSMatthias Ringwald   RdOff = pRing->RdOff;
4907dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff;
4917dc86dfdSMatthias Ringwald   if (RdOff <= WrOff) {
4927dc86dfdSMatthias Ringwald     r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
4937dc86dfdSMatthias Ringwald   } else {
4947dc86dfdSMatthias Ringwald     r = RdOff - WrOff - 1u;
4957dc86dfdSMatthias Ringwald   }
4967dc86dfdSMatthias Ringwald   return r;
4977dc86dfdSMatthias Ringwald }
4987dc86dfdSMatthias Ringwald 
4997dc86dfdSMatthias Ringwald /*********************************************************************
5007dc86dfdSMatthias Ringwald *
5017dc86dfdSMatthias Ringwald *       Public code
5027dc86dfdSMatthias Ringwald *
5037dc86dfdSMatthias Ringwald **********************************************************************
5047dc86dfdSMatthias Ringwald */
5057dc86dfdSMatthias Ringwald /*********************************************************************
5067dc86dfdSMatthias Ringwald *
5077dc86dfdSMatthias Ringwald *       SEGGER_RTT_ReadNoLock()
5087dc86dfdSMatthias Ringwald *
5097dc86dfdSMatthias Ringwald *  Function description
5107dc86dfdSMatthias Ringwald *    Reads characters from SEGGER real-time-terminal control block
5117dc86dfdSMatthias Ringwald *    which have been previously stored by the host.
5127dc86dfdSMatthias Ringwald *    Do not lock against interrupts and multiple access.
5137dc86dfdSMatthias Ringwald *
5147dc86dfdSMatthias Ringwald *  Parameters
5157dc86dfdSMatthias Ringwald *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
5167dc86dfdSMatthias Ringwald *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
5177dc86dfdSMatthias Ringwald *    BufferSize   Size of the target application buffer.
5187dc86dfdSMatthias Ringwald *
5197dc86dfdSMatthias Ringwald *  Return value
5207dc86dfdSMatthias Ringwald *    Number of bytes that have been read.
5217dc86dfdSMatthias Ringwald */
5227dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
5237dc86dfdSMatthias Ringwald   unsigned                NumBytesRem;
5247dc86dfdSMatthias Ringwald   unsigned                NumBytesRead;
5257dc86dfdSMatthias Ringwald   unsigned                RdOff;
5267dc86dfdSMatthias Ringwald   unsigned                WrOff;
5277dc86dfdSMatthias Ringwald   unsigned char*          pBuffer;
5287dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_DOWN* pRing;
5297dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
5307dc86dfdSMatthias Ringwald   const char*             pSrc;
5317dc86dfdSMatthias Ringwald #endif
5327dc86dfdSMatthias Ringwald   //
5337dc86dfdSMatthias Ringwald   INIT();
5347dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aDown[BufferIndex];
5357dc86dfdSMatthias Ringwald   pBuffer = (unsigned char*)pData;
5367dc86dfdSMatthias Ringwald   RdOff = pRing->RdOff;
5377dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff;
5387dc86dfdSMatthias Ringwald   NumBytesRead = 0u;
5397dc86dfdSMatthias Ringwald   //
5407dc86dfdSMatthias Ringwald   // Read from current read position to wrap-around of buffer, first
5417dc86dfdSMatthias Ringwald   //
5427dc86dfdSMatthias Ringwald   if (RdOff > WrOff) {
5437dc86dfdSMatthias Ringwald     NumBytesRem = pRing->SizeOfBuffer - RdOff;
5447dc86dfdSMatthias Ringwald     NumBytesRem = MIN(NumBytesRem, BufferSize);
5457dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
5467dc86dfdSMatthias Ringwald     pSrc = pRing->pBuffer + RdOff;
5477dc86dfdSMatthias Ringwald     NumBytesRead += NumBytesRem;
5487dc86dfdSMatthias Ringwald     BufferSize   -= NumBytesRem;
5497dc86dfdSMatthias Ringwald     RdOff        += NumBytesRem;
5507dc86dfdSMatthias Ringwald     while (NumBytesRem--) {
5517dc86dfdSMatthias Ringwald       *pBuffer++ = *pSrc++;
5527dc86dfdSMatthias Ringwald     };
5537dc86dfdSMatthias Ringwald #else
5547dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
5557dc86dfdSMatthias Ringwald     NumBytesRead += NumBytesRem;
5567dc86dfdSMatthias Ringwald     pBuffer      += NumBytesRem;
5577dc86dfdSMatthias Ringwald     BufferSize   -= NumBytesRem;
5587dc86dfdSMatthias Ringwald     RdOff        += NumBytesRem;
5597dc86dfdSMatthias Ringwald #endif
5607dc86dfdSMatthias Ringwald     //
5617dc86dfdSMatthias Ringwald     // Handle wrap-around of buffer
5627dc86dfdSMatthias Ringwald     //
5637dc86dfdSMatthias Ringwald     if (RdOff == pRing->SizeOfBuffer) {
5647dc86dfdSMatthias Ringwald       RdOff = 0u;
5657dc86dfdSMatthias Ringwald     }
5667dc86dfdSMatthias Ringwald   }
5677dc86dfdSMatthias Ringwald   //
5687dc86dfdSMatthias Ringwald   // Read remaining items of buffer
5697dc86dfdSMatthias Ringwald   //
5707dc86dfdSMatthias Ringwald   NumBytesRem = WrOff - RdOff;
5717dc86dfdSMatthias Ringwald   NumBytesRem = MIN(NumBytesRem, BufferSize);
5727dc86dfdSMatthias Ringwald   if (NumBytesRem > 0u) {
5737dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
5747dc86dfdSMatthias Ringwald     pSrc = pRing->pBuffer + RdOff;
5757dc86dfdSMatthias Ringwald     NumBytesRead += NumBytesRem;
5767dc86dfdSMatthias Ringwald     BufferSize   -= NumBytesRem;
5777dc86dfdSMatthias Ringwald     RdOff        += NumBytesRem;
5787dc86dfdSMatthias Ringwald     while (NumBytesRem--) {
5797dc86dfdSMatthias Ringwald       *pBuffer++ = *pSrc++;
5807dc86dfdSMatthias Ringwald     };
5817dc86dfdSMatthias Ringwald #else
5827dc86dfdSMatthias Ringwald     SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
5837dc86dfdSMatthias Ringwald     NumBytesRead += NumBytesRem;
5847dc86dfdSMatthias Ringwald     pBuffer      += NumBytesRem;
5857dc86dfdSMatthias Ringwald     BufferSize   -= NumBytesRem;
5867dc86dfdSMatthias Ringwald     RdOff        += NumBytesRem;
5877dc86dfdSMatthias Ringwald #endif
5887dc86dfdSMatthias Ringwald   }
5897dc86dfdSMatthias Ringwald   if (NumBytesRead) {
5907dc86dfdSMatthias Ringwald     pRing->RdOff = RdOff;
5917dc86dfdSMatthias Ringwald   }
5927dc86dfdSMatthias Ringwald   //
5937dc86dfdSMatthias Ringwald   return NumBytesRead;
5947dc86dfdSMatthias Ringwald }
5957dc86dfdSMatthias Ringwald 
5967dc86dfdSMatthias Ringwald /*********************************************************************
5977dc86dfdSMatthias Ringwald *
5987dc86dfdSMatthias Ringwald *       SEGGER_RTT_Read
5997dc86dfdSMatthias Ringwald *
6007dc86dfdSMatthias Ringwald *  Function description
6017dc86dfdSMatthias Ringwald *    Reads characters from SEGGER real-time-terminal control block
6027dc86dfdSMatthias Ringwald *    which have been previously stored by the host.
6037dc86dfdSMatthias Ringwald *
6047dc86dfdSMatthias Ringwald *  Parameters
6057dc86dfdSMatthias Ringwald *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
6067dc86dfdSMatthias Ringwald *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
6077dc86dfdSMatthias Ringwald *    BufferSize   Size of the target application buffer.
6087dc86dfdSMatthias Ringwald *
6097dc86dfdSMatthias Ringwald *  Return value
6107dc86dfdSMatthias Ringwald *    Number of bytes that have been read.
6117dc86dfdSMatthias Ringwald */
6127dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
6137dc86dfdSMatthias Ringwald   unsigned NumBytesRead;
6147dc86dfdSMatthias Ringwald   //
6157dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
6167dc86dfdSMatthias Ringwald   //
6177dc86dfdSMatthias Ringwald   // Call the non-locking read function
6187dc86dfdSMatthias Ringwald   //
6197dc86dfdSMatthias Ringwald   NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
6207dc86dfdSMatthias Ringwald   //
6217dc86dfdSMatthias Ringwald   // Finish up.
6227dc86dfdSMatthias Ringwald   //
6237dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
6247dc86dfdSMatthias Ringwald   //
6257dc86dfdSMatthias Ringwald   return NumBytesRead;
6267dc86dfdSMatthias Ringwald }
6277dc86dfdSMatthias Ringwald 
6287dc86dfdSMatthias Ringwald /*********************************************************************
6297dc86dfdSMatthias Ringwald *
6307dc86dfdSMatthias Ringwald *       SEGGER_RTT_WriteWithOverwriteNoLock
6317dc86dfdSMatthias Ringwald *
6327dc86dfdSMatthias Ringwald *  Function description
6337dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT
6347dc86dfdSMatthias Ringwald *    control block.
6357dc86dfdSMatthias Ringwald *    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application
6367dc86dfdSMatthias Ringwald *    and overwrites data if the data does not fit into the buffer.
6377dc86dfdSMatthias Ringwald *
6387dc86dfdSMatthias Ringwald *  Parameters
6397dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
6407dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
6417dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
6427dc86dfdSMatthias Ringwald *
6437dc86dfdSMatthias Ringwald *  Notes
6447dc86dfdSMatthias Ringwald *    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
6457dc86dfdSMatthias Ringwald *    (2) For performance reasons this function does not call Init()
6467dc86dfdSMatthias Ringwald *        and may only be called after RTT has been initialized.
6477dc86dfdSMatthias Ringwald *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
6487dc86dfdSMatthias Ringwald *    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link
6497dc86dfdSMatthias Ringwald *        connection reads RTT data.
6507dc86dfdSMatthias Ringwald */
6517dc86dfdSMatthias Ringwald void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
6527dc86dfdSMatthias Ringwald   const char*           pData;
6537dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
6547dc86dfdSMatthias Ringwald   unsigned              Avail;
6557dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
6567dc86dfdSMatthias Ringwald   char*                 pDst;
6577dc86dfdSMatthias Ringwald #endif
6587dc86dfdSMatthias Ringwald 
6597dc86dfdSMatthias Ringwald   pData = (const char *)pBuffer;
6607dc86dfdSMatthias Ringwald   //
6617dc86dfdSMatthias Ringwald   // Get "to-host" ring buffer and copy some elements into local variables.
6627dc86dfdSMatthias Ringwald   //
6637dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
6647dc86dfdSMatthias Ringwald   //
6657dc86dfdSMatthias Ringwald   // Check if we will overwrite data and need to adjust the RdOff.
6667dc86dfdSMatthias Ringwald   //
6677dc86dfdSMatthias Ringwald   if (pRing->WrOff == pRing->RdOff) {
6687dc86dfdSMatthias Ringwald     Avail = pRing->SizeOfBuffer - 1u;
6697dc86dfdSMatthias Ringwald   } else if ( pRing->WrOff < pRing->RdOff) {
6707dc86dfdSMatthias Ringwald     Avail = pRing->RdOff - pRing->WrOff - 1u;
6717dc86dfdSMatthias Ringwald   } else {
6727dc86dfdSMatthias Ringwald     Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
6737dc86dfdSMatthias Ringwald   }
6747dc86dfdSMatthias Ringwald   if (NumBytes > Avail) {
6757dc86dfdSMatthias Ringwald     pRing->RdOff += (NumBytes - Avail);
6767dc86dfdSMatthias Ringwald     while (pRing->RdOff >= pRing->SizeOfBuffer) {
6777dc86dfdSMatthias Ringwald       pRing->RdOff -= pRing->SizeOfBuffer;
6787dc86dfdSMatthias Ringwald     }
6797dc86dfdSMatthias Ringwald   }
6807dc86dfdSMatthias Ringwald   //
6817dc86dfdSMatthias Ringwald   // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
6827dc86dfdSMatthias Ringwald   //
6837dc86dfdSMatthias Ringwald   Avail = pRing->SizeOfBuffer - pRing->WrOff;
6847dc86dfdSMatthias Ringwald   do {
6857dc86dfdSMatthias Ringwald     if (Avail > NumBytes) {
6867dc86dfdSMatthias Ringwald       //
6877dc86dfdSMatthias Ringwald       // Last round
6887dc86dfdSMatthias Ringwald       //
6897dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
6907dc86dfdSMatthias Ringwald       pDst = pRing->pBuffer + pRing->WrOff;
6917dc86dfdSMatthias Ringwald       Avail = NumBytes;
6927dc86dfdSMatthias Ringwald       while (NumBytes--) {
6937dc86dfdSMatthias Ringwald         *pDst++ = *pData++;
6947dc86dfdSMatthias Ringwald       };
6957dc86dfdSMatthias Ringwald       pRing->WrOff += Avail;
6967dc86dfdSMatthias Ringwald #else
6977dc86dfdSMatthias Ringwald       SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes);
6987dc86dfdSMatthias Ringwald       pRing->WrOff += NumBytes;
6997dc86dfdSMatthias Ringwald #endif
7007dc86dfdSMatthias Ringwald       break;
7017dc86dfdSMatthias Ringwald     } else {
7027dc86dfdSMatthias Ringwald       //
7037dc86dfdSMatthias Ringwald       //  Wrap-around necessary, write until wrap-around and reset WrOff
7047dc86dfdSMatthias Ringwald       //
7057dc86dfdSMatthias Ringwald #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
7067dc86dfdSMatthias Ringwald       pDst = pRing->pBuffer + pRing->WrOff;
7077dc86dfdSMatthias Ringwald       NumBytes -= Avail;
7087dc86dfdSMatthias Ringwald       while (Avail--) {
7097dc86dfdSMatthias Ringwald         *pDst++ = *pData++;
7107dc86dfdSMatthias Ringwald       };
7117dc86dfdSMatthias Ringwald       pRing->WrOff = 0;
7127dc86dfdSMatthias Ringwald #else
7137dc86dfdSMatthias Ringwald       SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail);
7147dc86dfdSMatthias Ringwald       pData += Avail;
7157dc86dfdSMatthias Ringwald       pRing->WrOff = 0;
7167dc86dfdSMatthias Ringwald       NumBytes -= Avail;
7177dc86dfdSMatthias Ringwald #endif
7187dc86dfdSMatthias Ringwald       Avail = (pRing->SizeOfBuffer - 1);
7197dc86dfdSMatthias Ringwald     }
7207dc86dfdSMatthias Ringwald   } while (NumBytes);
7217dc86dfdSMatthias Ringwald }
7227dc86dfdSMatthias Ringwald 
7237dc86dfdSMatthias Ringwald /*********************************************************************
7247dc86dfdSMatthias Ringwald *
7257dc86dfdSMatthias Ringwald *       SEGGER_RTT_WriteSkipNoLock
7267dc86dfdSMatthias Ringwald *
7277dc86dfdSMatthias Ringwald *  Function description
7287dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT
7297dc86dfdSMatthias Ringwald *    control block which is then read by the host.
7307dc86dfdSMatthias Ringwald *    SEGGER_RTT_WriteSkipNoLock does not lock the application and
7317dc86dfdSMatthias Ringwald *    skips all data, if the data does not fit into the buffer.
7327dc86dfdSMatthias Ringwald *
7337dc86dfdSMatthias Ringwald *  Parameters
7347dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
7357dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
7367dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
737779af47bSMatthias Ringwald *                 MUST be > 0!!!
738779af47bSMatthias Ringwald *                 This is done for performance reasons, so no initial check has do be done.
7397dc86dfdSMatthias Ringwald *
7407dc86dfdSMatthias Ringwald *  Return value
741779af47bSMatthias Ringwald *    1: Data has been copied
742779af47bSMatthias Ringwald *    0: No space, data has not been copied
7437dc86dfdSMatthias Ringwald *
7447dc86dfdSMatthias Ringwald *  Notes
7457dc86dfdSMatthias Ringwald *    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
7467dc86dfdSMatthias Ringwald *    (2) For performance reasons this function does not call Init()
7477dc86dfdSMatthias Ringwald *        and may only be called after RTT has been initialized.
7487dc86dfdSMatthias Ringwald *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
7497dc86dfdSMatthias Ringwald */
750779af47bSMatthias Ringwald #if (RTT_USE_ASM == 0)
7517dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
7527dc86dfdSMatthias Ringwald   const char*           pData;
7537dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
7547dc86dfdSMatthias Ringwald   unsigned              Avail;
7557dc86dfdSMatthias Ringwald   unsigned              RdOff;
7567dc86dfdSMatthias Ringwald   unsigned              WrOff;
7577dc86dfdSMatthias Ringwald   unsigned              Rem;
758779af47bSMatthias Ringwald   //
759779af47bSMatthias Ringwald   // Cases:
760779af47bSMatthias Ringwald   //   1) RdOff <= WrOff => Space until wrap-around is sufficient
761779af47bSMatthias Ringwald   //   2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
762779af47bSMatthias Ringwald   //   3) RdOff <  WrOff => No space in buf
763779af47bSMatthias Ringwald   //   4) RdOff >  WrOff => Space is sufficient
764779af47bSMatthias Ringwald   //   5) RdOff >  WrOff => No space in buf
765779af47bSMatthias Ringwald   //
766779af47bSMatthias Ringwald   // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
767779af47bSMatthias Ringwald   //
7687dc86dfdSMatthias Ringwald   pData = (const char *)pBuffer;
7697dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
7707dc86dfdSMatthias Ringwald   RdOff = pRing->RdOff;
7717dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff;
772779af47bSMatthias Ringwald   if (RdOff <= WrOff) {                                 // Case 1), 2) or 3)
773779af47bSMatthias Ringwald     Avail = pRing->SizeOfBuffer - WrOff - 1u;           // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
774779af47bSMatthias Ringwald     if (Avail >= NumBytes) {                            // Case 1)?
775779af47bSMatthias Ringwald CopyStraight:
776779af47bSMatthias Ringwald       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
7777dc86dfdSMatthias Ringwald       pRing->WrOff = WrOff + NumBytes;
7787dc86dfdSMatthias Ringwald       return 1;
7797dc86dfdSMatthias Ringwald     }
780779af47bSMatthias Ringwald     Avail += RdOff;                                     // Space incl. wrap-around
781779af47bSMatthias Ringwald     if (Avail >= NumBytes) {                            // Case 2? => If not, we have case 3) (does not fit)
7827dc86dfdSMatthias Ringwald       Rem = pRing->SizeOfBuffer - WrOff;                // Space until end of buffer
783779af47bSMatthias Ringwald       memcpy(pRing->pBuffer + WrOff, pData, Rem);       // Copy 1st chunk
7847dc86dfdSMatthias Ringwald       NumBytes -= Rem;
785779af47bSMatthias Ringwald       //
786779af47bSMatthias Ringwald       // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
787779af47bSMatthias Ringwald       // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
788779af47bSMatthias Ringwald       // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
789779af47bSMatthias Ringwald       // Therefore, check if 2nd memcpy is necessary at all
790779af47bSMatthias Ringwald       //
791779af47bSMatthias Ringwald       if (NumBytes) {
792779af47bSMatthias Ringwald         memcpy(pRing->pBuffer, pData + Rem, NumBytes);
7937dc86dfdSMatthias Ringwald       }
794779af47bSMatthias Ringwald       pRing->WrOff = NumBytes;
7957dc86dfdSMatthias Ringwald       return 1;
7967dc86dfdSMatthias Ringwald     }
797779af47bSMatthias Ringwald   } else {                                             // Potential case 4)
7987dc86dfdSMatthias Ringwald     Avail = RdOff - WrOff - 1u;
799779af47bSMatthias Ringwald     if (Avail >= NumBytes) {                           // Case 4)? => If not, we have case 5) (does not fit)
800779af47bSMatthias Ringwald       goto CopyStraight;
801779af47bSMatthias Ringwald     }
802779af47bSMatthias Ringwald   }
803779af47bSMatthias Ringwald   return 0;     // No space in buffer
804779af47bSMatthias Ringwald }
8057dc86dfdSMatthias Ringwald #endif
8067dc86dfdSMatthias Ringwald 
8077dc86dfdSMatthias Ringwald /*********************************************************************
8087dc86dfdSMatthias Ringwald *
8097dc86dfdSMatthias Ringwald *       SEGGER_RTT_WriteNoLock
8107dc86dfdSMatthias Ringwald *
8117dc86dfdSMatthias Ringwald *  Function description
8127dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT
8137dc86dfdSMatthias Ringwald *    control block which is then read by the host.
8147dc86dfdSMatthias Ringwald *    SEGGER_RTT_WriteNoLock does not lock the application.
8157dc86dfdSMatthias Ringwald *
8167dc86dfdSMatthias Ringwald *  Parameters
8177dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
8187dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
8197dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
8207dc86dfdSMatthias Ringwald *
8217dc86dfdSMatthias Ringwald *  Return value
8227dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
8237dc86dfdSMatthias Ringwald *
8247dc86dfdSMatthias Ringwald *  Notes
8257dc86dfdSMatthias Ringwald *    (1) Data is stored according to buffer flags.
8267dc86dfdSMatthias Ringwald *    (2) For performance reasons this function does not call Init()
8277dc86dfdSMatthias Ringwald *        and may only be called after RTT has been initialized.
8287dc86dfdSMatthias Ringwald *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
8297dc86dfdSMatthias Ringwald */
8307dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
8317dc86dfdSMatthias Ringwald   unsigned              Status;
8327dc86dfdSMatthias Ringwald   unsigned              Avail;
8337dc86dfdSMatthias Ringwald   const char*           pData;
8347dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
8357dc86dfdSMatthias Ringwald 
8367dc86dfdSMatthias Ringwald   pData = (const char *)pBuffer;
8377dc86dfdSMatthias Ringwald   //
8387dc86dfdSMatthias Ringwald   // Get "to-host" ring buffer.
8397dc86dfdSMatthias Ringwald   //
8407dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
8417dc86dfdSMatthias Ringwald   //
8427dc86dfdSMatthias Ringwald   // How we output depends upon the mode...
8437dc86dfdSMatthias Ringwald   //
8447dc86dfdSMatthias Ringwald   switch (pRing->Flags) {
8457dc86dfdSMatthias Ringwald   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
8467dc86dfdSMatthias Ringwald     //
8477dc86dfdSMatthias Ringwald     // If we are in skip mode and there is no space for the whole
8487dc86dfdSMatthias Ringwald     // of this output, don't bother.
8497dc86dfdSMatthias Ringwald     //
8507dc86dfdSMatthias Ringwald     Avail = _GetAvailWriteSpace(pRing);
8517dc86dfdSMatthias Ringwald     if (Avail < NumBytes) {
8527dc86dfdSMatthias Ringwald       Status = 0u;
8537dc86dfdSMatthias Ringwald     } else {
8547dc86dfdSMatthias Ringwald       Status = NumBytes;
8557dc86dfdSMatthias Ringwald       _WriteNoCheck(pRing, pData, NumBytes);
8567dc86dfdSMatthias Ringwald     }
8577dc86dfdSMatthias Ringwald     break;
8587dc86dfdSMatthias Ringwald   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
8597dc86dfdSMatthias Ringwald     //
8607dc86dfdSMatthias Ringwald     // If we are in trim mode, trim to what we can output without blocking.
8617dc86dfdSMatthias Ringwald     //
8627dc86dfdSMatthias Ringwald     Avail = _GetAvailWriteSpace(pRing);
8637dc86dfdSMatthias Ringwald     Status = Avail < NumBytes ? Avail : NumBytes;
8647dc86dfdSMatthias Ringwald     _WriteNoCheck(pRing, pData, Status);
8657dc86dfdSMatthias Ringwald     break;
8667dc86dfdSMatthias Ringwald   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
8677dc86dfdSMatthias Ringwald     //
8687dc86dfdSMatthias Ringwald     // If we are in blocking mode, output everything.
8697dc86dfdSMatthias Ringwald     //
8707dc86dfdSMatthias Ringwald     Status = _WriteBlocking(pRing, pData, NumBytes);
8717dc86dfdSMatthias Ringwald     break;
8727dc86dfdSMatthias Ringwald   default:
8737dc86dfdSMatthias Ringwald     Status = 0u;
8747dc86dfdSMatthias Ringwald     break;
8757dc86dfdSMatthias Ringwald   }
8767dc86dfdSMatthias Ringwald   //
8777dc86dfdSMatthias Ringwald   // Finish up.
8787dc86dfdSMatthias Ringwald   //
8797dc86dfdSMatthias Ringwald   return Status;
8807dc86dfdSMatthias Ringwald }
8817dc86dfdSMatthias Ringwald 
8827dc86dfdSMatthias Ringwald /*********************************************************************
8837dc86dfdSMatthias Ringwald *
8847dc86dfdSMatthias Ringwald *       SEGGER_RTT_Write
8857dc86dfdSMatthias Ringwald *
8867dc86dfdSMatthias Ringwald *  Function description
8877dc86dfdSMatthias Ringwald *    Stores a specified number of characters in SEGGER RTT
8887dc86dfdSMatthias Ringwald *    control block which is then read by the host.
8897dc86dfdSMatthias Ringwald *
8907dc86dfdSMatthias Ringwald *  Parameters
8917dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
8927dc86dfdSMatthias Ringwald *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
8937dc86dfdSMatthias Ringwald *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
8947dc86dfdSMatthias Ringwald *
8957dc86dfdSMatthias Ringwald *  Return value
8967dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
8977dc86dfdSMatthias Ringwald *
8987dc86dfdSMatthias Ringwald *  Notes
8997dc86dfdSMatthias Ringwald *    (1) Data is stored according to buffer flags.
9007dc86dfdSMatthias Ringwald */
9017dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
9027dc86dfdSMatthias Ringwald   unsigned Status;
9037dc86dfdSMatthias Ringwald   //
9047dc86dfdSMatthias Ringwald   INIT();
9057dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
9067dc86dfdSMatthias Ringwald   //
9077dc86dfdSMatthias Ringwald   // Call the non-locking write function
9087dc86dfdSMatthias Ringwald   //
9097dc86dfdSMatthias Ringwald   Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
9107dc86dfdSMatthias Ringwald   //
9117dc86dfdSMatthias Ringwald   // Finish up.
9127dc86dfdSMatthias Ringwald   //
9137dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
9147dc86dfdSMatthias Ringwald   //
9157dc86dfdSMatthias Ringwald   return Status;
9167dc86dfdSMatthias Ringwald }
9177dc86dfdSMatthias Ringwald 
9187dc86dfdSMatthias Ringwald /*********************************************************************
9197dc86dfdSMatthias Ringwald *
9207dc86dfdSMatthias Ringwald *       SEGGER_RTT_WriteString
9217dc86dfdSMatthias Ringwald *
9227dc86dfdSMatthias Ringwald *  Function description
9237dc86dfdSMatthias Ringwald *    Stores string in SEGGER RTT control block.
9247dc86dfdSMatthias Ringwald *    This data is read by the host.
9257dc86dfdSMatthias Ringwald *
9267dc86dfdSMatthias Ringwald *  Parameters
9277dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
9287dc86dfdSMatthias Ringwald *    s            Pointer to string.
9297dc86dfdSMatthias Ringwald *
9307dc86dfdSMatthias Ringwald *  Return value
9317dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
9327dc86dfdSMatthias Ringwald *
9337dc86dfdSMatthias Ringwald *  Notes
9347dc86dfdSMatthias Ringwald *    (1) Data is stored according to buffer flags.
9357dc86dfdSMatthias Ringwald *    (2) String passed to this function has to be \0 terminated
9367dc86dfdSMatthias Ringwald *    (3) \0 termination character is *not* stored in RTT buffer
9377dc86dfdSMatthias Ringwald */
9387dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
9397dc86dfdSMatthias Ringwald   unsigned Len;
9407dc86dfdSMatthias Ringwald 
9417dc86dfdSMatthias Ringwald   Len = STRLEN(s);
9427dc86dfdSMatthias Ringwald   return SEGGER_RTT_Write(BufferIndex, s, Len);
9437dc86dfdSMatthias Ringwald }
9447dc86dfdSMatthias Ringwald 
9457dc86dfdSMatthias Ringwald /*********************************************************************
9467dc86dfdSMatthias Ringwald *
9477dc86dfdSMatthias Ringwald *       SEGGER_RTT_PutCharSkipNoLock
9487dc86dfdSMatthias Ringwald *
9497dc86dfdSMatthias Ringwald *  Function description
9507dc86dfdSMatthias Ringwald *    Stores a single character/byte in SEGGER RTT buffer.
9517dc86dfdSMatthias Ringwald *    SEGGER_RTT_PutCharSkipNoLock does not lock the application and
9527dc86dfdSMatthias Ringwald *    skips the byte, if it does not fit into the buffer.
9537dc86dfdSMatthias Ringwald *
9547dc86dfdSMatthias Ringwald *  Parameters
9557dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
9567dc86dfdSMatthias Ringwald *    c            Byte to be stored.
9577dc86dfdSMatthias Ringwald *
9587dc86dfdSMatthias Ringwald *  Return value
9597dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
9607dc86dfdSMatthias Ringwald *
9617dc86dfdSMatthias Ringwald *  Notes
9627dc86dfdSMatthias Ringwald *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
9637dc86dfdSMatthias Ringwald *    (2) For performance reasons this function does not call Init()
9647dc86dfdSMatthias Ringwald *        and may only be called after RTT has been initialized.
9657dc86dfdSMatthias Ringwald *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
9667dc86dfdSMatthias Ringwald */
9677dc86dfdSMatthias Ringwald 
9687dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
9697dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
9707dc86dfdSMatthias Ringwald   unsigned              WrOff;
9717dc86dfdSMatthias Ringwald   unsigned              Status;
9727dc86dfdSMatthias Ringwald   //
9737dc86dfdSMatthias Ringwald   // Get "to-host" ring buffer.
9747dc86dfdSMatthias Ringwald   //
9757dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
9767dc86dfdSMatthias Ringwald   //
9777dc86dfdSMatthias Ringwald   // Get write position and handle wrap-around if necessary
9787dc86dfdSMatthias Ringwald   //
9797dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff + 1;
9807dc86dfdSMatthias Ringwald   if (WrOff == pRing->SizeOfBuffer) {
9817dc86dfdSMatthias Ringwald     WrOff = 0;
9827dc86dfdSMatthias Ringwald   }
9837dc86dfdSMatthias Ringwald   //
9847dc86dfdSMatthias Ringwald   // Output byte if free space is available
9857dc86dfdSMatthias Ringwald   //
9867dc86dfdSMatthias Ringwald   if (WrOff != pRing->RdOff) {
9877dc86dfdSMatthias Ringwald     pRing->pBuffer[pRing->WrOff] = c;
9887dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff;
9897dc86dfdSMatthias Ringwald     Status = 1;
9907dc86dfdSMatthias Ringwald   } else {
9917dc86dfdSMatthias Ringwald     Status = 0;
9927dc86dfdSMatthias Ringwald   }
9937dc86dfdSMatthias Ringwald   //
9947dc86dfdSMatthias Ringwald   return Status;
9957dc86dfdSMatthias Ringwald }
9967dc86dfdSMatthias Ringwald 
9977dc86dfdSMatthias Ringwald /*********************************************************************
9987dc86dfdSMatthias Ringwald *
9997dc86dfdSMatthias Ringwald *       SEGGER_RTT_PutCharSkip
10007dc86dfdSMatthias Ringwald *
10017dc86dfdSMatthias Ringwald *  Function description
10027dc86dfdSMatthias Ringwald *    Stores a single character/byte in SEGGER RTT buffer.
10037dc86dfdSMatthias Ringwald *
10047dc86dfdSMatthias Ringwald *  Parameters
10057dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
10067dc86dfdSMatthias Ringwald *    c            Byte to be stored.
10077dc86dfdSMatthias Ringwald *
10087dc86dfdSMatthias Ringwald *  Return value
10097dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
10107dc86dfdSMatthias Ringwald *
10117dc86dfdSMatthias Ringwald *  Notes
10127dc86dfdSMatthias Ringwald *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
10137dc86dfdSMatthias Ringwald */
10147dc86dfdSMatthias Ringwald 
10157dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
10167dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
10177dc86dfdSMatthias Ringwald   unsigned              WrOff;
10187dc86dfdSMatthias Ringwald   unsigned              Status;
10197dc86dfdSMatthias Ringwald   //
10207dc86dfdSMatthias Ringwald   // Prepare
10217dc86dfdSMatthias Ringwald   //
10227dc86dfdSMatthias Ringwald   INIT();
10237dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
10247dc86dfdSMatthias Ringwald   //
10257dc86dfdSMatthias Ringwald   // Get "to-host" ring buffer.
10267dc86dfdSMatthias Ringwald   //
10277dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
10287dc86dfdSMatthias Ringwald   //
10297dc86dfdSMatthias Ringwald   // Get write position and handle wrap-around if necessary
10307dc86dfdSMatthias Ringwald   //
10317dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff + 1;
10327dc86dfdSMatthias Ringwald   if (WrOff == pRing->SizeOfBuffer) {
10337dc86dfdSMatthias Ringwald     WrOff = 0;
10347dc86dfdSMatthias Ringwald   }
10357dc86dfdSMatthias Ringwald   //
10367dc86dfdSMatthias Ringwald   // Output byte if free space is available
10377dc86dfdSMatthias Ringwald   //
10387dc86dfdSMatthias Ringwald   if (WrOff != pRing->RdOff) {
10397dc86dfdSMatthias Ringwald     pRing->pBuffer[pRing->WrOff] = c;
10407dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff;
10417dc86dfdSMatthias Ringwald     Status = 1;
10427dc86dfdSMatthias Ringwald   } else {
10437dc86dfdSMatthias Ringwald     Status = 0;
10447dc86dfdSMatthias Ringwald   }
10457dc86dfdSMatthias Ringwald   //
10467dc86dfdSMatthias Ringwald   // Finish up.
10477dc86dfdSMatthias Ringwald   //
10487dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
10497dc86dfdSMatthias Ringwald   //
10507dc86dfdSMatthias Ringwald   return Status;
10517dc86dfdSMatthias Ringwald }
10527dc86dfdSMatthias Ringwald 
10537dc86dfdSMatthias Ringwald  /*********************************************************************
10547dc86dfdSMatthias Ringwald *
10557dc86dfdSMatthias Ringwald *       SEGGER_RTT_PutChar
10567dc86dfdSMatthias Ringwald *
10577dc86dfdSMatthias Ringwald *  Function description
10587dc86dfdSMatthias Ringwald *    Stores a single character/byte in SEGGER RTT buffer.
10597dc86dfdSMatthias Ringwald *
10607dc86dfdSMatthias Ringwald *  Parameters
10617dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
10627dc86dfdSMatthias Ringwald *    c            Byte to be stored.
10637dc86dfdSMatthias Ringwald *
10647dc86dfdSMatthias Ringwald *  Return value
10657dc86dfdSMatthias Ringwald *    Number of bytes which have been stored in the "Up"-buffer.
10667dc86dfdSMatthias Ringwald *
10677dc86dfdSMatthias Ringwald *  Notes
10687dc86dfdSMatthias Ringwald *    (1) Data is stored according to buffer flags.
10697dc86dfdSMatthias Ringwald */
10707dc86dfdSMatthias Ringwald 
10717dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
10727dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
10737dc86dfdSMatthias Ringwald   unsigned              WrOff;
10747dc86dfdSMatthias Ringwald   unsigned              Status;
10757dc86dfdSMatthias Ringwald   //
10767dc86dfdSMatthias Ringwald   // Prepare
10777dc86dfdSMatthias Ringwald   //
10787dc86dfdSMatthias Ringwald   INIT();
10797dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
10807dc86dfdSMatthias Ringwald   //
10817dc86dfdSMatthias Ringwald   // Get "to-host" ring buffer.
10827dc86dfdSMatthias Ringwald   //
10837dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
10847dc86dfdSMatthias Ringwald   //
10857dc86dfdSMatthias Ringwald   // Get write position and handle wrap-around if necessary
10867dc86dfdSMatthias Ringwald   //
10877dc86dfdSMatthias Ringwald   WrOff = pRing->WrOff + 1;
10887dc86dfdSMatthias Ringwald   if (WrOff == pRing->SizeOfBuffer) {
10897dc86dfdSMatthias Ringwald     WrOff = 0;
10907dc86dfdSMatthias Ringwald   }
10917dc86dfdSMatthias Ringwald   //
10927dc86dfdSMatthias Ringwald   // Wait for free space if mode is set to blocking
10937dc86dfdSMatthias Ringwald   //
10947dc86dfdSMatthias Ringwald   if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
10957dc86dfdSMatthias Ringwald     while (WrOff == pRing->RdOff) {
10967dc86dfdSMatthias Ringwald       ;
10977dc86dfdSMatthias Ringwald     }
10987dc86dfdSMatthias Ringwald   }
10997dc86dfdSMatthias Ringwald   //
11007dc86dfdSMatthias Ringwald   // Output byte if free space is available
11017dc86dfdSMatthias Ringwald   //
11027dc86dfdSMatthias Ringwald   if (WrOff != pRing->RdOff) {
11037dc86dfdSMatthias Ringwald     pRing->pBuffer[pRing->WrOff] = c;
11047dc86dfdSMatthias Ringwald     pRing->WrOff = WrOff;
11057dc86dfdSMatthias Ringwald     Status = 1;
11067dc86dfdSMatthias Ringwald   } else {
11077dc86dfdSMatthias Ringwald     Status = 0;
11087dc86dfdSMatthias Ringwald   }
11097dc86dfdSMatthias Ringwald   //
11107dc86dfdSMatthias Ringwald   // Finish up.
11117dc86dfdSMatthias Ringwald   //
11127dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
11137dc86dfdSMatthias Ringwald   //
11147dc86dfdSMatthias Ringwald   return Status;
11157dc86dfdSMatthias Ringwald }
11167dc86dfdSMatthias Ringwald 
11177dc86dfdSMatthias Ringwald /*********************************************************************
11187dc86dfdSMatthias Ringwald *
11197dc86dfdSMatthias Ringwald *       SEGGER_RTT_GetKey
11207dc86dfdSMatthias Ringwald *
11217dc86dfdSMatthias Ringwald *  Function description
11227dc86dfdSMatthias Ringwald *    Reads one character from the SEGGER RTT buffer.
11237dc86dfdSMatthias Ringwald *    Host has previously stored data there.
11247dc86dfdSMatthias Ringwald *
11257dc86dfdSMatthias Ringwald *  Return value
11267dc86dfdSMatthias Ringwald *    <  0 -   No character available (buffer empty).
11277dc86dfdSMatthias Ringwald *    >= 0 -   Character which has been read. (Possible values: 0 - 255)
11287dc86dfdSMatthias Ringwald *
11297dc86dfdSMatthias Ringwald *  Notes
11307dc86dfdSMatthias Ringwald *    (1) This function is only specified for accesses to RTT buffer 0.
11317dc86dfdSMatthias Ringwald */
11327dc86dfdSMatthias Ringwald int SEGGER_RTT_GetKey(void) {
11337dc86dfdSMatthias Ringwald   char c;
11347dc86dfdSMatthias Ringwald   int r;
11357dc86dfdSMatthias Ringwald 
11367dc86dfdSMatthias Ringwald   r = (int)SEGGER_RTT_Read(0u, &c, 1u);
11377dc86dfdSMatthias Ringwald   if (r == 1) {
11387dc86dfdSMatthias Ringwald     r = (int)(unsigned char)c;
11397dc86dfdSMatthias Ringwald   } else {
11407dc86dfdSMatthias Ringwald     r = -1;
11417dc86dfdSMatthias Ringwald   }
11427dc86dfdSMatthias Ringwald   return r;
11437dc86dfdSMatthias Ringwald }
11447dc86dfdSMatthias Ringwald 
11457dc86dfdSMatthias Ringwald /*********************************************************************
11467dc86dfdSMatthias Ringwald *
11477dc86dfdSMatthias Ringwald *       SEGGER_RTT_WaitKey
11487dc86dfdSMatthias Ringwald *
11497dc86dfdSMatthias Ringwald *  Function description
11507dc86dfdSMatthias Ringwald *    Waits until at least one character is avaible in the SEGGER RTT buffer.
11517dc86dfdSMatthias Ringwald *    Once a character is available, it is read and this function returns.
11527dc86dfdSMatthias Ringwald *
11537dc86dfdSMatthias Ringwald *  Return value
11547dc86dfdSMatthias Ringwald *    >=0 -   Character which has been read.
11557dc86dfdSMatthias Ringwald *
11567dc86dfdSMatthias Ringwald *  Notes
11577dc86dfdSMatthias Ringwald *    (1) This function is only specified for accesses to RTT buffer 0
11587dc86dfdSMatthias Ringwald *    (2) This function is blocking if no character is present in RTT buffer
11597dc86dfdSMatthias Ringwald */
11607dc86dfdSMatthias Ringwald int SEGGER_RTT_WaitKey(void) {
11617dc86dfdSMatthias Ringwald   int r;
11627dc86dfdSMatthias Ringwald 
11637dc86dfdSMatthias Ringwald   do {
11647dc86dfdSMatthias Ringwald     r = SEGGER_RTT_GetKey();
11657dc86dfdSMatthias Ringwald   } while (r < 0);
11667dc86dfdSMatthias Ringwald   return r;
11677dc86dfdSMatthias Ringwald }
11687dc86dfdSMatthias Ringwald 
11697dc86dfdSMatthias Ringwald /*********************************************************************
11707dc86dfdSMatthias Ringwald *
11717dc86dfdSMatthias Ringwald *       SEGGER_RTT_HasKey
11727dc86dfdSMatthias Ringwald *
11737dc86dfdSMatthias Ringwald *  Function description
11747dc86dfdSMatthias Ringwald *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
11757dc86dfdSMatthias Ringwald *
11767dc86dfdSMatthias Ringwald *  Return value
11777dc86dfdSMatthias Ringwald *    == 0 -     No characters are available to read.
11787dc86dfdSMatthias Ringwald *    == 1 -     At least one character is available.
11797dc86dfdSMatthias Ringwald *
11807dc86dfdSMatthias Ringwald *  Notes
11817dc86dfdSMatthias Ringwald *    (1) This function is only specified for accesses to RTT buffer 0
11827dc86dfdSMatthias Ringwald */
11837dc86dfdSMatthias Ringwald int SEGGER_RTT_HasKey(void) {
11847dc86dfdSMatthias Ringwald   unsigned RdOff;
11857dc86dfdSMatthias Ringwald   int r;
11867dc86dfdSMatthias Ringwald 
11877dc86dfdSMatthias Ringwald   INIT();
11887dc86dfdSMatthias Ringwald   RdOff = _SEGGER_RTT.aDown[0].RdOff;
11897dc86dfdSMatthias Ringwald   if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
11907dc86dfdSMatthias Ringwald     r = 1;
11917dc86dfdSMatthias Ringwald   } else {
11927dc86dfdSMatthias Ringwald     r = 0;
11937dc86dfdSMatthias Ringwald   }
11947dc86dfdSMatthias Ringwald   return r;
11957dc86dfdSMatthias Ringwald }
11967dc86dfdSMatthias Ringwald 
11977dc86dfdSMatthias Ringwald /*********************************************************************
11987dc86dfdSMatthias Ringwald *
11997dc86dfdSMatthias Ringwald *       SEGGER_RTT_HasData
12007dc86dfdSMatthias Ringwald *
12017dc86dfdSMatthias Ringwald *  Function description
12027dc86dfdSMatthias Ringwald *    Check if there is data from the host in the given buffer.
12037dc86dfdSMatthias Ringwald *
12047dc86dfdSMatthias Ringwald *  Return value:
12057dc86dfdSMatthias Ringwald *  ==0:  No data
12067dc86dfdSMatthias Ringwald *  !=0:  Data in buffer
12077dc86dfdSMatthias Ringwald *
12087dc86dfdSMatthias Ringwald */
12097dc86dfdSMatthias Ringwald unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
12107dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_DOWN* pRing;
12117dc86dfdSMatthias Ringwald   unsigned                v;
12127dc86dfdSMatthias Ringwald 
12137dc86dfdSMatthias Ringwald   pRing = &_SEGGER_RTT.aDown[BufferIndex];
12147dc86dfdSMatthias Ringwald   v = pRing->WrOff;
12157dc86dfdSMatthias Ringwald   return v - pRing->RdOff;
12167dc86dfdSMatthias Ringwald }
12177dc86dfdSMatthias Ringwald 
12187dc86dfdSMatthias Ringwald /*********************************************************************
12197dc86dfdSMatthias Ringwald *
1220779af47bSMatthias Ringwald *       SEGGER_RTT_HasDataUp
1221779af47bSMatthias Ringwald *
1222779af47bSMatthias Ringwald *  Function description
1223779af47bSMatthias Ringwald *    Check if there is data remaining to be sent in the given buffer.
1224779af47bSMatthias Ringwald *
1225779af47bSMatthias Ringwald *  Return value:
1226779af47bSMatthias Ringwald *  ==0:  No data
1227779af47bSMatthias Ringwald *  !=0:  Data in buffer
1228779af47bSMatthias Ringwald *
1229779af47bSMatthias Ringwald */
1230779af47bSMatthias Ringwald unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
1231779af47bSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
1232779af47bSMatthias Ringwald   unsigned                v;
1233779af47bSMatthias Ringwald 
1234779af47bSMatthias Ringwald   pRing = &_SEGGER_RTT.aUp[BufferIndex];
1235779af47bSMatthias Ringwald   v = pRing->RdOff;
1236779af47bSMatthias Ringwald   return pRing->WrOff - v;
1237779af47bSMatthias Ringwald }
1238779af47bSMatthias Ringwald 
1239779af47bSMatthias Ringwald /*********************************************************************
1240779af47bSMatthias Ringwald *
12417dc86dfdSMatthias Ringwald *       SEGGER_RTT_AllocDownBuffer
12427dc86dfdSMatthias Ringwald *
12437dc86dfdSMatthias Ringwald *  Function description
12447dc86dfdSMatthias Ringwald *    Run-time configuration of the next down-buffer (H->T).
12457dc86dfdSMatthias Ringwald *    The next buffer, which is not used yet is configured.
12467dc86dfdSMatthias Ringwald *    This includes: Buffer address, size, name, flags, ...
12477dc86dfdSMatthias Ringwald *
12487dc86dfdSMatthias Ringwald *  Parameters
12497dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
12507dc86dfdSMatthias Ringwald *    pBuffer      Pointer to a buffer to be used.
12517dc86dfdSMatthias Ringwald *    BufferSize   Size of the buffer.
12527dc86dfdSMatthias Ringwald *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
12537dc86dfdSMatthias Ringwald *
12547dc86dfdSMatthias Ringwald *  Return value
12557dc86dfdSMatthias Ringwald *    >= 0 - O.K. Buffer Index
12567dc86dfdSMatthias Ringwald *     < 0 - Error
12577dc86dfdSMatthias Ringwald */
12587dc86dfdSMatthias Ringwald int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
12597dc86dfdSMatthias Ringwald   int BufferIndex;
12607dc86dfdSMatthias Ringwald 
12617dc86dfdSMatthias Ringwald   INIT();
12627dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
12637dc86dfdSMatthias Ringwald   BufferIndex = 0;
12647dc86dfdSMatthias Ringwald   do {
12657dc86dfdSMatthias Ringwald     if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
12667dc86dfdSMatthias Ringwald       break;
12677dc86dfdSMatthias Ringwald     }
12687dc86dfdSMatthias Ringwald     BufferIndex++;
12697dc86dfdSMatthias Ringwald   } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
12707dc86dfdSMatthias Ringwald   if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
12717dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
12727dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
12737dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
12747dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
12757dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
12767dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
12777dc86dfdSMatthias Ringwald   } else {
12787dc86dfdSMatthias Ringwald     BufferIndex = -1;
12797dc86dfdSMatthias Ringwald   }
12807dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
12817dc86dfdSMatthias Ringwald   return BufferIndex;
12827dc86dfdSMatthias Ringwald }
12837dc86dfdSMatthias Ringwald 
12847dc86dfdSMatthias Ringwald /*********************************************************************
12857dc86dfdSMatthias Ringwald *
12867dc86dfdSMatthias Ringwald *       SEGGER_RTT_AllocUpBuffer
12877dc86dfdSMatthias Ringwald *
12887dc86dfdSMatthias Ringwald *  Function description
12897dc86dfdSMatthias Ringwald *    Run-time configuration of the next up-buffer (T->H).
12907dc86dfdSMatthias Ringwald *    The next buffer, which is not used yet is configured.
12917dc86dfdSMatthias Ringwald *    This includes: Buffer address, size, name, flags, ...
12927dc86dfdSMatthias Ringwald *
12937dc86dfdSMatthias Ringwald *  Parameters
12947dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
12957dc86dfdSMatthias Ringwald *    pBuffer      Pointer to a buffer to be used.
12967dc86dfdSMatthias Ringwald *    BufferSize   Size of the buffer.
12977dc86dfdSMatthias Ringwald *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
12987dc86dfdSMatthias Ringwald *
12997dc86dfdSMatthias Ringwald *  Return value
13007dc86dfdSMatthias Ringwald *    >= 0 - O.K. Buffer Index
13017dc86dfdSMatthias Ringwald *     < 0 - Error
13027dc86dfdSMatthias Ringwald */
13037dc86dfdSMatthias Ringwald int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
13047dc86dfdSMatthias Ringwald   int BufferIndex;
13057dc86dfdSMatthias Ringwald 
13067dc86dfdSMatthias Ringwald   INIT();
13077dc86dfdSMatthias Ringwald   SEGGER_RTT_LOCK();
13087dc86dfdSMatthias Ringwald   BufferIndex = 0;
13097dc86dfdSMatthias Ringwald   do {
13107dc86dfdSMatthias Ringwald     if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
13117dc86dfdSMatthias Ringwald       break;
13127dc86dfdSMatthias Ringwald     }
13137dc86dfdSMatthias Ringwald     BufferIndex++;
13147dc86dfdSMatthias Ringwald   } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
13157dc86dfdSMatthias Ringwald   if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
13167dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
13177dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
13187dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
13197dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
13207dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
13217dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
13227dc86dfdSMatthias Ringwald   } else {
13237dc86dfdSMatthias Ringwald     BufferIndex = -1;
13247dc86dfdSMatthias Ringwald   }
13257dc86dfdSMatthias Ringwald   SEGGER_RTT_UNLOCK();
13267dc86dfdSMatthias Ringwald   return BufferIndex;
13277dc86dfdSMatthias Ringwald }
13287dc86dfdSMatthias Ringwald 
13297dc86dfdSMatthias Ringwald /*********************************************************************
13307dc86dfdSMatthias Ringwald *
13317dc86dfdSMatthias Ringwald *       SEGGER_RTT_ConfigUpBuffer
13327dc86dfdSMatthias Ringwald *
13337dc86dfdSMatthias Ringwald *  Function description
13347dc86dfdSMatthias Ringwald *    Run-time configuration of a specific up-buffer (T->H).
13357dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
13367dc86dfdSMatthias Ringwald *    This includes: Buffer address, size, name, flags, ...
13377dc86dfdSMatthias Ringwald *
13387dc86dfdSMatthias Ringwald *  Parameters
13397dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer to configure.
13407dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
13417dc86dfdSMatthias Ringwald *    pBuffer      Pointer to a buffer to be used.
13427dc86dfdSMatthias Ringwald *    BufferSize   Size of the buffer.
13437dc86dfdSMatthias Ringwald *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
13447dc86dfdSMatthias Ringwald *
13457dc86dfdSMatthias Ringwald *  Return value
13467dc86dfdSMatthias Ringwald *    >= 0 - O.K.
13477dc86dfdSMatthias Ringwald *     < 0 - Error
13487dc86dfdSMatthias Ringwald *
13497dc86dfdSMatthias Ringwald *  Additional information
13507dc86dfdSMatthias Ringwald *    Buffer 0 is configured on compile-time.
13517dc86dfdSMatthias Ringwald *    May only be called once per buffer.
13527dc86dfdSMatthias Ringwald *    Buffer name and flags can be reconfigured using the appropriate functions.
13537dc86dfdSMatthias Ringwald */
13547dc86dfdSMatthias Ringwald int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
13557dc86dfdSMatthias Ringwald   int r;
13567dc86dfdSMatthias Ringwald 
13577dc86dfdSMatthias Ringwald   INIT();
13587dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
13597dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
13607dc86dfdSMatthias Ringwald     if (BufferIndex > 0u) {
13617dc86dfdSMatthias Ringwald       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
13627dc86dfdSMatthias Ringwald       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
13637dc86dfdSMatthias Ringwald       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
13647dc86dfdSMatthias Ringwald       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
13657dc86dfdSMatthias Ringwald       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
13667dc86dfdSMatthias Ringwald     }
13677dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
13687dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
13697dc86dfdSMatthias Ringwald     r =  0;
13707dc86dfdSMatthias Ringwald   } else {
13717dc86dfdSMatthias Ringwald     r = -1;
13727dc86dfdSMatthias Ringwald   }
13737dc86dfdSMatthias Ringwald   return r;
13747dc86dfdSMatthias Ringwald }
13757dc86dfdSMatthias Ringwald 
13767dc86dfdSMatthias Ringwald /*********************************************************************
13777dc86dfdSMatthias Ringwald *
13787dc86dfdSMatthias Ringwald *       SEGGER_RTT_ConfigDownBuffer
13797dc86dfdSMatthias Ringwald *
13807dc86dfdSMatthias Ringwald *  Function description
13817dc86dfdSMatthias Ringwald *    Run-time configuration of a specific down-buffer (H->T).
13827dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
13837dc86dfdSMatthias Ringwald *    This includes: Buffer address, size, name, flags, ...
13847dc86dfdSMatthias Ringwald *
13857dc86dfdSMatthias Ringwald *  Parameters
13867dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer to configure.
13877dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
13887dc86dfdSMatthias Ringwald *    pBuffer      Pointer to a buffer to be used.
13897dc86dfdSMatthias Ringwald *    BufferSize   Size of the buffer.
13907dc86dfdSMatthias Ringwald *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
13917dc86dfdSMatthias Ringwald *
13927dc86dfdSMatthias Ringwald *  Return value
13937dc86dfdSMatthias Ringwald *    >= 0  O.K.
13947dc86dfdSMatthias Ringwald *     < 0  Error
13957dc86dfdSMatthias Ringwald *
13967dc86dfdSMatthias Ringwald *  Additional information
13977dc86dfdSMatthias Ringwald *    Buffer 0 is configured on compile-time.
13987dc86dfdSMatthias Ringwald *    May only be called once per buffer.
13997dc86dfdSMatthias Ringwald *    Buffer name and flags can be reconfigured using the appropriate functions.
14007dc86dfdSMatthias Ringwald */
14017dc86dfdSMatthias Ringwald int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
14027dc86dfdSMatthias Ringwald   int r;
14037dc86dfdSMatthias Ringwald 
14047dc86dfdSMatthias Ringwald   INIT();
14057dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
14067dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
14077dc86dfdSMatthias Ringwald     if (BufferIndex > 0u) {
14087dc86dfdSMatthias Ringwald       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
14097dc86dfdSMatthias Ringwald       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
14107dc86dfdSMatthias Ringwald       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
14117dc86dfdSMatthias Ringwald       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
14127dc86dfdSMatthias Ringwald       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
14137dc86dfdSMatthias Ringwald     }
14147dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
14157dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
14167dc86dfdSMatthias Ringwald     r =  0;
14177dc86dfdSMatthias Ringwald   } else {
14187dc86dfdSMatthias Ringwald     r = -1;
14197dc86dfdSMatthias Ringwald   }
14207dc86dfdSMatthias Ringwald   return r;
14217dc86dfdSMatthias Ringwald }
14227dc86dfdSMatthias Ringwald 
14237dc86dfdSMatthias Ringwald /*********************************************************************
14247dc86dfdSMatthias Ringwald *
14257dc86dfdSMatthias Ringwald *       SEGGER_RTT_SetNameUpBuffer
14267dc86dfdSMatthias Ringwald *
14277dc86dfdSMatthias Ringwald *  Function description
14287dc86dfdSMatthias Ringwald *    Run-time configuration of a specific up-buffer name (T->H).
14297dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
14307dc86dfdSMatthias Ringwald *
14317dc86dfdSMatthias Ringwald *  Parameters
14327dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer to renamed.
14337dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
14347dc86dfdSMatthias Ringwald *
14357dc86dfdSMatthias Ringwald *  Return value
14367dc86dfdSMatthias Ringwald *    >= 0  O.K.
14377dc86dfdSMatthias Ringwald *     < 0  Error
14387dc86dfdSMatthias Ringwald */
14397dc86dfdSMatthias Ringwald int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
14407dc86dfdSMatthias Ringwald   int r;
14417dc86dfdSMatthias Ringwald 
14427dc86dfdSMatthias Ringwald   INIT();
14437dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
14447dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
14457dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].sName = sName;
14467dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
14477dc86dfdSMatthias Ringwald     r =  0;
14487dc86dfdSMatthias Ringwald   } else {
14497dc86dfdSMatthias Ringwald     r = -1;
14507dc86dfdSMatthias Ringwald   }
14517dc86dfdSMatthias Ringwald   return r;
14527dc86dfdSMatthias Ringwald }
14537dc86dfdSMatthias Ringwald 
14547dc86dfdSMatthias Ringwald /*********************************************************************
14557dc86dfdSMatthias Ringwald *
14567dc86dfdSMatthias Ringwald *       SEGGER_RTT_SetNameDownBuffer
14577dc86dfdSMatthias Ringwald *
14587dc86dfdSMatthias Ringwald *  Function description
14597dc86dfdSMatthias Ringwald *    Run-time configuration of a specific Down-buffer name (T->H).
14607dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
14617dc86dfdSMatthias Ringwald *
14627dc86dfdSMatthias Ringwald *  Parameters
14637dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer to renamed.
14647dc86dfdSMatthias Ringwald *    sName        Pointer to a constant name string.
14657dc86dfdSMatthias Ringwald *
14667dc86dfdSMatthias Ringwald *  Return value
14677dc86dfdSMatthias Ringwald *    >= 0  O.K.
14687dc86dfdSMatthias Ringwald *     < 0  Error
14697dc86dfdSMatthias Ringwald */
14707dc86dfdSMatthias Ringwald int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
14717dc86dfdSMatthias Ringwald   int r;
14727dc86dfdSMatthias Ringwald 
14737dc86dfdSMatthias Ringwald   INIT();
14747dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
14757dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
14767dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].sName = sName;
14777dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
14787dc86dfdSMatthias Ringwald     r =  0;
14797dc86dfdSMatthias Ringwald   } else {
14807dc86dfdSMatthias Ringwald     r = -1;
14817dc86dfdSMatthias Ringwald   }
14827dc86dfdSMatthias Ringwald   return r;
14837dc86dfdSMatthias Ringwald }
14847dc86dfdSMatthias Ringwald 
14857dc86dfdSMatthias Ringwald /*********************************************************************
14867dc86dfdSMatthias Ringwald *
14877dc86dfdSMatthias Ringwald *       SEGGER_RTT_SetFlagsUpBuffer
14887dc86dfdSMatthias Ringwald *
14897dc86dfdSMatthias Ringwald *  Function description
14907dc86dfdSMatthias Ringwald *    Run-time configuration of specific up-buffer flags (T->H).
14917dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
14927dc86dfdSMatthias Ringwald *
14937dc86dfdSMatthias Ringwald *  Parameters
14947dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer.
14957dc86dfdSMatthias Ringwald *    Flags        Flags to set for the buffer.
14967dc86dfdSMatthias Ringwald *
14977dc86dfdSMatthias Ringwald *  Return value
14987dc86dfdSMatthias Ringwald *    >= 0  O.K.
14997dc86dfdSMatthias Ringwald *     < 0  Error
15007dc86dfdSMatthias Ringwald */
15017dc86dfdSMatthias Ringwald int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
15027dc86dfdSMatthias Ringwald   int r;
15037dc86dfdSMatthias Ringwald 
15047dc86dfdSMatthias Ringwald   INIT();
15057dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
15067dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
15077dc86dfdSMatthias Ringwald     _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
15087dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
15097dc86dfdSMatthias Ringwald     r =  0;
15107dc86dfdSMatthias Ringwald   } else {
15117dc86dfdSMatthias Ringwald     r = -1;
15127dc86dfdSMatthias Ringwald   }
15137dc86dfdSMatthias Ringwald   return r;
15147dc86dfdSMatthias Ringwald }
15157dc86dfdSMatthias Ringwald 
15167dc86dfdSMatthias Ringwald /*********************************************************************
15177dc86dfdSMatthias Ringwald *
15187dc86dfdSMatthias Ringwald *       SEGGER_RTT_SetFlagsDownBuffer
15197dc86dfdSMatthias Ringwald *
15207dc86dfdSMatthias Ringwald *  Function description
15217dc86dfdSMatthias Ringwald *    Run-time configuration of specific Down-buffer flags (T->H).
15227dc86dfdSMatthias Ringwald *    Buffer to be configured is specified by index.
15237dc86dfdSMatthias Ringwald *
15247dc86dfdSMatthias Ringwald *  Parameters
15257dc86dfdSMatthias Ringwald *    BufferIndex  Index of the buffer to renamed.
15267dc86dfdSMatthias Ringwald *    Flags        Flags to set for the buffer.
15277dc86dfdSMatthias Ringwald *
15287dc86dfdSMatthias Ringwald *  Return value
15297dc86dfdSMatthias Ringwald *    >= 0  O.K.
15307dc86dfdSMatthias Ringwald *     < 0  Error
15317dc86dfdSMatthias Ringwald */
15327dc86dfdSMatthias Ringwald int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
15337dc86dfdSMatthias Ringwald   int r;
15347dc86dfdSMatthias Ringwald 
15357dc86dfdSMatthias Ringwald   INIT();
15367dc86dfdSMatthias Ringwald   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
15377dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
15387dc86dfdSMatthias Ringwald     _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
15397dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
15407dc86dfdSMatthias Ringwald     r =  0;
15417dc86dfdSMatthias Ringwald   } else {
15427dc86dfdSMatthias Ringwald     r = -1;
15437dc86dfdSMatthias Ringwald   }
15447dc86dfdSMatthias Ringwald   return r;
15457dc86dfdSMatthias Ringwald }
15467dc86dfdSMatthias Ringwald 
15477dc86dfdSMatthias Ringwald /*********************************************************************
15487dc86dfdSMatthias Ringwald *
15497dc86dfdSMatthias Ringwald *       SEGGER_RTT_Init
15507dc86dfdSMatthias Ringwald *
15517dc86dfdSMatthias Ringwald *  Function description
15527dc86dfdSMatthias Ringwald *    Initializes the RTT Control Block.
15537dc86dfdSMatthias Ringwald *    Should be used in RAM targets, at start of the application.
15547dc86dfdSMatthias Ringwald *
15557dc86dfdSMatthias Ringwald */
15567dc86dfdSMatthias Ringwald void SEGGER_RTT_Init (void) {
15577dc86dfdSMatthias Ringwald   _DoInit();
15587dc86dfdSMatthias Ringwald }
15597dc86dfdSMatthias Ringwald 
15607dc86dfdSMatthias Ringwald /*********************************************************************
15617dc86dfdSMatthias Ringwald *
15627dc86dfdSMatthias Ringwald *       SEGGER_RTT_SetTerminal
15637dc86dfdSMatthias Ringwald *
15647dc86dfdSMatthias Ringwald *  Function description
15657dc86dfdSMatthias Ringwald *    Sets the terminal to be used for output on channel 0.
15667dc86dfdSMatthias Ringwald *
15677dc86dfdSMatthias Ringwald *  Parameters
15687dc86dfdSMatthias Ringwald *    TerminalId  Index of the terminal.
15697dc86dfdSMatthias Ringwald *
15707dc86dfdSMatthias Ringwald *  Return value
15717dc86dfdSMatthias Ringwald *    >= 0  O.K.
15727dc86dfdSMatthias Ringwald *     < 0  Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id)
15737dc86dfdSMatthias Ringwald */
1574779af47bSMatthias Ringwald int SEGGER_RTT_SetTerminal (unsigned char TerminalId) {
1575779af47bSMatthias Ringwald   unsigned char         ac[2];
15767dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
15777dc86dfdSMatthias Ringwald   unsigned Avail;
15787dc86dfdSMatthias Ringwald   int r;
15797dc86dfdSMatthias Ringwald   //
15807dc86dfdSMatthias Ringwald   INIT();
15817dc86dfdSMatthias Ringwald   //
15827dc86dfdSMatthias Ringwald   r = 0;
1583779af47bSMatthias Ringwald   ac[0] = 0xFFu;
1584779af47bSMatthias Ringwald   if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels
1585779af47bSMatthias Ringwald     ac[1] = _aTerminalId[TerminalId];
15867dc86dfdSMatthias Ringwald     pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
15877dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();    // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing
15887dc86dfdSMatthias Ringwald     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
15897dc86dfdSMatthias Ringwald       _ActiveTerminal = TerminalId;
1590779af47bSMatthias Ringwald       _WriteBlocking(pRing, (const char*)ac, 2u);
15917dc86dfdSMatthias Ringwald     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
15927dc86dfdSMatthias Ringwald       Avail = _GetAvailWriteSpace(pRing);
15937dc86dfdSMatthias Ringwald       if (Avail >= 2) {
15947dc86dfdSMatthias Ringwald         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
1595779af47bSMatthias Ringwald         _WriteNoCheck(pRing, (const char*)ac, 2u);
15967dc86dfdSMatthias Ringwald       } else {
15977dc86dfdSMatthias Ringwald         r = -1;
15987dc86dfdSMatthias Ringwald       }
15997dc86dfdSMatthias Ringwald     }
16007dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
16017dc86dfdSMatthias Ringwald   } else {
16027dc86dfdSMatthias Ringwald     r = -1;
16037dc86dfdSMatthias Ringwald   }
16047dc86dfdSMatthias Ringwald   return r;
16057dc86dfdSMatthias Ringwald }
16067dc86dfdSMatthias Ringwald 
16077dc86dfdSMatthias Ringwald /*********************************************************************
16087dc86dfdSMatthias Ringwald *
16097dc86dfdSMatthias Ringwald *       SEGGER_RTT_TerminalOut
16107dc86dfdSMatthias Ringwald *
16117dc86dfdSMatthias Ringwald *  Function description
16127dc86dfdSMatthias Ringwald *    Writes a string to the given terminal
16137dc86dfdSMatthias Ringwald *     without changing the terminal for channel 0.
16147dc86dfdSMatthias Ringwald *
16157dc86dfdSMatthias Ringwald *  Parameters
16167dc86dfdSMatthias Ringwald *    TerminalId   Index of the terminal.
16177dc86dfdSMatthias Ringwald *    s            String to be printed on the terminal.
16187dc86dfdSMatthias Ringwald *
16197dc86dfdSMatthias Ringwald *  Return value
16207dc86dfdSMatthias Ringwald *    >= 0 - Number of bytes written.
16217dc86dfdSMatthias Ringwald *     < 0 - Error.
16227dc86dfdSMatthias Ringwald *
16237dc86dfdSMatthias Ringwald */
1624779af47bSMatthias Ringwald int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) {
16257dc86dfdSMatthias Ringwald   int                   Status;
16267dc86dfdSMatthias Ringwald   unsigned              FragLen;
16277dc86dfdSMatthias Ringwald   unsigned              Avail;
16287dc86dfdSMatthias Ringwald   SEGGER_RTT_BUFFER_UP* pRing;
16297dc86dfdSMatthias Ringwald   //
16307dc86dfdSMatthias Ringwald   INIT();
16317dc86dfdSMatthias Ringwald   //
16327dc86dfdSMatthias Ringwald   // Validate terminal ID.
16337dc86dfdSMatthias Ringwald   //
16347dc86dfdSMatthias Ringwald   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
16357dc86dfdSMatthias Ringwald     //
16367dc86dfdSMatthias Ringwald     // Get "to-host" ring buffer.
16377dc86dfdSMatthias Ringwald     //
16387dc86dfdSMatthias Ringwald     pRing = &_SEGGER_RTT.aUp[0];
16397dc86dfdSMatthias Ringwald     //
16407dc86dfdSMatthias Ringwald     // Need to be able to change terminal, write data, change back.
16417dc86dfdSMatthias Ringwald     // Compute the fixed and variable sizes.
16427dc86dfdSMatthias Ringwald     //
16437dc86dfdSMatthias Ringwald     FragLen = STRLEN(s);
16447dc86dfdSMatthias Ringwald     //
16457dc86dfdSMatthias Ringwald     // How we output depends upon the mode...
16467dc86dfdSMatthias Ringwald     //
16477dc86dfdSMatthias Ringwald     SEGGER_RTT_LOCK();
16487dc86dfdSMatthias Ringwald     Avail = _GetAvailWriteSpace(pRing);
16497dc86dfdSMatthias Ringwald     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
16507dc86dfdSMatthias Ringwald     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
16517dc86dfdSMatthias Ringwald       //
16527dc86dfdSMatthias Ringwald       // If we are in skip mode and there is no space for the whole
16537dc86dfdSMatthias Ringwald       // of this output, don't bother switching terminals at all.
16547dc86dfdSMatthias Ringwald       //
16557dc86dfdSMatthias Ringwald       if (Avail < (FragLen + 4u)) {
16567dc86dfdSMatthias Ringwald         Status = 0;
16577dc86dfdSMatthias Ringwald       } else {
16587dc86dfdSMatthias Ringwald         _PostTerminalSwitch(pRing, TerminalId);
16597dc86dfdSMatthias Ringwald         Status = (int)_WriteBlocking(pRing, s, FragLen);
16607dc86dfdSMatthias Ringwald         _PostTerminalSwitch(pRing, _ActiveTerminal);
16617dc86dfdSMatthias Ringwald       }
16627dc86dfdSMatthias Ringwald       break;
16637dc86dfdSMatthias Ringwald     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
16647dc86dfdSMatthias Ringwald       //
16657dc86dfdSMatthias Ringwald       // If we are in trim mode and there is not enough space for everything,
16667dc86dfdSMatthias Ringwald       // trim the output but always include the terminal switch.  If no room
16677dc86dfdSMatthias Ringwald       // for terminal switch, skip that totally.
16687dc86dfdSMatthias Ringwald       //
16697dc86dfdSMatthias Ringwald       if (Avail < 4u) {
16707dc86dfdSMatthias Ringwald         Status = -1;
16717dc86dfdSMatthias Ringwald       } else {
16727dc86dfdSMatthias Ringwald         _PostTerminalSwitch(pRing, TerminalId);
16737dc86dfdSMatthias Ringwald         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
16747dc86dfdSMatthias Ringwald         _PostTerminalSwitch(pRing, _ActiveTerminal);
16757dc86dfdSMatthias Ringwald       }
16767dc86dfdSMatthias Ringwald       break;
16777dc86dfdSMatthias Ringwald     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
16787dc86dfdSMatthias Ringwald       //
16797dc86dfdSMatthias Ringwald       // If we are in blocking mode, output everything.
16807dc86dfdSMatthias Ringwald       //
16817dc86dfdSMatthias Ringwald       _PostTerminalSwitch(pRing, TerminalId);
16827dc86dfdSMatthias Ringwald       Status = (int)_WriteBlocking(pRing, s, FragLen);
16837dc86dfdSMatthias Ringwald       _PostTerminalSwitch(pRing, _ActiveTerminal);
16847dc86dfdSMatthias Ringwald       break;
16857dc86dfdSMatthias Ringwald     default:
16867dc86dfdSMatthias Ringwald       Status = -1;
16877dc86dfdSMatthias Ringwald       break;
16887dc86dfdSMatthias Ringwald     }
16897dc86dfdSMatthias Ringwald     //
16907dc86dfdSMatthias Ringwald     // Finish up.
16917dc86dfdSMatthias Ringwald     //
16927dc86dfdSMatthias Ringwald     SEGGER_RTT_UNLOCK();
16937dc86dfdSMatthias Ringwald   } else {
16947dc86dfdSMatthias Ringwald     Status = -1;
16957dc86dfdSMatthias Ringwald   }
16967dc86dfdSMatthias Ringwald   return Status;
16977dc86dfdSMatthias Ringwald }
16987dc86dfdSMatthias Ringwald 
1699*a20be900SMatthias Ringwald /*********************************************************************
1700*a20be900SMatthias Ringwald *
1701*a20be900SMatthias Ringwald *       SEGGER_RTT_GetAvailWriteSpace
1702*a20be900SMatthias Ringwald *    Returns the number of bytes that can be written to the ring
1703*a20be900SMatthias Ringwald *    buffer without blocking.
1704*a20be900SMatthias Ringwald *
1705*a20be900SMatthias Ringwald *  Parameters
1706*a20be900SMatthias Ringwald *    BufferIndex  Index of the buffer.
1707*a20be900SMatthias Ringwald *
1708*a20be900SMatthias Ringwald *  Return value
1709*a20be900SMatthias Ringwald *    Number of bytes that are free in the buffer.
1710*a20be900SMatthias Ringwald */
1711*a20be900SMatthias Ringwald 
1712*a20be900SMatthias Ringwald unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){
1713*a20be900SMatthias Ringwald   return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]);
1714*a20be900SMatthias Ringwald }
1715*a20be900SMatthias Ringwald 
17167dc86dfdSMatthias Ringwald 
17177dc86dfdSMatthias Ringwald /*************************** End of file ****************************/
1718