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