1 /*********************************************************************
2 *                    SEGGER Microcontroller GmbH                     *
3 *                        The Embedded Experts                        *
4 **********************************************************************
5 *                                                                    *
6 *            (c) 1995 - 2021 SEGGER Microcontroller GmbH             *
7 *                                                                    *
8 *       www.segger.com     Support: support@segger.com               *
9 *                                                                    *
10 **********************************************************************
11 *                                                                    *
12 *       SEGGER RTT * Real Time Transfer for embedded targets         *
13 *                                                                    *
14 **********************************************************************
15 *                                                                    *
16 * All rights reserved.                                               *
17 *                                                                    *
18 * SEGGER strongly recommends to not make any changes                 *
19 * to or modify the source code of this software in order to stay     *
20 * compatible with the RTT protocol and J-Link.                       *
21 *                                                                    *
22 * Redistribution and use in source and binary forms, with or         *
23 * without modification, are permitted provided that the following    *
24 * condition is met:                                                  *
25 *                                                                    *
26 * o Redistributions of source code must retain the above copyright   *
27 *   notice, this condition and the following disclaimer.             *
28 *                                                                    *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
33 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
34 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
40 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
41 * DAMAGE.                                                            *
42 *                                                                    *
43 **********************************************************************
44 *                                                                    *
45 *       RTT version: 7.88c                                           *
46 *                                                                    *
47 **********************************************************************
48 
49 ---------------------------END-OF-HEADER------------------------------
50 File    : SEGGER_RTT.c
51 Purpose : Implementation of SEGGER real-time transfer (RTT) which
52           allows real-time communication on targets which support
53           debugger memory accesses while the CPU is running.
54 Revision: $Rev: 29668 $
55 
56 Additional information:
57           Type "int" is assumed to be 32-bits in size
58           H->T    Host to target communication
59           T->H    Target to host communication
60 
61           RTT channel 0 is always present and reserved for Terminal usage.
62           Name is fixed to "Terminal"
63 
64           Effective buffer size: SizeOfBuffer - 1
65 
66           WrOff == RdOff:       Buffer is empty
67           WrOff == (RdOff - 1): Buffer is full
68           WrOff >  RdOff:       Free space includes wrap-around
69           WrOff <  RdOff:       Used space includes wrap-around
70           (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):
71                                 Buffer full and wrap-around after next byte
72 
73 
74 ----------------------------------------------------------------------
75 */
76 
77 #include "SEGGER_RTT.h"
78 
79 #include <string.h>                 // for memcpy
80 
81 #ifdef __GNUC__
82 #pragma GCC diagnostic ignored "-Wcast-qual"
83 #pragma GCC diagnostic ignored "-Wcast-align"
84 #endif
85 
86 /*********************************************************************
87 *
88 *       Configuration, default values
89 *
90 **********************************************************************
91 */
92 
93 #if SEGGER_RTT_CPU_CACHE_LINE_SIZE
94   #ifdef SEGGER_RTT_CB_ALIGN
95     #error "Custom SEGGER_RTT_CB_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
96   #endif
97   #ifdef SEGGER_RTT_BUFFER_ALIGN
98     #error "Custom SEGGER_RTT_BUFFER_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
99   #endif
100   #ifdef SEGGER_RTT_PUT_CB_SECTION
101     #error "Custom SEGGER_RTT_PUT_CB_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
102   #endif
103   #ifdef SEGGER_RTT_PUT_BUFFER_SECTION
104     #error "Custom SEGGER_RTT_PUT_BUFFER_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
105   #endif
106   #ifdef SEGGER_RTT_BUFFER_ALIGNMENT
107     #error "Custom SEGGER_RTT_BUFFER_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
108   #endif
109   #ifdef SEGGER_RTT_ALIGNMENT
110     #error "Custom SEGGER_RTT_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
111   #endif
112 #endif
113 
114 #ifndef   BUFFER_SIZE_UP
115   #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
116 #endif
117 
118 #ifndef   BUFFER_SIZE_DOWN
119   #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
120 #endif
121 
122 #ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
123   #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
124 #endif
125 
126 #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
127   #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
128 #endif
129 
130 #ifndef SEGGER_RTT_BUFFER_SECTION
131   #if defined(SEGGER_RTT_SECTION)
132     #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
133   #endif
134 #endif
135 
136 #ifndef   SEGGER_RTT_ALIGNMENT
137   #define SEGGER_RTT_ALIGNMENT                            SEGGER_RTT_CPU_CACHE_LINE_SIZE
138 #endif
139 
140 #ifndef   SEGGER_RTT_BUFFER_ALIGNMENT
141   #define SEGGER_RTT_BUFFER_ALIGNMENT                     SEGGER_RTT_CPU_CACHE_LINE_SIZE
142 #endif
143 
144 #ifndef   SEGGER_RTT_MODE_DEFAULT
145   #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
146 #endif
147 
148 #ifndef   SEGGER_RTT_LOCK
149   #define SEGGER_RTT_LOCK()
150 #endif
151 
152 #ifndef   SEGGER_RTT_UNLOCK
153   #define SEGGER_RTT_UNLOCK()
154 #endif
155 
156 #ifndef   STRLEN
157   #define STRLEN(a)                                       strlen((a))
158 #endif
159 
160 #ifndef   STRCPY
161   #define STRCPY(pDest, pSrc)                             strcpy((pDest), (pSrc))
162 #endif
163 
164 #ifndef   SEGGER_RTT_MEMCPY_USE_BYTELOOP
165   #define SEGGER_RTT_MEMCPY_USE_BYTELOOP                  0
166 #endif
167 
168 #ifndef   SEGGER_RTT_MEMCPY
169   #ifdef  MEMCPY
170     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      MEMCPY((pDest), (pSrc), (NumBytes))
171   #else
172     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      memcpy((pDest), (pSrc), (NumBytes))
173   #endif
174 #endif
175 
176 #ifndef   MIN
177   #define MIN(a, b)                                       (((a) < (b)) ? (a) : (b))
178 #endif
179 
180 #ifndef   MAX
181   #define MAX(a, b)                                       (((a) > (b)) ? (a) : (b))
182 #endif
183 //
184 // For some environments, NULL may not be defined until certain headers are included
185 //
186 #ifndef NULL
187   #define NULL                                            0
188 #endif
189 
190 /*********************************************************************
191 *
192 *       Defines, fixed
193 *
194 **********************************************************************
195 */
196 #if (defined __ICCARM__) || (defined __ICCRX__)
197   #define RTT_PRAGMA(P) _Pragma(#P)
198 #endif
199 
200 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
201   #if ((defined __GNUC__) || (defined __clang__))
202     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
203   #elif (defined __ICCARM__) || (defined __ICCRX__)
204     #define PRAGMA(A) _Pragma(#A)
205 #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
206                                   Var
207   #elif (defined __CC_ARM)
208     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
209   #else
210     #error "Alignment not supported for this compiler."
211   #endif
212 #else
213   #define SEGGER_RTT_ALIGN(Var, Alignment) Var
214 #endif
215 
216 #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
217   #if ((defined __GNUC__) || (defined __clang__))
218     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
219   #elif (defined __ICCARM__) || (defined __ICCRX__)
220 #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
221                                         Var
222   #elif (defined __CC_ARM)
223     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init))  Var
224   #else
225     #error "Section placement not supported for this compiler."
226   #endif
227 #else
228   #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
229 #endif
230 
231 #if SEGGER_RTT_ALIGNMENT
232   #define SEGGER_RTT_CB_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
233 #else
234   #define SEGGER_RTT_CB_ALIGN(Var)  Var
235 #endif
236 
237 #if SEGGER_RTT_BUFFER_ALIGNMENT
238   #define SEGGER_RTT_BUFFER_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
239 #else
240   #define SEGGER_RTT_BUFFER_ALIGN(Var)  Var
241 #endif
242 
243 
244 #if defined(SEGGER_RTT_SECTION)
245   #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
246 #else
247   #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
248 #endif
249 
250 #if defined(SEGGER_RTT_BUFFER_SECTION)
251   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
252 #else
253   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
254 #endif
255 
256 /*********************************************************************
257 *
258 *       Static const data
259 *
260 **********************************************************************
261 */
262 
263 static const unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
264 
265 /*********************************************************************
266 *
267 *       Static data
268 *
269 **********************************************************************
270 */
271 
272 //
273 // RTT Control Block and allocate buffers for channel 0
274 //
275 #if SEGGER_RTT_CPU_CACHE_LINE_SIZE
276   #if ((defined __GNUC__) || (defined __clang__))
277     SEGGER_RTT_CB _SEGGER_RTT                                                             __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
278     static char   _acUpBuffer  [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)]   __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
279     static char   _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
280   #elif (defined __ICCARM__)
281     #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
282     SEGGER_RTT_CB _SEGGER_RTT;
283     #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
284     static char   _acUpBuffer  [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)];
285     #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
286     static char   _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)];
287   #else
288     #error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned"
289   #endif
290 #else
291   SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
292   SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer  [BUFFER_SIZE_UP]));
293   SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
294 #endif
295 
296 static unsigned char _ActiveTerminal;
297 
298 /*********************************************************************
299 *
300 *       Static functions
301 *
302 **********************************************************************
303 */
304 
305 /*********************************************************************
306 *
307 *       _DoInit()
308 *
309 *  Function description
310 *    Initializes the control block an buffers.
311 *
312 *  Notes
313 *    (1) May only be called via INIT() to avoid overriding settings.
314 *        The only exception is SEGGER_RTT_Init(), to make an intentional override possible.
315 */
316   #define INIT()                                                                             \
317     do {                                                                                     \
318       volatile SEGGER_RTT_CB* pRTTCBInit;                                                    \
319       pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \
320       if (pRTTCBInit->acID[0] != 'S') {                                                      \
321         _DoInit();                                                                           \
322       }                                                                                      \
323     } while (0)
324 
_DoInit(void)325 static void _DoInit(void) {
326   volatile SEGGER_RTT_CB* p;   // Volatile to make sure that compiler cannot change the order of accesses to the control block
327   static const char _aInitStr[] = "\0\0\0\0\0\0TTR REGGES";  // Init complete ID string to make sure that things also work if RTT is linked to a no-init memory area
328   unsigned i;
329   //
330   // Initialize control block
331   //
332   p                     = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access control block uncached so that nothing in the cache ever becomes dirty and all changes are visible in HW directly
333   memset((SEGGER_RTT_CB*)p, 0, sizeof(_SEGGER_RTT));         // Make sure that the RTT CB is always zero initialized.
334   p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
335   p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
336   //
337   // Initialize up buffer 0
338   //
339   p->aUp[0].sName         = "Terminal";
340   p->aUp[0].pBuffer       = _acUpBuffer;
341   p->aUp[0].SizeOfBuffer  = BUFFER_SIZE_UP;
342   p->aUp[0].RdOff         = 0u;
343   p->aUp[0].WrOff         = 0u;
344   p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
345   //
346   // Initialize down buffer 0
347   //
348   p->aDown[0].sName         = "Terminal";
349   p->aDown[0].pBuffer       = _acDownBuffer;
350   p->aDown[0].SizeOfBuffer  = BUFFER_SIZE_DOWN;
351   p->aDown[0].RdOff         = 0u;
352   p->aDown[0].WrOff         = 0u;
353   p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
354   //
355   // Finish initialization of the control block.
356   // Copy Id string backwards to make sure that "SEGGER RTT" is not found in initializer memory (usually flash),
357   // as this would cause J-Link to "find" the control block at a wrong address.
358   //
359   RTT__DMB();                       // Force order of memory accesses for cores that may perform out-of-order memory accesses
360   for (i = 0; i < sizeof(_aInitStr) - 1; ++i) {
361     p->acID[i] = _aInitStr[sizeof(_aInitStr) - 2 - i];  // Skip terminating \0 at the end of the array
362   }
363   RTT__DMB();                       // Force order of memory accesses for cores that may perform out-of-order memory accesses
364 }
365 
366 /*********************************************************************
367 *
368 *       _WriteBlocking()
369 *
370 *  Function description
371 *    Stores a specified number of characters in SEGGER RTT ring buffer
372 *    and updates the associated write pointer which is periodically
373 *    read by the host.
374 *    The caller is responsible for managing the write chunk sizes as
375 *    _WriteBlocking() will block until all data has been posted successfully.
376 *
377 *  Parameters
378 *    pRing        Ring buffer to post to.
379 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
380 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
381 *
382 *  Return value
383 *    >= 0 - Number of bytes written into buffer.
384 */
_WriteBlocking(SEGGER_RTT_BUFFER_UP * pRing,const char * pBuffer,unsigned NumBytes)385 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
386   unsigned NumBytesToWrite;
387   unsigned NumBytesWritten;
388   unsigned RdOff;
389   unsigned WrOff;
390   volatile char* pDst;
391   //
392   // Write data to buffer and handle wrap-around if necessary
393   //
394   NumBytesWritten = 0u;
395   WrOff = pRing->WrOff;
396   do {
397     RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
398     if (RdOff > WrOff) {
399       NumBytesToWrite = RdOff - WrOff - 1u;
400     } else {
401       NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
402     }
403     NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
404     NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
405     pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
406 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
407     NumBytesWritten += NumBytesToWrite;
408     NumBytes        -= NumBytesToWrite;
409     WrOff           += NumBytesToWrite;
410     while (NumBytesToWrite--) {
411       *pDst++ = *pBuffer++;
412     };
413 #else
414     SEGGER_RTT_MEMCPY((void*)pDst, pBuffer, NumBytesToWrite);
415     NumBytesWritten += NumBytesToWrite;
416     pBuffer         += NumBytesToWrite;
417     NumBytes        -= NumBytesToWrite;
418     WrOff           += NumBytesToWrite;
419 #endif
420     if (WrOff == pRing->SizeOfBuffer) {
421       WrOff = 0u;
422     }
423     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
424     pRing->WrOff = WrOff;
425   } while (NumBytes);
426   return NumBytesWritten;
427 }
428 
429 /*********************************************************************
430 *
431 *       _WriteNoCheck()
432 *
433 *  Function description
434 *    Stores a specified number of characters in SEGGER RTT ring buffer
435 *    and updates the associated write pointer which is periodically
436 *    read by the host.
437 *    It is callers responsibility to make sure data actually fits in buffer.
438 *
439 *  Parameters
440 *    pRing        Ring buffer to post to.
441 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
442 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
443 *
444 *  Notes
445 *    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
446 */
_WriteNoCheck(SEGGER_RTT_BUFFER_UP * pRing,const char * pData,unsigned NumBytes)447 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
448   unsigned NumBytesAtOnce;
449   unsigned WrOff;
450   unsigned Rem;
451   volatile char* pDst;
452 
453   WrOff = pRing->WrOff;
454   Rem = pRing->SizeOfBuffer - WrOff;
455   if (Rem > NumBytes) {
456     //
457     // All data fits before wrap around
458     //
459     pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
460 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
461     WrOff += NumBytes;
462     while (NumBytes--) {
463       *pDst++ = *pData++;
464     };
465     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
466     pRing->WrOff = WrOff;
467 #else
468     SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes);
469     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
470     pRing->WrOff = WrOff + NumBytes;
471 #endif
472   } else {
473     //
474     // We reach the end of the buffer, so need to wrap around
475     //
476 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
477     pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
478     NumBytesAtOnce = Rem;
479     while (NumBytesAtOnce--) {
480       *pDst++ = *pData++;
481     };
482     pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
483     NumBytesAtOnce = NumBytes - Rem;
484     while (NumBytesAtOnce--) {
485       *pDst++ = *pData++;
486     };
487     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
488     pRing->WrOff = NumBytes - Rem;
489 #else
490     NumBytesAtOnce = Rem;
491     pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
492     SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytesAtOnce);
493     NumBytesAtOnce = NumBytes - Rem;
494     pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
495     SEGGER_RTT_MEMCPY((void*)pDst, pData + Rem, NumBytesAtOnce);
496     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
497     pRing->WrOff = NumBytesAtOnce;
498 #endif
499   }
500 }
501 
502 /*********************************************************************
503 *
504 *       _PostTerminalSwitch()
505 *
506 *  Function description
507 *    Switch terminal to the given terminal ID.  It is the caller's
508 *    responsibility to ensure the terminal ID is correct and there is
509 *    enough space in the buffer for this to complete successfully.
510 *
511 *  Parameters
512 *    pRing        Ring buffer to post to.
513 *    TerminalId   Terminal ID to switch to.
514 */
_PostTerminalSwitch(SEGGER_RTT_BUFFER_UP * pRing,unsigned char TerminalId)515 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
516   unsigned char ac[2];
517 
518   ac[0] = 0xFFu;
519   ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
520   _WriteBlocking(pRing, (const char*)ac, 2u);
521 }
522 
523 /*********************************************************************
524 *
525 *       _GetAvailWriteSpace()
526 *
527 *  Function description
528 *    Returns the number of bytes that can be written to the ring
529 *    buffer without blocking.
530 *
531 *  Parameters
532 *    pRing        Ring buffer to check.
533 *
534 *  Return value
535 *    Number of bytes that are free in the buffer.
536 */
_GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP * pRing)537 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
538   unsigned RdOff;
539   unsigned WrOff;
540   unsigned r;
541   //
542   // Avoid warnings regarding volatile access order.  It's not a problem
543   // in this case, but dampen compiler enthusiasm.
544   //
545   RdOff = pRing->RdOff;
546   WrOff = pRing->WrOff;
547   if (RdOff <= WrOff) {
548     r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
549   } else {
550     r = RdOff - WrOff - 1u;
551   }
552   return r;
553 }
554 
555 /*********************************************************************
556 *
557 *       Public code
558 *
559 **********************************************************************
560 */
561 
562 /*********************************************************************
563 *
564 *       SEGGER_RTT_ReadUpBufferNoLock()
565 *
566 *  Function description
567 *    Reads characters from SEGGER real-time-terminal control block
568 *    which have been previously stored by the application.
569 *    Do not lock against interrupts and multiple access.
570 *    Used to do the same operation that J-Link does, to transfer
571 *    RTT data via other channels, such as TCP/IP or UART.
572 *
573 *  Parameters
574 *    BufferIndex  Index of Up-buffer to be used.
575 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
576 *    BufferSize   Size of the target application buffer.
577 *
578 *  Return value
579 *    Number of bytes that have been read.
580 *
581 *  Additional information
582 *    This function must not be called when J-Link might also do RTT.
583 */
SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)584 unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
585   unsigned                NumBytesRem;
586   unsigned                NumBytesRead;
587   unsigned                RdOff;
588   unsigned                WrOff;
589   unsigned char*          pBuffer;
590   SEGGER_RTT_BUFFER_UP*   pRing;
591   volatile char*          pSrc;
592 
593   INIT();
594   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
595   pBuffer = (unsigned char*)pData;
596   RdOff = pRing->RdOff;
597   WrOff = pRing->WrOff;
598   NumBytesRead = 0u;
599   //
600   // Read from current read position to wrap-around of buffer, first
601   //
602   if (RdOff > WrOff) {
603     NumBytesRem = pRing->SizeOfBuffer - RdOff;
604     NumBytesRem = MIN(NumBytesRem, BufferSize);
605     pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
606 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
607     NumBytesRead += NumBytesRem;
608     BufferSize   -= NumBytesRem;
609     RdOff        += NumBytesRem;
610     while (NumBytesRem--) {
611       *pBuffer++ = *pSrc++;
612     };
613 #else
614     SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem);
615     NumBytesRead += NumBytesRem;
616     pBuffer      += NumBytesRem;
617     BufferSize   -= NumBytesRem;
618     RdOff        += NumBytesRem;
619 #endif
620     //
621     // Handle wrap-around of buffer
622     //
623     if (RdOff == pRing->SizeOfBuffer) {
624       RdOff = 0u;
625     }
626   }
627   //
628   // Read remaining items of buffer
629   //
630   NumBytesRem = WrOff - RdOff;
631   NumBytesRem = MIN(NumBytesRem, BufferSize);
632   if (NumBytesRem > 0u) {
633     pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
634 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
635     NumBytesRead += NumBytesRem;
636     BufferSize   -= NumBytesRem;
637     RdOff        += NumBytesRem;
638     while (NumBytesRem--) {
639       *pBuffer++ = *pSrc++;
640     };
641 #else
642     SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem);
643     NumBytesRead += NumBytesRem;
644     pBuffer      += NumBytesRem;
645     BufferSize   -= NumBytesRem;
646     RdOff        += NumBytesRem;
647 #endif
648   }
649   //
650   // Update read offset of buffer
651   //
652   if (NumBytesRead) {
653     pRing->RdOff = RdOff;
654   }
655   //
656   return NumBytesRead;
657 }
658 
659 /*********************************************************************
660 *
661 *       SEGGER_RTT_ReadNoLock()
662 *
663 *  Function description
664 *    Reads characters from SEGGER real-time-terminal control block
665 *    which have been previously stored by the host.
666 *    Do not lock against interrupts and multiple access.
667 *
668 *  Parameters
669 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
670 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
671 *    BufferSize   Size of the target application buffer.
672 *
673 *  Return value
674 *    Number of bytes that have been read.
675 */
SEGGER_RTT_ReadNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)676 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
677   unsigned                NumBytesRem;
678   unsigned                NumBytesRead;
679   unsigned                RdOff;
680   unsigned                WrOff;
681   unsigned char*          pBuffer;
682   SEGGER_RTT_BUFFER_DOWN* pRing;
683   volatile char*          pSrc;
684   //
685   INIT();
686   pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
687   pBuffer = (unsigned char*)pData;
688   RdOff = pRing->RdOff;
689   WrOff = pRing->WrOff;
690   NumBytesRead = 0u;
691   //
692   // Read from current read position to wrap-around of buffer, first
693   //
694   if (RdOff > WrOff) {
695     NumBytesRem = pRing->SizeOfBuffer - RdOff;
696     NumBytesRem = MIN(NumBytesRem, BufferSize);
697     pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
698 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
699     NumBytesRead += NumBytesRem;
700     BufferSize   -= NumBytesRem;
701     RdOff        += NumBytesRem;
702     while (NumBytesRem--) {
703       *pBuffer++ = *pSrc++;
704     };
705 #else
706     SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem);
707     NumBytesRead += NumBytesRem;
708     pBuffer      += NumBytesRem;
709     BufferSize   -= NumBytesRem;
710     RdOff        += NumBytesRem;
711 #endif
712     //
713     // Handle wrap-around of buffer
714     //
715     if (RdOff == pRing->SizeOfBuffer) {
716       RdOff = 0u;
717     }
718   }
719   //
720   // Read remaining items of buffer
721   //
722   NumBytesRem = WrOff - RdOff;
723   NumBytesRem = MIN(NumBytesRem, BufferSize);
724   if (NumBytesRem > 0u) {
725     pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
726 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
727     NumBytesRead += NumBytesRem;
728     BufferSize   -= NumBytesRem;
729     RdOff        += NumBytesRem;
730     while (NumBytesRem--) {
731       *pBuffer++ = *pSrc++;
732     };
733 #else
734     SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem);
735     NumBytesRead += NumBytesRem;
736     pBuffer      += NumBytesRem;
737     BufferSize   -= NumBytesRem;
738     RdOff        += NumBytesRem;
739 #endif
740   }
741   if (NumBytesRead) {
742     pRing->RdOff = RdOff;
743   }
744   //
745   return NumBytesRead;
746 }
747 
748 /*********************************************************************
749 *
750 *       SEGGER_RTT_ReadUpBuffer
751 *
752 *  Function description
753 *    Reads characters from SEGGER real-time-terminal control block
754 *    which have been previously stored by the application.
755 *    Used to do the same operation that J-Link does, to transfer
756 *    RTT data via other channels, such as TCP/IP or UART.
757 *
758 *  Parameters
759 *    BufferIndex  Index of Up-buffer to be used.
760 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
761 *    BufferSize   Size of the target application buffer.
762 *
763 *  Return value
764 *    Number of bytes that have been read.
765 *
766 *  Additional information
767 *    This function must not be called when J-Link might also do RTT.
768 *    This function locks against all other RTT operations. I.e. during
769 *    the read operation, writing is also locked.
770 *    If only one consumer reads from the up buffer,
771 *    call sEGGER_RTT_ReadUpBufferNoLock() instead.
772 */
SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex,void * pBuffer,unsigned BufferSize)773 unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
774   unsigned NumBytesRead;
775 
776   SEGGER_RTT_LOCK();
777   //
778   // Call the non-locking read function
779   //
780   NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize);
781   //
782   // Finish up.
783   //
784   SEGGER_RTT_UNLOCK();
785   //
786   return NumBytesRead;
787 }
788 
789 /*********************************************************************
790 *
791 *       SEGGER_RTT_Read
792 *
793 *  Function description
794 *    Reads characters from SEGGER real-time-terminal control block
795 *    which have been previously stored by the host.
796 *
797 *  Parameters
798 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
799 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
800 *    BufferSize   Size of the target application buffer.
801 *
802 *  Return value
803 *    Number of bytes that have been read.
804 */
SEGGER_RTT_Read(unsigned BufferIndex,void * pBuffer,unsigned BufferSize)805 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
806   unsigned NumBytesRead;
807 
808   SEGGER_RTT_LOCK();
809   //
810   // Call the non-locking read function
811   //
812   NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
813   //
814   // Finish up.
815   //
816   SEGGER_RTT_UNLOCK();
817   //
818   return NumBytesRead;
819 }
820 
821 /*********************************************************************
822 *
823 *       SEGGER_RTT_WriteWithOverwriteNoLock
824 *
825 *  Function description
826 *    Stores a specified number of characters in SEGGER RTT
827 *    control block.
828 *    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application
829 *    and overwrites data if the data does not fit into the buffer.
830 *
831 *  Parameters
832 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
833 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
834 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
835 *
836 *  Notes
837 *    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
838 *    (2) For performance reasons this function does not call Init()
839 *        and may only be called after RTT has been initialized.
840 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
841 *    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link
842 *        connection reads RTT data.
843 */
SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)844 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
845   const char*           pData;
846   SEGGER_RTT_BUFFER_UP* pRing;
847   unsigned              Avail;
848   volatile char*        pDst;
849   //
850   // Get "to-host" ring buffer and copy some elements into local variables.
851   //
852   pData = (const char *)pBuffer;
853   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
854   //
855   // Check if we will overwrite data and need to adjust the RdOff.
856   //
857   if (pRing->WrOff == pRing->RdOff) {
858     Avail = pRing->SizeOfBuffer - 1u;
859   } else if ( pRing->WrOff < pRing->RdOff) {
860     Avail = pRing->RdOff - pRing->WrOff - 1u;
861   } else {
862     Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
863   }
864   if (NumBytes > Avail) {
865     pRing->RdOff += (NumBytes - Avail);
866     while (pRing->RdOff >= pRing->SizeOfBuffer) {
867       pRing->RdOff -= pRing->SizeOfBuffer;
868     }
869   }
870   //
871   // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
872   //
873   Avail = pRing->SizeOfBuffer - pRing->WrOff;
874   do {
875     if (Avail > NumBytes) {
876       //
877       // Last round
878       //
879       pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
880 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
881       Avail = NumBytes;
882       while (NumBytes--) {
883         *pDst++ = *pData++;
884       };
885       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
886       pRing->WrOff += Avail;
887 #else
888       SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes);
889       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
890       pRing->WrOff += NumBytes;
891 #endif
892       break;
893     } else {
894       //
895       //  Wrap-around necessary, write until wrap-around and reset WrOff
896       //
897       pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
898 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
899       NumBytes -= Avail;
900       while (Avail--) {
901         *pDst++ = *pData++;
902       };
903       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
904       pRing->WrOff = 0;
905 #else
906       SEGGER_RTT_MEMCPY((void*)pDst, pData, Avail);
907       pData += Avail;
908       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
909       pRing->WrOff = 0;
910       NumBytes -= Avail;
911 #endif
912       Avail = (pRing->SizeOfBuffer - 1);
913     }
914   } while (NumBytes);
915 }
916 
917 /*********************************************************************
918 *
919 *       SEGGER_RTT_WriteSkipNoLock
920 *
921 *  Function description
922 *    Stores a specified number of characters in SEGGER RTT
923 *    control block which is then read by the host.
924 *    SEGGER_RTT_WriteSkipNoLock does not lock the application and
925 *    skips all data, if the data does not fit into the buffer.
926 *
927 *  Parameters
928 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
929 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
930 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
931 *                 MUST be > 0!!!
932 *                 This is done for performance reasons, so no initial check has do be done.
933 *
934 *  Return value
935 *    1: Data has been copied
936 *    0: No space, data has not been copied
937 *
938 *  Notes
939 *    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
940 *    (2) For performance reasons this function does not call Init()
941 *        and may only be called after RTT has been initialized.
942 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
943 */
944 #if (RTT_USE_ASM == 0)
SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)945 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
946   const char*           pData;
947   SEGGER_RTT_BUFFER_UP* pRing;
948   unsigned              Avail;
949   unsigned              RdOff;
950   unsigned              WrOff;
951   unsigned              Rem;
952   volatile char*        pDst;
953   //
954   // Cases:
955   //   1) RdOff <= WrOff => Space until wrap-around is sufficient
956   //   2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
957   //   3) RdOff <  WrOff => No space in buf
958   //   4) RdOff >  WrOff => Space is sufficient
959   //   5) RdOff >  WrOff => No space in buf
960   //
961   // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
962   //
963   pData = (const char *)pBuffer;
964   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
965   RdOff = pRing->RdOff;
966   WrOff = pRing->WrOff;
967   pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
968   if (RdOff <= WrOff) {                                 // Case 1), 2) or 3)
969     Avail = pRing->SizeOfBuffer - WrOff - 1u;           // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
970     if (Avail >= NumBytes) {                            // Case 1)?
971       memcpy((void*)pDst, pData, NumBytes);
972       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
973       pRing->WrOff = WrOff + NumBytes;
974       return 1;
975     }
976     Avail += RdOff;                                     // Space incl. wrap-around
977     if (Avail >= NumBytes) {                            // Case 2? => If not, we have case 3) (does not fit)
978       Rem = pRing->SizeOfBuffer - WrOff;                // Space until end of buffer
979       memcpy((void*)pDst, pData, Rem);                  // Copy 1st chunk
980       NumBytes -= Rem;
981       //
982       // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
983       // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
984       // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
985       // Therefore, check if 2nd memcpy is necessary at all
986       //
987       if (NumBytes) {
988         pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
989         memcpy((void*)pDst, pData + Rem, NumBytes);
990       }
991       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
992       pRing->WrOff = NumBytes;
993       return 1;
994     }
995   } else {                                             // Potential case 4)
996     Avail = RdOff - WrOff - 1u;
997     if (Avail >= NumBytes) {                           // Case 4)? => If not, we have case 5) (does not fit)
998       memcpy((void*)pDst, pData, NumBytes);
999       RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1000       pRing->WrOff = WrOff + NumBytes;
1001       return 1;
1002     }
1003   }
1004   return 0;     // No space in buffer
1005 }
1006 #endif
1007 
1008 /*********************************************************************
1009 *
1010 *       SEGGER_RTT_WriteDownBufferNoLock
1011 *
1012 *  Function description
1013 *    Stores a specified number of characters in SEGGER RTT
1014 *    control block inside a <Down> buffer.
1015 *    SEGGER_RTT_WriteDownBufferNoLock does not lock the application.
1016 *    Used to do the same operation that J-Link does, to transfer
1017 *    RTT data from other channels, such as TCP/IP or UART.
1018 *
1019 *  Parameters
1020 *    BufferIndex  Index of "Down"-buffer to be used.
1021 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
1022 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
1023 *
1024 *  Return value
1025 *    Number of bytes which have been stored in the "Down"-buffer.
1026 *
1027 *  Notes
1028 *    (1) Data is stored according to buffer flags.
1029 *    (2) For performance reasons this function does not call Init()
1030 *        and may only be called after RTT has been initialized.
1031 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1032 *
1033 *  Additional information
1034 *    This function must not be called when J-Link might also do RTT.
1035 */
SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1036 unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
1037   unsigned                Status;
1038   unsigned                Avail;
1039   const char*             pData;
1040   SEGGER_RTT_BUFFER_UP*   pRing;
1041   //
1042   // Get "to-target" ring buffer.
1043   // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link.
1044   //
1045   pData = (const char *)pBuffer;
1046   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1047   //
1048   // How we output depends upon the mode...
1049   //
1050   switch (pRing->Flags) {
1051   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1052     //
1053     // If we are in skip mode and there is no space for the whole
1054     // of this output, don't bother.
1055     //
1056     Avail = _GetAvailWriteSpace(pRing);
1057     if (Avail < NumBytes) {
1058       Status = 0u;
1059     } else {
1060       Status = NumBytes;
1061       _WriteNoCheck(pRing, pData, NumBytes);
1062     }
1063     break;
1064   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1065     //
1066     // If we are in trim mode, trim to what we can output without blocking.
1067     //
1068     Avail = _GetAvailWriteSpace(pRing);
1069     Status = Avail < NumBytes ? Avail : NumBytes;
1070     _WriteNoCheck(pRing, pData, Status);
1071     break;
1072   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1073     //
1074     // If we are in blocking mode, output everything.
1075     //
1076     Status = _WriteBlocking(pRing, pData, NumBytes);
1077     break;
1078   default:
1079     Status = 0u;
1080     break;
1081   }
1082   //
1083   // Finish up.
1084   //
1085   return Status;
1086 }
1087 
1088 /*********************************************************************
1089 *
1090 *       SEGGER_RTT_WriteNoLock
1091 *
1092 *  Function description
1093 *    Stores a specified number of characters in SEGGER RTT
1094 *    control block which is then read by the host.
1095 *    SEGGER_RTT_WriteNoLock does not lock the application.
1096 *
1097 *  Parameters
1098 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1099 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
1100 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
1101 *
1102 *  Return value
1103 *    Number of bytes which have been stored in the "Up"-buffer.
1104 *
1105 *  Notes
1106 *    (1) Data is stored according to buffer flags.
1107 *    (2) For performance reasons this function does not call Init()
1108 *        and may only be called after RTT has been initialized.
1109 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1110 */
SEGGER_RTT_WriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1111 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
1112   unsigned              Status;
1113   unsigned              Avail;
1114   const char*           pData;
1115   SEGGER_RTT_BUFFER_UP* pRing;
1116   //
1117   // Get "to-host" ring buffer.
1118   //
1119   pData = (const char *)pBuffer;
1120   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1121   //
1122   // How we output depends upon the mode...
1123   //
1124   switch (pRing->Flags) {
1125   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1126     //
1127     // If we are in skip mode and there is no space for the whole
1128     // of this output, don't bother.
1129     //
1130     Avail = _GetAvailWriteSpace(pRing);
1131     if (Avail < NumBytes) {
1132       Status = 0u;
1133     } else {
1134       Status = NumBytes;
1135       _WriteNoCheck(pRing, pData, NumBytes);
1136     }
1137     break;
1138   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1139     //
1140     // If we are in trim mode, trim to what we can output without blocking.
1141     //
1142     Avail = _GetAvailWriteSpace(pRing);
1143     Status = Avail < NumBytes ? Avail : NumBytes;
1144     _WriteNoCheck(pRing, pData, Status);
1145     break;
1146   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1147     //
1148     // If we are in blocking mode, output everything.
1149     //
1150     Status = _WriteBlocking(pRing, pData, NumBytes);
1151     break;
1152   default:
1153     Status = 0u;
1154     break;
1155   }
1156   //
1157   // Finish up.
1158   //
1159   return Status;
1160 }
1161 
1162 /*********************************************************************
1163 *
1164 *       SEGGER_RTT_WriteDownBuffer
1165 *
1166 *  Function description
1167 *    Stores a specified number of characters in SEGGER RTT control block in a <Down> buffer.
1168 *
1169 *  Parameters
1170 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1171 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
1172 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
1173 *
1174 *  Return value
1175 *    Number of bytes which have been stored in the "Down"-buffer.
1176 *
1177 *  Notes
1178 *    (1) Data is stored according to buffer flags.
1179 *
1180 *  Additional information
1181 *    This function must not be called when J-Link might also do RTT.
1182 *    This function locks against all other RTT operations. I.e. during
1183 *    the write operation, writing from the application is also locked.
1184 *    If only one consumer writes to the down buffer,
1185 *    call SEGGER_RTT_WriteDownBufferNoLock() instead.
1186 */
SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1187 unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
1188   unsigned Status;
1189 
1190   INIT();
1191   SEGGER_RTT_LOCK();
1192   Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes);  // Call the non-locking write function
1193   SEGGER_RTT_UNLOCK();
1194   return Status;
1195 }
1196 
1197 /*********************************************************************
1198 *
1199 *       SEGGER_RTT_Write
1200 *
1201 *  Function description
1202 *    Stores a specified number of characters in SEGGER RTT
1203 *    control block which is then read by the host.
1204 *
1205 *  Parameters
1206 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1207 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
1208 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
1209 *
1210 *  Return value
1211 *    Number of bytes which have been stored in the "Up"-buffer.
1212 *
1213 *  Notes
1214 *    (1) Data is stored according to buffer flags.
1215 */
SEGGER_RTT_Write(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1216 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
1217   unsigned Status;
1218 
1219   INIT();
1220   SEGGER_RTT_LOCK();
1221   Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);  // Call the non-locking write function
1222   SEGGER_RTT_UNLOCK();
1223   return Status;
1224 }
1225 
1226 /*********************************************************************
1227 *
1228 *       SEGGER_RTT_WriteString
1229 *
1230 *  Function description
1231 *    Stores string in SEGGER RTT control block.
1232 *    This data is read by the host.
1233 *
1234 *  Parameters
1235 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1236 *    s            Pointer to string.
1237 *
1238 *  Return value
1239 *    Number of bytes which have been stored in the "Up"-buffer.
1240 *
1241 *  Notes
1242 *    (1) Data is stored according to buffer flags.
1243 *    (2) String passed to this function has to be \0 terminated
1244 *    (3) \0 termination character is *not* stored in RTT buffer
1245 */
SEGGER_RTT_WriteString(unsigned BufferIndex,const char * s)1246 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
1247   unsigned Len;
1248 
1249   Len = STRLEN(s);
1250   return SEGGER_RTT_Write(BufferIndex, s, Len);
1251 }
1252 
1253 /*********************************************************************
1254 *
1255 *       SEGGER_RTT_PutCharSkipNoLock
1256 *
1257 *  Function description
1258 *    Stores a single character/byte in SEGGER RTT buffer.
1259 *    SEGGER_RTT_PutCharSkipNoLock does not lock the application and
1260 *    skips the byte, if it does not fit into the buffer.
1261 *
1262 *  Parameters
1263 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1264 *    c            Byte to be stored.
1265 *
1266 *  Return value
1267 *    Number of bytes which have been stored in the "Up"-buffer.
1268 *
1269 *  Notes
1270 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
1271 *    (2) For performance reasons this function does not call Init()
1272 *        and may only be called after RTT has been initialized.
1273 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1274 */
1275 
SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex,char c)1276 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
1277   SEGGER_RTT_BUFFER_UP* pRing;
1278   unsigned              WrOff;
1279   unsigned              Status;
1280   volatile char*        pDst;
1281   //
1282   // Get "to-host" ring buffer.
1283   //
1284   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1285   //
1286   // Get write position and handle wrap-around if necessary
1287   //
1288   WrOff = pRing->WrOff + 1;
1289   if (WrOff == pRing->SizeOfBuffer) {
1290     WrOff = 0;
1291   }
1292   //
1293   // Output byte if free space is available
1294   //
1295   if (WrOff != pRing->RdOff) {
1296     pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1297     *pDst = c;
1298     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1299     pRing->WrOff = WrOff;
1300     Status = 1;
1301   } else {
1302     Status = 0;
1303   }
1304   //
1305   return Status;
1306 }
1307 
1308 /*********************************************************************
1309 *
1310 *       SEGGER_RTT_PutCharSkip
1311 *
1312 *  Function description
1313 *    Stores a single character/byte in SEGGER RTT buffer.
1314 *
1315 *  Parameters
1316 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1317 *    c            Byte to be stored.
1318 *
1319 *  Return value
1320 *    Number of bytes which have been stored in the "Up"-buffer.
1321 *
1322 *  Notes
1323 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
1324 */
1325 
SEGGER_RTT_PutCharSkip(unsigned BufferIndex,char c)1326 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
1327   SEGGER_RTT_BUFFER_UP* pRing;
1328   unsigned              WrOff;
1329   unsigned              Status;
1330   volatile char*        pDst;
1331   //
1332   // Prepare
1333   //
1334   INIT();
1335   SEGGER_RTT_LOCK();
1336   //
1337   // Get "to-host" ring buffer.
1338   //
1339   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1340   //
1341   // Get write position and handle wrap-around if necessary
1342   //
1343   WrOff = pRing->WrOff + 1;
1344   if (WrOff == pRing->SizeOfBuffer) {
1345     WrOff = 0;
1346   }
1347   //
1348   // Output byte if free space is available
1349   //
1350   if (WrOff != pRing->RdOff) {
1351     pDst  = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1352     *pDst = c;
1353     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1354     pRing->WrOff = WrOff;
1355     Status = 1;
1356   } else {
1357     Status = 0;
1358   }
1359   //
1360   // Finish up.
1361   //
1362   SEGGER_RTT_UNLOCK();
1363   //
1364   return Status;
1365 }
1366 
1367  /*********************************************************************
1368 *
1369 *       SEGGER_RTT_PutChar
1370 *
1371 *  Function description
1372 *    Stores a single character/byte in SEGGER RTT buffer.
1373 *
1374 *  Parameters
1375 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1376 *    c            Byte to be stored.
1377 *
1378 *  Return value
1379 *    Number of bytes which have been stored in the "Up"-buffer.
1380 *
1381 *  Notes
1382 *    (1) Data is stored according to buffer flags.
1383 */
1384 
SEGGER_RTT_PutChar(unsigned BufferIndex,char c)1385 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
1386   SEGGER_RTT_BUFFER_UP* pRing;
1387   unsigned              WrOff;
1388   unsigned              Status;
1389   volatile char*        pDst;
1390   //
1391   // Prepare
1392   //
1393   INIT();
1394   SEGGER_RTT_LOCK();
1395   //
1396   // Get "to-host" ring buffer.
1397   //
1398   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1399   //
1400   // Get write position and handle wrap-around if necessary
1401   //
1402   WrOff = pRing->WrOff + 1;
1403   if (WrOff == pRing->SizeOfBuffer) {
1404     WrOff = 0;
1405   }
1406   //
1407   // Wait for free space if mode is set to blocking
1408   //
1409   if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1410     while (WrOff == pRing->RdOff) {
1411       ;
1412     }
1413   }
1414   //
1415   // Output byte if free space is available
1416   //
1417   if (WrOff != pRing->RdOff) {
1418     pDst  = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1419     *pDst = c;
1420     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1421     pRing->WrOff = WrOff;
1422     Status = 1;
1423   } else {
1424     Status = 0;
1425   }
1426   //
1427   // Finish up.
1428   //
1429   SEGGER_RTT_UNLOCK();
1430   return Status;
1431 }
1432 
1433 /*********************************************************************
1434 *
1435 *       SEGGER_RTT_GetKey
1436 *
1437 *  Function description
1438 *    Reads one character from the SEGGER RTT buffer.
1439 *    Host has previously stored data there.
1440 *
1441 *  Return value
1442 *    <  0 -   No character available (buffer empty).
1443 *    >= 0 -   Character which has been read. (Possible values: 0 - 255)
1444 *
1445 *  Notes
1446 *    (1) This function is only specified for accesses to RTT buffer 0.
1447 */
SEGGER_RTT_GetKey(void)1448 int SEGGER_RTT_GetKey(void) {
1449   char c;
1450   int r;
1451 
1452   r = (int)SEGGER_RTT_Read(0u, &c, 1u);
1453   if (r == 1) {
1454     r = (int)(unsigned char)c;
1455   } else {
1456     r = -1;
1457   }
1458   return r;
1459 }
1460 
1461 /*********************************************************************
1462 *
1463 *       SEGGER_RTT_WaitKey
1464 *
1465 *  Function description
1466 *    Waits until at least one character is avaible in the SEGGER RTT buffer.
1467 *    Once a character is available, it is read and this function returns.
1468 *
1469 *  Return value
1470 *    >=0 -   Character which has been read.
1471 *
1472 *  Notes
1473 *    (1) This function is only specified for accesses to RTT buffer 0
1474 *    (2) This function is blocking if no character is present in RTT buffer
1475 */
SEGGER_RTT_WaitKey(void)1476 int SEGGER_RTT_WaitKey(void) {
1477   int r;
1478 
1479   do {
1480     r = SEGGER_RTT_GetKey();
1481   } while (r < 0);
1482   return r;
1483 }
1484 
1485 /*********************************************************************
1486 *
1487 *       SEGGER_RTT_HasKey
1488 *
1489 *  Function description
1490 *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
1491 *
1492 *  Return value
1493 *    == 0 -     No characters are available to read.
1494 *    == 1 -     At least one character is available.
1495 *
1496 *  Notes
1497 *    (1) This function is only specified for accesses to RTT buffer 0
1498 */
SEGGER_RTT_HasKey(void)1499 int SEGGER_RTT_HasKey(void) {
1500   SEGGER_RTT_BUFFER_DOWN* pRing;
1501   unsigned RdOff;
1502   int r;
1503 
1504   INIT();
1505   pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[0] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1506   RdOff = pRing->RdOff;
1507   if (RdOff != pRing->WrOff) {
1508     r = 1;
1509   } else {
1510     r = 0;
1511   }
1512   return r;
1513 }
1514 
1515 /*********************************************************************
1516 *
1517 *       SEGGER_RTT_HasData
1518 *
1519 *  Function description
1520 *    Check if there is data from the host in the given buffer.
1521 *
1522 *  Return value:
1523 *  ==0:  No data
1524 *  !=0:  Data in buffer
1525 *
1526 */
SEGGER_RTT_HasData(unsigned BufferIndex)1527 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
1528   SEGGER_RTT_BUFFER_DOWN* pRing;
1529   unsigned                v;
1530 
1531   pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1532   v = pRing->WrOff;
1533   return v - pRing->RdOff;
1534 }
1535 
1536 /*********************************************************************
1537 *
1538 *       SEGGER_RTT_HasDataUp
1539 *
1540 *  Function description
1541 *    Check if there is data remaining to be sent in the given buffer.
1542 *
1543 *  Return value:
1544 *  ==0:  No data
1545 *  !=0:  Data in buffer
1546 *
1547 */
SEGGER_RTT_HasDataUp(unsigned BufferIndex)1548 unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
1549   SEGGER_RTT_BUFFER_UP* pRing;
1550   unsigned                v;
1551 
1552   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1553   v = pRing->RdOff;
1554   return pRing->WrOff - v;
1555 }
1556 
1557 /*********************************************************************
1558 *
1559 *       SEGGER_RTT_AllocDownBuffer
1560 *
1561 *  Function description
1562 *    Run-time configuration of the next down-buffer (H->T).
1563 *    The next buffer, which is not used yet is configured.
1564 *    This includes: Buffer address, size, name, flags, ...
1565 *
1566 *  Parameters
1567 *    sName        Pointer to a constant name string.
1568 *    pBuffer      Pointer to a buffer to be used.
1569 *    BufferSize   Size of the buffer.
1570 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1571 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1572 *
1573 *  Return value
1574 *    >= 0 - O.K. Buffer Index
1575 *     < 0 - Error
1576 */
SEGGER_RTT_AllocDownBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1577 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1578   int BufferIndex;
1579   volatile SEGGER_RTT_CB* pRTTCB;
1580 
1581   INIT();
1582   SEGGER_RTT_LOCK();
1583   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1584   BufferIndex = 0;
1585   do {
1586     if (pRTTCB->aDown[BufferIndex].pBuffer == NULL) {
1587       break;
1588     }
1589     BufferIndex++;
1590   } while (BufferIndex < pRTTCB->MaxNumDownBuffers);
1591   if (BufferIndex < pRTTCB->MaxNumDownBuffers) {
1592     pRTTCB->aDown[BufferIndex].sName        = sName;
1593     pRTTCB->aDown[BufferIndex].pBuffer      = (char*)pBuffer;
1594     pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize;
1595     pRTTCB->aDown[BufferIndex].RdOff        = 0u;
1596     pRTTCB->aDown[BufferIndex].WrOff        = 0u;
1597     pRTTCB->aDown[BufferIndex].Flags        = Flags;
1598     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1599   } else {
1600     BufferIndex = -1;
1601   }
1602   SEGGER_RTT_UNLOCK();
1603   return BufferIndex;
1604 }
1605 
1606 /*********************************************************************
1607 *
1608 *       SEGGER_RTT_AllocUpBuffer
1609 *
1610 *  Function description
1611 *    Run-time configuration of the next up-buffer (T->H).
1612 *    The next buffer, which is not used yet is configured.
1613 *    This includes: Buffer address, size, name, flags, ...
1614 *
1615 *  Parameters
1616 *    sName        Pointer to a constant name string.
1617 *    pBuffer      Pointer to a buffer to be used.
1618 *    BufferSize   Size of the buffer.
1619 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1620 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1621 *
1622 *  Return value
1623 *    >= 0 - O.K. Buffer Index
1624 *     < 0 - Error
1625 */
SEGGER_RTT_AllocUpBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1626 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1627   int BufferIndex;
1628   volatile SEGGER_RTT_CB* pRTTCB;
1629 
1630   INIT();
1631   SEGGER_RTT_LOCK();
1632   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1633   BufferIndex = 0;
1634   do {
1635     if (pRTTCB->aUp[BufferIndex].pBuffer == NULL) {
1636       break;
1637     }
1638     BufferIndex++;
1639   } while (BufferIndex < pRTTCB->MaxNumUpBuffers);
1640   if (BufferIndex < pRTTCB->MaxNumUpBuffers) {
1641     pRTTCB->aUp[BufferIndex].sName        = sName;
1642     pRTTCB->aUp[BufferIndex].pBuffer      = (char*)pBuffer;
1643     pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize;
1644     pRTTCB->aUp[BufferIndex].RdOff        = 0u;
1645     pRTTCB->aUp[BufferIndex].WrOff        = 0u;
1646     pRTTCB->aUp[BufferIndex].Flags        = Flags;
1647     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1648   } else {
1649     BufferIndex = -1;
1650   }
1651   SEGGER_RTT_UNLOCK();
1652   return BufferIndex;
1653 }
1654 
1655 /*********************************************************************
1656 *
1657 *       SEGGER_RTT_ConfigUpBuffer
1658 *
1659 *  Function description
1660 *    Run-time configuration of a specific up-buffer (T->H).
1661 *    Buffer to be configured is specified by index.
1662 *    This includes: Buffer address, size, name, flags, ...
1663 *
1664 *  Parameters
1665 *    BufferIndex  Index of the buffer to configure.
1666 *    sName        Pointer to a constant name string.
1667 *    pBuffer      Pointer to a buffer to be used.
1668 *    BufferSize   Size of the buffer.
1669 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1670 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1671 *
1672 *  Return value
1673 *    >= 0 - O.K.
1674 *     < 0 - Error
1675 *
1676 *  Additional information
1677 *    Buffer 0 is configured on compile-time.
1678 *    May only be called once per buffer.
1679 *    Buffer name and flags can be reconfigured using the appropriate functions.
1680 */
SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1681 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1682   int r;
1683   volatile SEGGER_RTT_CB* pRTTCB;
1684   volatile SEGGER_RTT_BUFFER_UP* pUp;
1685 
1686   INIT();
1687   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1688   if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
1689     SEGGER_RTT_LOCK();
1690     pUp = &pRTTCB->aUp[BufferIndex];
1691     if (BufferIndex) {
1692       pUp->sName        = sName;
1693       pUp->pBuffer      = (char*)pBuffer;
1694       pUp->SizeOfBuffer = BufferSize;
1695       pUp->RdOff        = 0u;
1696       pUp->WrOff        = 0u;
1697     }
1698     pUp->Flags          = Flags;
1699     SEGGER_RTT_UNLOCK();
1700     r =  0;
1701   } else {
1702     r = -1;
1703   }
1704   return r;
1705 }
1706 
1707 /*********************************************************************
1708 *
1709 *       SEGGER_RTT_ConfigDownBuffer
1710 *
1711 *  Function description
1712 *    Run-time configuration of a specific down-buffer (H->T).
1713 *    Buffer to be configured is specified by index.
1714 *    This includes: Buffer address, size, name, flags, ...
1715 *
1716 *  Parameters
1717 *    BufferIndex  Index of the buffer to configure.
1718 *    sName        Pointer to a constant name string.
1719 *    pBuffer      Pointer to a buffer to be used.
1720 *    BufferSize   Size of the buffer.
1721 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1722 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1723 *
1724 *  Return value
1725 *    >= 0  O.K.
1726 *     < 0  Error
1727 *
1728 *  Additional information
1729 *    Buffer 0 is configured on compile-time.
1730 *    May only be called once per buffer.
1731 *    Buffer name and flags can be reconfigured using the appropriate functions.
1732 */
SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1733 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1734   int r;
1735   volatile SEGGER_RTT_CB* pRTTCB;
1736   volatile SEGGER_RTT_BUFFER_DOWN* pDown;
1737 
1738   INIT();
1739   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1740   if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
1741     SEGGER_RTT_LOCK();
1742     pDown = &pRTTCB->aDown[BufferIndex];
1743     if (BufferIndex) {
1744       pDown->sName        = sName;
1745       pDown->pBuffer      = (char*)pBuffer;
1746       pDown->SizeOfBuffer = BufferSize;
1747       pDown->RdOff        = 0u;
1748       pDown->WrOff        = 0u;
1749     }
1750     pDown->Flags          = Flags;
1751     RTT__DMB();                     // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
1752     SEGGER_RTT_UNLOCK();
1753     r =  0;
1754   } else {
1755     r = -1;
1756   }
1757   return r;
1758 }
1759 
1760 /*********************************************************************
1761 *
1762 *       SEGGER_RTT_SetNameUpBuffer
1763 *
1764 *  Function description
1765 *    Run-time configuration of a specific up-buffer name (T->H).
1766 *    Buffer to be configured is specified by index.
1767 *
1768 *  Parameters
1769 *    BufferIndex  Index of the buffer to renamed.
1770 *    sName        Pointer to a constant name string.
1771 *
1772 *  Return value
1773 *    >= 0  O.K.
1774 *     < 0  Error
1775 */
SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex,const char * sName)1776 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
1777   int r;
1778   volatile SEGGER_RTT_CB* pRTTCB;
1779   volatile SEGGER_RTT_BUFFER_UP* pUp;
1780 
1781   INIT();
1782   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1783   if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
1784     SEGGER_RTT_LOCK();
1785     pUp = &pRTTCB->aUp[BufferIndex];
1786     pUp->sName = sName;
1787     SEGGER_RTT_UNLOCK();
1788     r =  0;
1789   } else {
1790     r = -1;
1791   }
1792   return r;
1793 }
1794 
1795 /*********************************************************************
1796 *
1797 *       SEGGER_RTT_SetNameDownBuffer
1798 *
1799 *  Function description
1800 *    Run-time configuration of a specific Down-buffer name (T->H).
1801 *    Buffer to be configured is specified by index.
1802 *
1803 *  Parameters
1804 *    BufferIndex  Index of the buffer to renamed.
1805 *    sName        Pointer to a constant name string.
1806 *
1807 *  Return value
1808 *    >= 0  O.K.
1809 *     < 0  Error
1810 */
SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex,const char * sName)1811 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
1812   int r;
1813   volatile SEGGER_RTT_CB* pRTTCB;
1814   volatile SEGGER_RTT_BUFFER_DOWN* pDown;
1815 
1816   INIT();
1817   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1818   if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
1819     SEGGER_RTT_LOCK();
1820     pDown = &pRTTCB->aDown[BufferIndex];
1821     pDown->sName = sName;
1822     SEGGER_RTT_UNLOCK();
1823     r =  0;
1824   } else {
1825     r = -1;
1826   }
1827   return r;
1828 }
1829 
1830 /*********************************************************************
1831 *
1832 *       SEGGER_RTT_SetFlagsUpBuffer
1833 *
1834 *  Function description
1835 *    Run-time configuration of specific up-buffer flags (T->H).
1836 *    Buffer to be configured is specified by index.
1837 *
1838 *  Parameters
1839 *    BufferIndex  Index of the buffer.
1840 *    Flags        Flags to set for the buffer.
1841 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1842 *
1843 *  Return value
1844 *    >= 0  O.K.
1845 *     < 0  Error
1846 */
SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex,unsigned Flags)1847 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
1848   int r;
1849   volatile SEGGER_RTT_CB* pRTTCB;
1850   volatile SEGGER_RTT_BUFFER_UP* pUp;
1851 
1852   INIT();
1853   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1854   if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
1855     SEGGER_RTT_LOCK();
1856     pUp = &pRTTCB->aUp[BufferIndex];
1857     pUp->Flags = Flags;
1858     SEGGER_RTT_UNLOCK();
1859     r =  0;
1860   } else {
1861     r = -1;
1862   }
1863   return r;
1864 }
1865 
1866 /*********************************************************************
1867 *
1868 *       SEGGER_RTT_SetFlagsDownBuffer
1869 *
1870 *  Function description
1871 *    Run-time configuration of specific Down-buffer flags (T->H).
1872 *    Buffer to be configured is specified by index.
1873 *
1874 *  Parameters
1875 *    BufferIndex  Index of the buffer to renamed.
1876 *    Flags        Flags to set for the buffer.
1877 *                 Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
1878 *
1879 *  Return value
1880 *    >= 0  O.K.
1881 *     < 0  Error
1882 */
SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex,unsigned Flags)1883 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
1884   int r;
1885   volatile SEGGER_RTT_CB* pRTTCB;
1886   volatile SEGGER_RTT_BUFFER_DOWN* pDown;
1887 
1888   INIT();
1889   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1890   if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
1891     SEGGER_RTT_LOCK();
1892     pDown = &pRTTCB->aDown[BufferIndex];
1893     pDown->Flags = Flags;
1894     SEGGER_RTT_UNLOCK();
1895     r =  0;
1896   } else {
1897     r = -1;
1898   }
1899   return r;
1900 }
1901 
1902 /*********************************************************************
1903 *
1904 *       SEGGER_RTT_Init
1905 *
1906 *  Function description
1907 *    Initializes the RTT Control Block.
1908 *    Should be used in RAM targets, at start of the application.
1909 *
1910 */
SEGGER_RTT_Init(void)1911 void SEGGER_RTT_Init (void) {
1912   _DoInit();
1913 }
1914 
1915 /*********************************************************************
1916 *
1917 *       SEGGER_RTT_SetTerminal
1918 *
1919 *  Function description
1920 *    Sets the terminal to be used for output on channel 0.
1921 *
1922 *  Parameters
1923 *    TerminalId  Index of the terminal.
1924 *
1925 *  Return value
1926 *    >= 0  O.K.
1927 *     < 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)
1928 *
1929 *  Notes
1930 *    (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
1931 */
SEGGER_RTT_SetTerminal(unsigned char TerminalId)1932 int SEGGER_RTT_SetTerminal (unsigned char TerminalId) {
1933   unsigned char         ac[2];
1934   SEGGER_RTT_BUFFER_UP* pRing;
1935   unsigned Avail;
1936   int r;
1937 
1938   INIT();
1939   r = 0;
1940   ac[0] = 0xFFu;
1941   if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels
1942     ac[1] = _aTerminalId[TerminalId];
1943     pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1944     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
1945     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1946       _ActiveTerminal = TerminalId;
1947       _WriteBlocking(pRing, (const char*)ac, 2u);
1948     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
1949       Avail = _GetAvailWriteSpace(pRing);
1950       if (Avail >= 2) {
1951         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
1952         _WriteNoCheck(pRing, (const char*)ac, 2u);
1953       } else {
1954         r = -1;
1955       }
1956     }
1957     SEGGER_RTT_UNLOCK();
1958   } else {
1959     r = -1;
1960   }
1961   return r;
1962 }
1963 
1964 /*********************************************************************
1965 *
1966 *       SEGGER_RTT_TerminalOut
1967 *
1968 *  Function description
1969 *    Writes a string to the given terminal
1970 *     without changing the terminal for channel 0.
1971 *
1972 *  Parameters
1973 *    TerminalId   Index of the terminal.
1974 *    s            String to be printed on the terminal.
1975 *
1976 *  Return value
1977 *    >= 0 - Number of bytes written.
1978 *     < 0 - Error.
1979 *
1980 */
SEGGER_RTT_TerminalOut(unsigned char TerminalId,const char * s)1981 int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) {
1982   int                   Status;
1983   unsigned              FragLen;
1984   unsigned              Avail;
1985   SEGGER_RTT_BUFFER_UP* pRing;
1986   //
1987   INIT();
1988   //
1989   // Validate terminal ID.
1990   //
1991   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1992     //
1993     // Get "to-host" ring buffer.
1994     //
1995     pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
1996     //
1997     // Need to be able to change terminal, write data, change back.
1998     // Compute the fixed and variable sizes.
1999     //
2000     FragLen = STRLEN(s);
2001     //
2002     // How we output depends upon the mode...
2003     //
2004     SEGGER_RTT_LOCK();
2005     Avail = _GetAvailWriteSpace(pRing);
2006     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
2007     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
2008       //
2009       // If we are in skip mode and there is no space for the whole
2010       // of this output, don't bother switching terminals at all.
2011       //
2012       if (Avail < (FragLen + 4u)) {
2013         Status = 0;
2014       } else {
2015         _PostTerminalSwitch(pRing, TerminalId);
2016         Status = (int)_WriteBlocking(pRing, s, FragLen);
2017         _PostTerminalSwitch(pRing, _ActiveTerminal);
2018       }
2019       break;
2020     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
2021       //
2022       // If we are in trim mode and there is not enough space for everything,
2023       // trim the output but always include the terminal switch.  If no room
2024       // for terminal switch, skip that totally.
2025       //
2026       if (Avail < 4u) {
2027         Status = -1;
2028       } else {
2029         _PostTerminalSwitch(pRing, TerminalId);
2030         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
2031         _PostTerminalSwitch(pRing, _ActiveTerminal);
2032       }
2033       break;
2034     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
2035       //
2036       // If we are in blocking mode, output everything.
2037       //
2038       _PostTerminalSwitch(pRing, TerminalId);
2039       Status = (int)_WriteBlocking(pRing, s, FragLen);
2040       _PostTerminalSwitch(pRing, _ActiveTerminal);
2041       break;
2042     default:
2043       Status = -1;
2044       break;
2045     }
2046     //
2047     // Finish up.
2048     //
2049     SEGGER_RTT_UNLOCK();
2050   } else {
2051     Status = -1;
2052   }
2053   return Status;
2054 }
2055 
2056 /*********************************************************************
2057 *
2058 *       SEGGER_RTT_GetAvailWriteSpace
2059 *
2060 *  Function description
2061 *    Returns the number of bytes available in the ring buffer.
2062 *
2063 *  Parameters
2064 *    BufferIndex  Index of the up buffer.
2065 *
2066 *  Return value
2067 *    Number of bytes that are free in the selected up buffer.
2068 */
SEGGER_RTT_GetAvailWriteSpace(unsigned BufferIndex)2069 unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex) {
2070   SEGGER_RTT_BUFFER_UP* pRing;
2071 
2072   pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF);  // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
2073   return _GetAvailWriteSpace(pRing);
2074 }
2075 
2076 
2077 /*********************************************************************
2078 *
2079 *       SEGGER_RTT_GetBytesInBuffer()
2080 *
2081 *  Function description
2082 *    Returns the number of bytes currently used in the up buffer.
2083 *
2084 *  Parameters
2085 *    BufferIndex  Index of the up buffer.
2086 *
2087 *  Return value
2088 *    Number of bytes that are used in the buffer.
2089 */
SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex)2090 unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) {
2091   unsigned RdOff;
2092   unsigned WrOff;
2093   unsigned r;
2094   volatile SEGGER_RTT_CB* pRTTCB;
2095   //
2096   // Avoid warnings regarding volatile access order.  It's not a problem
2097   // in this case, but dampen compiler enthusiasm.
2098   //
2099   pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);  // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
2100   RdOff = pRTTCB->aUp[BufferIndex].RdOff;
2101   WrOff = pRTTCB->aUp[BufferIndex].WrOff;
2102   if (RdOff <= WrOff) {
2103     r = WrOff - RdOff;
2104   } else {
2105     r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff);
2106   }
2107   return r;
2108 }
2109 
2110 /*************************** End of file ****************************/
2111