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