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