xref: /btstack/3rd-party/segger-rtt/SEGGER_RTT.c (revision 09cf8159072d80e092b9c303cea9b43a81b36aee)
1 /*********************************************************************
2 *               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
3 *       Solutions for real time microcontroller applications         *
4 **********************************************************************
5 *                                                                    *
6 *       (c) 2014 - 2017  SEGGER Microcontroller GmbH & Co. KG        *
7 *                                                                    *
8 *       www.segger.com     Support: [email protected]               *
9 *                                                                    *
10 **********************************************************************
11 *                                                                    *
12 *       SEGGER RTT * Real Time Transfer for embedded targets         *
13 *                                                                    *
14 **********************************************************************
15 *                                                                    *
16 * All rights reserved.                                               *
17 *                                                                    *
18 * SEGGER strongly recommends to not make any changes                 *
19 * to or modify the source code of this software in order to stay     *
20 * compatible with the RTT protocol and J-Link.                       *
21 *                                                                    *
22 * Redistribution and use in source and binary forms, with or         *
23 * without modification, are permitted provided that the following    *
24 * 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 & Co. KG         *
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: 6852 $
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)
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 */
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 */
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 */
459 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
460   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, 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 */
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 */
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 */
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 */
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 */
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         do {
834           *pDst++ = *pData++;
835         } while (--NumBytes);
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 */
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 */
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 */
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 
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 
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 
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 */
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 */
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 */
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 */
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_AllocDownBuffer
1282 *
1283 *  Function description
1284 *    Run-time configuration of the next down-buffer (H->T).
1285 *    The next buffer, which is not used yet is configured.
1286 *    This includes: Buffer address, size, name, flags, ...
1287 *
1288 *  Parameters
1289 *    sName        Pointer to a constant name string.
1290 *    pBuffer      Pointer to a buffer to be used.
1291 *    BufferSize   Size of the buffer.
1292 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1293 *
1294 *  Return value
1295 *    >= 0 - O.K. Buffer Index
1296 *     < 0 - Error
1297 */
1298 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1299   int BufferIndex;
1300 
1301   INIT();
1302   SEGGER_RTT_LOCK();
1303   BufferIndex = 0;
1304   do {
1305     if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
1306       break;
1307     }
1308     BufferIndex++;
1309   } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
1310   if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
1311     _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
1312     _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
1313     _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1314     _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
1315     _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
1316     _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
1317   } else {
1318     BufferIndex = -1;
1319   }
1320   SEGGER_RTT_UNLOCK();
1321   return BufferIndex;
1322 }
1323 
1324 /*********************************************************************
1325 *
1326 *       SEGGER_RTT_AllocUpBuffer
1327 *
1328 *  Function description
1329 *    Run-time configuration of the next up-buffer (T->H).
1330 *    The next buffer, which is not used yet is configured.
1331 *    This includes: Buffer address, size, name, flags, ...
1332 *
1333 *  Parameters
1334 *    sName        Pointer to a constant name string.
1335 *    pBuffer      Pointer to a buffer to be used.
1336 *    BufferSize   Size of the buffer.
1337 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1338 *
1339 *  Return value
1340 *    >= 0 - O.K. Buffer Index
1341 *     < 0 - Error
1342 */
1343 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1344   int BufferIndex;
1345 
1346   INIT();
1347   SEGGER_RTT_LOCK();
1348   BufferIndex = 0;
1349   do {
1350     if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
1351       break;
1352     }
1353     BufferIndex++;
1354   } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
1355   if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
1356     _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
1357     _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
1358     _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1359     _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
1360     _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
1361     _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
1362   } else {
1363     BufferIndex = -1;
1364   }
1365   SEGGER_RTT_UNLOCK();
1366   return BufferIndex;
1367 }
1368 
1369 /*********************************************************************
1370 *
1371 *       SEGGER_RTT_ConfigUpBuffer
1372 *
1373 *  Function description
1374 *    Run-time configuration of a specific up-buffer (T->H).
1375 *    Buffer to be configured is specified by index.
1376 *    This includes: Buffer address, size, name, flags, ...
1377 *
1378 *  Parameters
1379 *    BufferIndex  Index of the buffer to configure.
1380 *    sName        Pointer to a constant name string.
1381 *    pBuffer      Pointer to a buffer to be used.
1382 *    BufferSize   Size of the buffer.
1383 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1384 *
1385 *  Return value
1386 *    >= 0 - O.K.
1387 *     < 0 - Error
1388 *
1389 *  Additional information
1390 *    Buffer 0 is configured on compile-time.
1391 *    May only be called once per buffer.
1392 *    Buffer name and flags can be reconfigured using the appropriate functions.
1393 */
1394 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1395   int r;
1396 
1397   INIT();
1398   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1399     SEGGER_RTT_LOCK();
1400     if (BufferIndex > 0u) {
1401       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
1402       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
1403       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1404       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
1405       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
1406     }
1407     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
1408     SEGGER_RTT_UNLOCK();
1409     r =  0;
1410   } else {
1411     r = -1;
1412   }
1413   return r;
1414 }
1415 
1416 /*********************************************************************
1417 *
1418 *       SEGGER_RTT_ConfigDownBuffer
1419 *
1420 *  Function description
1421 *    Run-time configuration of a specific down-buffer (H->T).
1422 *    Buffer to be configured is specified by index.
1423 *    This includes: Buffer address, size, name, flags, ...
1424 *
1425 *  Parameters
1426 *    BufferIndex  Index of the buffer to configure.
1427 *    sName        Pointer to a constant name string.
1428 *    pBuffer      Pointer to a buffer to be used.
1429 *    BufferSize   Size of the buffer.
1430 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1431 *
1432 *  Return value
1433 *    >= 0  O.K.
1434 *     < 0  Error
1435 *
1436 *  Additional information
1437 *    Buffer 0 is configured on compile-time.
1438 *    May only be called once per buffer.
1439 *    Buffer name and flags can be reconfigured using the appropriate functions.
1440 */
1441 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1442   int r;
1443 
1444   INIT();
1445   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1446     SEGGER_RTT_LOCK();
1447     if (BufferIndex > 0u) {
1448       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
1449       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
1450       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1451       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
1452       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
1453     }
1454     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
1455     SEGGER_RTT_UNLOCK();
1456     r =  0;
1457   } else {
1458     r = -1;
1459   }
1460   return r;
1461 }
1462 
1463 /*********************************************************************
1464 *
1465 *       SEGGER_RTT_SetNameUpBuffer
1466 *
1467 *  Function description
1468 *    Run-time configuration of a specific up-buffer name (T->H).
1469 *    Buffer to be configured is specified by index.
1470 *
1471 *  Parameters
1472 *    BufferIndex  Index of the buffer to renamed.
1473 *    sName        Pointer to a constant name string.
1474 *
1475 *  Return value
1476 *    >= 0  O.K.
1477 *     < 0  Error
1478 */
1479 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
1480   int r;
1481 
1482   INIT();
1483   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1484     SEGGER_RTT_LOCK();
1485     _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1486     SEGGER_RTT_UNLOCK();
1487     r =  0;
1488   } else {
1489     r = -1;
1490   }
1491   return r;
1492 }
1493 
1494 /*********************************************************************
1495 *
1496 *       SEGGER_RTT_SetNameDownBuffer
1497 *
1498 *  Function description
1499 *    Run-time configuration of a specific Down-buffer name (T->H).
1500 *    Buffer to be configured is specified by index.
1501 *
1502 *  Parameters
1503 *    BufferIndex  Index of the buffer to renamed.
1504 *    sName        Pointer to a constant name string.
1505 *
1506 *  Return value
1507 *    >= 0  O.K.
1508 *     < 0  Error
1509 */
1510 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
1511   int r;
1512 
1513   INIT();
1514   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1515     SEGGER_RTT_LOCK();
1516     _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1517     SEGGER_RTT_UNLOCK();
1518     r =  0;
1519   } else {
1520     r = -1;
1521   }
1522   return r;
1523 }
1524 
1525 /*********************************************************************
1526 *
1527 *       SEGGER_RTT_SetFlagsUpBuffer
1528 *
1529 *  Function description
1530 *    Run-time configuration of specific up-buffer flags (T->H).
1531 *    Buffer to be configured is specified by index.
1532 *
1533 *  Parameters
1534 *    BufferIndex  Index of the buffer.
1535 *    Flags        Flags to set for the buffer.
1536 *
1537 *  Return value
1538 *    >= 0  O.K.
1539 *     < 0  Error
1540 */
1541 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
1542   int r;
1543 
1544   INIT();
1545   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1546     SEGGER_RTT_LOCK();
1547     _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1548     SEGGER_RTT_UNLOCK();
1549     r =  0;
1550   } else {
1551     r = -1;
1552   }
1553   return r;
1554 }
1555 
1556 /*********************************************************************
1557 *
1558 *       SEGGER_RTT_SetFlagsDownBuffer
1559 *
1560 *  Function description
1561 *    Run-time configuration of specific Down-buffer flags (T->H).
1562 *    Buffer to be configured is specified by index.
1563 *
1564 *  Parameters
1565 *    BufferIndex  Index of the buffer to renamed.
1566 *    Flags        Flags to set for the buffer.
1567 *
1568 *  Return value
1569 *    >= 0  O.K.
1570 *     < 0  Error
1571 */
1572 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
1573   int r;
1574 
1575   INIT();
1576   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1577     SEGGER_RTT_LOCK();
1578     _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1579     SEGGER_RTT_UNLOCK();
1580     r =  0;
1581   } else {
1582     r = -1;
1583   }
1584   return r;
1585 }
1586 
1587 /*********************************************************************
1588 *
1589 *       SEGGER_RTT_Init
1590 *
1591 *  Function description
1592 *    Initializes the RTT Control Block.
1593 *    Should be used in RAM targets, at start of the application.
1594 *
1595 */
1596 void SEGGER_RTT_Init (void) {
1597   _DoInit();
1598 }
1599 
1600 /*********************************************************************
1601 *
1602 *       SEGGER_RTT_SetTerminal
1603 *
1604 *  Function description
1605 *    Sets the terminal to be used for output on channel 0.
1606 *
1607 *  Parameters
1608 *    TerminalId  Index of the terminal.
1609 *
1610 *  Return value
1611 *    >= 0  O.K.
1612 *     < 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)
1613 */
1614 int SEGGER_RTT_SetTerminal (char TerminalId) {
1615   char                  ac[2];
1616   SEGGER_RTT_BUFFER_UP* pRing;
1617   unsigned Avail;
1618   int r;
1619   //
1620   INIT();
1621   //
1622   r = 0;
1623   ac[0] = 0xFFU;
1624   if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1625     ac[1] = _aTerminalId[(unsigned char)TerminalId];
1626     pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
1627     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
1628     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1629       _ActiveTerminal = TerminalId;
1630       _WriteBlocking(pRing, ac, 2u);
1631     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
1632       Avail = _GetAvailWriteSpace(pRing);
1633       if (Avail >= 2) {
1634         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
1635         _WriteNoCheck(pRing, ac, 2u);
1636       } else {
1637         r = -1;
1638       }
1639     }
1640     SEGGER_RTT_UNLOCK();
1641   } else {
1642     r = -1;
1643   }
1644   return r;
1645 }
1646 
1647 /*********************************************************************
1648 *
1649 *       SEGGER_RTT_TerminalOut
1650 *
1651 *  Function description
1652 *    Writes a string to the given terminal
1653 *     without changing the terminal for channel 0.
1654 *
1655 *  Parameters
1656 *    TerminalId   Index of the terminal.
1657 *    s            String to be printed on the terminal.
1658 *
1659 *  Return value
1660 *    >= 0 - Number of bytes written.
1661 *     < 0 - Error.
1662 *
1663 */
1664 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
1665   int                   Status;
1666   unsigned              FragLen;
1667   unsigned              Avail;
1668   SEGGER_RTT_BUFFER_UP* pRing;
1669   //
1670   INIT();
1671   //
1672   // Validate terminal ID.
1673   //
1674   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1675     //
1676     // Get "to-host" ring buffer.
1677     //
1678     pRing = &_SEGGER_RTT.aUp[0];
1679     //
1680     // Need to be able to change terminal, write data, change back.
1681     // Compute the fixed and variable sizes.
1682     //
1683     FragLen = STRLEN(s);
1684     //
1685     // How we output depends upon the mode...
1686     //
1687     SEGGER_RTT_LOCK();
1688     Avail = _GetAvailWriteSpace(pRing);
1689     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1690     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1691       //
1692       // If we are in skip mode and there is no space for the whole
1693       // of this output, don't bother switching terminals at all.
1694       //
1695       if (Avail < (FragLen + 4u)) {
1696         Status = 0;
1697       } else {
1698         _PostTerminalSwitch(pRing, TerminalId);
1699         Status = (int)_WriteBlocking(pRing, s, FragLen);
1700         _PostTerminalSwitch(pRing, _ActiveTerminal);
1701       }
1702       break;
1703     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1704       //
1705       // If we are in trim mode and there is not enough space for everything,
1706       // trim the output but always include the terminal switch.  If no room
1707       // for terminal switch, skip that totally.
1708       //
1709       if (Avail < 4u) {
1710         Status = -1;
1711       } else {
1712         _PostTerminalSwitch(pRing, TerminalId);
1713         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1714         _PostTerminalSwitch(pRing, _ActiveTerminal);
1715       }
1716       break;
1717     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1718       //
1719       // If we are in blocking mode, output everything.
1720       //
1721       _PostTerminalSwitch(pRing, TerminalId);
1722       Status = (int)_WriteBlocking(pRing, s, FragLen);
1723       _PostTerminalSwitch(pRing, _ActiveTerminal);
1724       break;
1725     default:
1726       Status = -1;
1727       break;
1728     }
1729     //
1730     // Finish up.
1731     //
1732     SEGGER_RTT_UNLOCK();
1733   } else {
1734     Status = -1;
1735   }
1736   return Status;
1737 }
1738 
1739 
1740 /*************************** End of file ****************************/
1741