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