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