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