xref: /btstack/3rd-party/segger-rtt/SEGGER_RTT.c (revision d58a1b5f11ada8ddf896c41fff5a35e7f140c37e)
1 /*********************************************************************
2 *                    SEGGER Microcontroller GmbH                     *
3 *                        The Embedded Experts                        *
4 **********************************************************************
5 *                                                                    *
6 *            (c) 1995 - 2019 SEGGER Microcontroller GmbH             *
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                  *
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: 14765 $
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 unsigned 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   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 */
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 *                 MUST be > 0!!!
738 *                 This is done for performance reasons, so no initial check has do be done.
739 *
740 *  Return value
741 *    1: Data has been copied
742 *    0: No space, data has not been copied
743 *
744 *  Notes
745 *    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
746 *    (2) For performance reasons this function does not call Init()
747 *        and may only be called after RTT has been initialized.
748 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
749 */
750 #if (RTT_USE_ASM == 0)
751 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
752   const char*           pData;
753   SEGGER_RTT_BUFFER_UP* pRing;
754   unsigned              Avail;
755   unsigned              RdOff;
756   unsigned              WrOff;
757   unsigned              Rem;
758   //
759   // Cases:
760   //   1) RdOff <= WrOff => Space until wrap-around is sufficient
761   //   2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
762   //   3) RdOff <  WrOff => No space in buf
763   //   4) RdOff >  WrOff => Space is sufficient
764   //   5) RdOff >  WrOff => No space in buf
765   //
766   // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
767   //
768   pData = (const char *)pBuffer;
769   pRing = &_SEGGER_RTT.aUp[BufferIndex];
770   RdOff = pRing->RdOff;
771   WrOff = pRing->WrOff;
772   if (RdOff <= WrOff) {                                 // Case 1), 2) or 3)
773     Avail = pRing->SizeOfBuffer - WrOff - 1u;           // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
774     if (Avail >= NumBytes) {                            // Case 1)?
775 CopyStraight:
776       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
777       pRing->WrOff = WrOff + NumBytes;
778       return 1;
779     }
780     Avail += RdOff;                                     // Space incl. wrap-around
781     if (Avail >= NumBytes) {                            // Case 2? => If not, we have case 3) (does not fit)
782       Rem = pRing->SizeOfBuffer - WrOff;                // Space until end of buffer
783       memcpy(pRing->pBuffer + WrOff, pData, Rem);       // Copy 1st chunk
784       NumBytes -= Rem;
785       //
786       // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
787       // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
788       // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
789       // Therefore, check if 2nd memcpy is necessary at all
790       //
791       if (NumBytes) {
792         memcpy(pRing->pBuffer, pData + Rem, NumBytes);
793       }
794       pRing->WrOff = NumBytes;
795       return 1;
796     }
797   } else {                                             // Potential case 4)
798     Avail = RdOff - WrOff - 1u;
799     if (Avail >= NumBytes) {                           // Case 4)? => If not, we have case 5) (does not fit)
800       goto CopyStraight;
801     }
802   }
803   return 0;     // No space in buffer
804 }
805 #endif
806 
807 /*********************************************************************
808 *
809 *       SEGGER_RTT_WriteNoLock
810 *
811 *  Function description
812 *    Stores a specified number of characters in SEGGER RTT
813 *    control block which is then read by the host.
814 *    SEGGER_RTT_WriteNoLock does not lock the application.
815 *
816 *  Parameters
817 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
818 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
819 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
820 *
821 *  Return value
822 *    Number of bytes which have been stored in the "Up"-buffer.
823 *
824 *  Notes
825 *    (1) Data is stored according to buffer flags.
826 *    (2) For performance reasons this function does not call Init()
827 *        and may only be called after RTT has been initialized.
828 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
829 */
830 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
831   unsigned              Status;
832   unsigned              Avail;
833   const char*           pData;
834   SEGGER_RTT_BUFFER_UP* pRing;
835 
836   pData = (const char *)pBuffer;
837   //
838   // Get "to-host" ring buffer.
839   //
840   pRing = &_SEGGER_RTT.aUp[BufferIndex];
841   //
842   // How we output depends upon the mode...
843   //
844   switch (pRing->Flags) {
845   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
846     //
847     // If we are in skip mode and there is no space for the whole
848     // of this output, don't bother.
849     //
850     Avail = _GetAvailWriteSpace(pRing);
851     if (Avail < NumBytes) {
852       Status = 0u;
853     } else {
854       Status = NumBytes;
855       _WriteNoCheck(pRing, pData, NumBytes);
856     }
857     break;
858   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
859     //
860     // If we are in trim mode, trim to what we can output without blocking.
861     //
862     Avail = _GetAvailWriteSpace(pRing);
863     Status = Avail < NumBytes ? Avail : NumBytes;
864     _WriteNoCheck(pRing, pData, Status);
865     break;
866   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
867     //
868     // If we are in blocking mode, output everything.
869     //
870     Status = _WriteBlocking(pRing, pData, NumBytes);
871     break;
872   default:
873     Status = 0u;
874     break;
875   }
876   //
877   // Finish up.
878   //
879   return Status;
880 }
881 
882 /*********************************************************************
883 *
884 *       SEGGER_RTT_Write
885 *
886 *  Function description
887 *    Stores a specified number of characters in SEGGER RTT
888 *    control block which is then read by the host.
889 *
890 *  Parameters
891 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
892 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
893 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
894 *
895 *  Return value
896 *    Number of bytes which have been stored in the "Up"-buffer.
897 *
898 *  Notes
899 *    (1) Data is stored according to buffer flags.
900 */
901 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
902   unsigned Status;
903   //
904   INIT();
905   SEGGER_RTT_LOCK();
906   //
907   // Call the non-locking write function
908   //
909   Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
910   //
911   // Finish up.
912   //
913   SEGGER_RTT_UNLOCK();
914   //
915   return Status;
916 }
917 
918 /*********************************************************************
919 *
920 *       SEGGER_RTT_WriteString
921 *
922 *  Function description
923 *    Stores string in SEGGER RTT control block.
924 *    This data is read by the host.
925 *
926 *  Parameters
927 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
928 *    s            Pointer to string.
929 *
930 *  Return value
931 *    Number of bytes which have been stored in the "Up"-buffer.
932 *
933 *  Notes
934 *    (1) Data is stored according to buffer flags.
935 *    (2) String passed to this function has to be \0 terminated
936 *    (3) \0 termination character is *not* stored in RTT buffer
937 */
938 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
939   unsigned Len;
940 
941   Len = STRLEN(s);
942   return SEGGER_RTT_Write(BufferIndex, s, Len);
943 }
944 
945 /*********************************************************************
946 *
947 *       SEGGER_RTT_PutCharSkipNoLock
948 *
949 *  Function description
950 *    Stores a single character/byte in SEGGER RTT buffer.
951 *    SEGGER_RTT_PutCharSkipNoLock does not lock the application and
952 *    skips the byte, if it does not fit into the buffer.
953 *
954 *  Parameters
955 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
956 *    c            Byte to be stored.
957 *
958 *  Return value
959 *    Number of bytes which have been stored in the "Up"-buffer.
960 *
961 *  Notes
962 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
963 *    (2) For performance reasons this function does not call Init()
964 *        and may only be called after RTT has been initialized.
965 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
966 */
967 
968 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
969   SEGGER_RTT_BUFFER_UP* pRing;
970   unsigned              WrOff;
971   unsigned              Status;
972   //
973   // Get "to-host" ring buffer.
974   //
975   pRing = &_SEGGER_RTT.aUp[BufferIndex];
976   //
977   // Get write position and handle wrap-around if necessary
978   //
979   WrOff = pRing->WrOff + 1;
980   if (WrOff == pRing->SizeOfBuffer) {
981     WrOff = 0;
982   }
983   //
984   // Output byte if free space is available
985   //
986   if (WrOff != pRing->RdOff) {
987     pRing->pBuffer[pRing->WrOff] = c;
988     pRing->WrOff = WrOff;
989     Status = 1;
990   } else {
991     Status = 0;
992   }
993   //
994   return Status;
995 }
996 
997 /*********************************************************************
998 *
999 *       SEGGER_RTT_PutCharSkip
1000 *
1001 *  Function description
1002 *    Stores a single character/byte in SEGGER RTT buffer.
1003 *
1004 *  Parameters
1005 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1006 *    c            Byte to be stored.
1007 *
1008 *  Return value
1009 *    Number of bytes which have been stored in the "Up"-buffer.
1010 *
1011 *  Notes
1012 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
1013 */
1014 
1015 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
1016   SEGGER_RTT_BUFFER_UP* pRing;
1017   unsigned              WrOff;
1018   unsigned              Status;
1019   //
1020   // Prepare
1021   //
1022   INIT();
1023   SEGGER_RTT_LOCK();
1024   //
1025   // Get "to-host" ring buffer.
1026   //
1027   pRing = &_SEGGER_RTT.aUp[BufferIndex];
1028   //
1029   // Get write position and handle wrap-around if necessary
1030   //
1031   WrOff = pRing->WrOff + 1;
1032   if (WrOff == pRing->SizeOfBuffer) {
1033     WrOff = 0;
1034   }
1035   //
1036   // Output byte if free space is available
1037   //
1038   if (WrOff != pRing->RdOff) {
1039     pRing->pBuffer[pRing->WrOff] = c;
1040     pRing->WrOff = WrOff;
1041     Status = 1;
1042   } else {
1043     Status = 0;
1044   }
1045   //
1046   // Finish up.
1047   //
1048   SEGGER_RTT_UNLOCK();
1049   //
1050   return Status;
1051 }
1052 
1053  /*********************************************************************
1054 *
1055 *       SEGGER_RTT_PutChar
1056 *
1057 *  Function description
1058 *    Stores a single character/byte in SEGGER RTT buffer.
1059 *
1060 *  Parameters
1061 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1062 *    c            Byte to be stored.
1063 *
1064 *  Return value
1065 *    Number of bytes which have been stored in the "Up"-buffer.
1066 *
1067 *  Notes
1068 *    (1) Data is stored according to buffer flags.
1069 */
1070 
1071 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
1072   SEGGER_RTT_BUFFER_UP* pRing;
1073   unsigned              WrOff;
1074   unsigned              Status;
1075   //
1076   // Prepare
1077   //
1078   INIT();
1079   SEGGER_RTT_LOCK();
1080   //
1081   // Get "to-host" ring buffer.
1082   //
1083   pRing = &_SEGGER_RTT.aUp[BufferIndex];
1084   //
1085   // Get write position and handle wrap-around if necessary
1086   //
1087   WrOff = pRing->WrOff + 1;
1088   if (WrOff == pRing->SizeOfBuffer) {
1089     WrOff = 0;
1090   }
1091   //
1092   // Wait for free space if mode is set to blocking
1093   //
1094   if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1095     while (WrOff == pRing->RdOff) {
1096       ;
1097     }
1098   }
1099   //
1100   // Output byte if free space is available
1101   //
1102   if (WrOff != pRing->RdOff) {
1103     pRing->pBuffer[pRing->WrOff] = c;
1104     pRing->WrOff = WrOff;
1105     Status = 1;
1106   } else {
1107     Status = 0;
1108   }
1109   //
1110   // Finish up.
1111   //
1112   SEGGER_RTT_UNLOCK();
1113   //
1114   return Status;
1115 }
1116 
1117 /*********************************************************************
1118 *
1119 *       SEGGER_RTT_GetKey
1120 *
1121 *  Function description
1122 *    Reads one character from the SEGGER RTT buffer.
1123 *    Host has previously stored data there.
1124 *
1125 *  Return value
1126 *    <  0 -   No character available (buffer empty).
1127 *    >= 0 -   Character which has been read. (Possible values: 0 - 255)
1128 *
1129 *  Notes
1130 *    (1) This function is only specified for accesses to RTT buffer 0.
1131 */
1132 int SEGGER_RTT_GetKey(void) {
1133   char c;
1134   int r;
1135 
1136   r = (int)SEGGER_RTT_Read(0u, &c, 1u);
1137   if (r == 1) {
1138     r = (int)(unsigned char)c;
1139   } else {
1140     r = -1;
1141   }
1142   return r;
1143 }
1144 
1145 /*********************************************************************
1146 *
1147 *       SEGGER_RTT_WaitKey
1148 *
1149 *  Function description
1150 *    Waits until at least one character is avaible in the SEGGER RTT buffer.
1151 *    Once a character is available, it is read and this function returns.
1152 *
1153 *  Return value
1154 *    >=0 -   Character which has been read.
1155 *
1156 *  Notes
1157 *    (1) This function is only specified for accesses to RTT buffer 0
1158 *    (2) This function is blocking if no character is present in RTT buffer
1159 */
1160 int SEGGER_RTT_WaitKey(void) {
1161   int r;
1162 
1163   do {
1164     r = SEGGER_RTT_GetKey();
1165   } while (r < 0);
1166   return r;
1167 }
1168 
1169 /*********************************************************************
1170 *
1171 *       SEGGER_RTT_HasKey
1172 *
1173 *  Function description
1174 *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
1175 *
1176 *  Return value
1177 *    == 0 -     No characters are available to read.
1178 *    == 1 -     At least one character is available.
1179 *
1180 *  Notes
1181 *    (1) This function is only specified for accesses to RTT buffer 0
1182 */
1183 int SEGGER_RTT_HasKey(void) {
1184   unsigned RdOff;
1185   int r;
1186 
1187   INIT();
1188   RdOff = _SEGGER_RTT.aDown[0].RdOff;
1189   if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
1190     r = 1;
1191   } else {
1192     r = 0;
1193   }
1194   return r;
1195 }
1196 
1197 /*********************************************************************
1198 *
1199 *       SEGGER_RTT_HasData
1200 *
1201 *  Function description
1202 *    Check if there is data from the host in the given buffer.
1203 *
1204 *  Return value:
1205 *  ==0:  No data
1206 *  !=0:  Data in buffer
1207 *
1208 */
1209 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
1210   SEGGER_RTT_BUFFER_DOWN* pRing;
1211   unsigned                v;
1212 
1213   pRing = &_SEGGER_RTT.aDown[BufferIndex];
1214   v = pRing->WrOff;
1215   return v - pRing->RdOff;
1216 }
1217 
1218 /*********************************************************************
1219 *
1220 *       SEGGER_RTT_HasDataUp
1221 *
1222 *  Function description
1223 *    Check if there is data remaining to be sent in the given buffer.
1224 *
1225 *  Return value:
1226 *  ==0:  No data
1227 *  !=0:  Data in buffer
1228 *
1229 */
1230 unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
1231   SEGGER_RTT_BUFFER_UP* pRing;
1232   unsigned                v;
1233 
1234   pRing = &_SEGGER_RTT.aUp[BufferIndex];
1235   v = pRing->RdOff;
1236   return pRing->WrOff - v;
1237 }
1238 
1239 /*********************************************************************
1240 *
1241 *       SEGGER_RTT_AllocDownBuffer
1242 *
1243 *  Function description
1244 *    Run-time configuration of the next down-buffer (H->T).
1245 *    The next buffer, which is not used yet is configured.
1246 *    This includes: Buffer address, size, name, flags, ...
1247 *
1248 *  Parameters
1249 *    sName        Pointer to a constant name string.
1250 *    pBuffer      Pointer to a buffer to be used.
1251 *    BufferSize   Size of the buffer.
1252 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1253 *
1254 *  Return value
1255 *    >= 0 - O.K. Buffer Index
1256 *     < 0 - Error
1257 */
1258 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1259   int BufferIndex;
1260 
1261   INIT();
1262   SEGGER_RTT_LOCK();
1263   BufferIndex = 0;
1264   do {
1265     if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
1266       break;
1267     }
1268     BufferIndex++;
1269   } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
1270   if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
1271     _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
1272     _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
1273     _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1274     _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
1275     _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
1276     _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
1277   } else {
1278     BufferIndex = -1;
1279   }
1280   SEGGER_RTT_UNLOCK();
1281   return BufferIndex;
1282 }
1283 
1284 /*********************************************************************
1285 *
1286 *       SEGGER_RTT_AllocUpBuffer
1287 *
1288 *  Function description
1289 *    Run-time configuration of the next up-buffer (T->H).
1290 *    The next buffer, which is not used yet is configured.
1291 *    This includes: Buffer address, size, name, flags, ...
1292 *
1293 *  Parameters
1294 *    sName        Pointer to a constant name string.
1295 *    pBuffer      Pointer to a buffer to be used.
1296 *    BufferSize   Size of the buffer.
1297 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1298 *
1299 *  Return value
1300 *    >= 0 - O.K. Buffer Index
1301 *     < 0 - Error
1302 */
1303 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1304   int BufferIndex;
1305 
1306   INIT();
1307   SEGGER_RTT_LOCK();
1308   BufferIndex = 0;
1309   do {
1310     if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
1311       break;
1312     }
1313     BufferIndex++;
1314   } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
1315   if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
1316     _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
1317     _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
1318     _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1319     _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
1320     _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
1321     _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
1322   } else {
1323     BufferIndex = -1;
1324   }
1325   SEGGER_RTT_UNLOCK();
1326   return BufferIndex;
1327 }
1328 
1329 /*********************************************************************
1330 *
1331 *       SEGGER_RTT_ConfigUpBuffer
1332 *
1333 *  Function description
1334 *    Run-time configuration of a specific up-buffer (T->H).
1335 *    Buffer to be configured is specified by index.
1336 *    This includes: Buffer address, size, name, flags, ...
1337 *
1338 *  Parameters
1339 *    BufferIndex  Index of the buffer to configure.
1340 *    sName        Pointer to a constant name string.
1341 *    pBuffer      Pointer to a buffer to be used.
1342 *    BufferSize   Size of the buffer.
1343 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1344 *
1345 *  Return value
1346 *    >= 0 - O.K.
1347 *     < 0 - Error
1348 *
1349 *  Additional information
1350 *    Buffer 0 is configured on compile-time.
1351 *    May only be called once per buffer.
1352 *    Buffer name and flags can be reconfigured using the appropriate functions.
1353 */
1354 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1355   int r;
1356 
1357   INIT();
1358   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1359     SEGGER_RTT_LOCK();
1360     if (BufferIndex > 0u) {
1361       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
1362       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
1363       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1364       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
1365       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
1366     }
1367     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
1368     SEGGER_RTT_UNLOCK();
1369     r =  0;
1370   } else {
1371     r = -1;
1372   }
1373   return r;
1374 }
1375 
1376 /*********************************************************************
1377 *
1378 *       SEGGER_RTT_ConfigDownBuffer
1379 *
1380 *  Function description
1381 *    Run-time configuration of a specific down-buffer (H->T).
1382 *    Buffer to be configured is specified by index.
1383 *    This includes: Buffer address, size, name, flags, ...
1384 *
1385 *  Parameters
1386 *    BufferIndex  Index of the buffer to configure.
1387 *    sName        Pointer to a constant name string.
1388 *    pBuffer      Pointer to a buffer to be used.
1389 *    BufferSize   Size of the buffer.
1390 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
1391 *
1392 *  Return value
1393 *    >= 0  O.K.
1394 *     < 0  Error
1395 *
1396 *  Additional information
1397 *    Buffer 0 is configured on compile-time.
1398 *    May only be called once per buffer.
1399 *    Buffer name and flags can be reconfigured using the appropriate functions.
1400 */
1401 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1402   int r;
1403 
1404   INIT();
1405   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1406     SEGGER_RTT_LOCK();
1407     if (BufferIndex > 0u) {
1408       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
1409       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
1410       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1411       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
1412       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
1413     }
1414     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
1415     SEGGER_RTT_UNLOCK();
1416     r =  0;
1417   } else {
1418     r = -1;
1419   }
1420   return r;
1421 }
1422 
1423 /*********************************************************************
1424 *
1425 *       SEGGER_RTT_SetNameUpBuffer
1426 *
1427 *  Function description
1428 *    Run-time configuration of a specific up-buffer name (T->H).
1429 *    Buffer to be configured is specified by index.
1430 *
1431 *  Parameters
1432 *    BufferIndex  Index of the buffer to renamed.
1433 *    sName        Pointer to a constant name string.
1434 *
1435 *  Return value
1436 *    >= 0  O.K.
1437 *     < 0  Error
1438 */
1439 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
1440   int r;
1441 
1442   INIT();
1443   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1444     SEGGER_RTT_LOCK();
1445     _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1446     SEGGER_RTT_UNLOCK();
1447     r =  0;
1448   } else {
1449     r = -1;
1450   }
1451   return r;
1452 }
1453 
1454 /*********************************************************************
1455 *
1456 *       SEGGER_RTT_SetNameDownBuffer
1457 *
1458 *  Function description
1459 *    Run-time configuration of a specific Down-buffer name (T->H).
1460 *    Buffer to be configured is specified by index.
1461 *
1462 *  Parameters
1463 *    BufferIndex  Index of the buffer to renamed.
1464 *    sName        Pointer to a constant name string.
1465 *
1466 *  Return value
1467 *    >= 0  O.K.
1468 *     < 0  Error
1469 */
1470 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
1471   int r;
1472 
1473   INIT();
1474   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1475     SEGGER_RTT_LOCK();
1476     _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1477     SEGGER_RTT_UNLOCK();
1478     r =  0;
1479   } else {
1480     r = -1;
1481   }
1482   return r;
1483 }
1484 
1485 /*********************************************************************
1486 *
1487 *       SEGGER_RTT_SetFlagsUpBuffer
1488 *
1489 *  Function description
1490 *    Run-time configuration of specific up-buffer flags (T->H).
1491 *    Buffer to be configured is specified by index.
1492 *
1493 *  Parameters
1494 *    BufferIndex  Index of the buffer.
1495 *    Flags        Flags to set for the buffer.
1496 *
1497 *  Return value
1498 *    >= 0  O.K.
1499 *     < 0  Error
1500 */
1501 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
1502   int r;
1503 
1504   INIT();
1505   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1506     SEGGER_RTT_LOCK();
1507     _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1508     SEGGER_RTT_UNLOCK();
1509     r =  0;
1510   } else {
1511     r = -1;
1512   }
1513   return r;
1514 }
1515 
1516 /*********************************************************************
1517 *
1518 *       SEGGER_RTT_SetFlagsDownBuffer
1519 *
1520 *  Function description
1521 *    Run-time configuration of specific Down-buffer flags (T->H).
1522 *    Buffer to be configured is specified by index.
1523 *
1524 *  Parameters
1525 *    BufferIndex  Index of the buffer to renamed.
1526 *    Flags        Flags to set for the buffer.
1527 *
1528 *  Return value
1529 *    >= 0  O.K.
1530 *     < 0  Error
1531 */
1532 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
1533   int r;
1534 
1535   INIT();
1536   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1537     SEGGER_RTT_LOCK();
1538     _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1539     SEGGER_RTT_UNLOCK();
1540     r =  0;
1541   } else {
1542     r = -1;
1543   }
1544   return r;
1545 }
1546 
1547 /*********************************************************************
1548 *
1549 *       SEGGER_RTT_Init
1550 *
1551 *  Function description
1552 *    Initializes the RTT Control Block.
1553 *    Should be used in RAM targets, at start of the application.
1554 *
1555 */
1556 void SEGGER_RTT_Init (void) {
1557   _DoInit();
1558 }
1559 
1560 /*********************************************************************
1561 *
1562 *       SEGGER_RTT_SetTerminal
1563 *
1564 *  Function description
1565 *    Sets the terminal to be used for output on channel 0.
1566 *
1567 *  Parameters
1568 *    TerminalId  Index of the terminal.
1569 *
1570 *  Return value
1571 *    >= 0  O.K.
1572 *     < 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)
1573 */
1574 int SEGGER_RTT_SetTerminal (unsigned char TerminalId) {
1575   unsigned char         ac[2];
1576   SEGGER_RTT_BUFFER_UP* pRing;
1577   unsigned Avail;
1578   int r;
1579   //
1580   INIT();
1581   //
1582   r = 0;
1583   ac[0] = 0xFFu;
1584   if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels
1585     ac[1] = _aTerminalId[TerminalId];
1586     pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
1587     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
1588     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1589       _ActiveTerminal = TerminalId;
1590       _WriteBlocking(pRing, (const char*)ac, 2u);
1591     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
1592       Avail = _GetAvailWriteSpace(pRing);
1593       if (Avail >= 2) {
1594         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
1595         _WriteNoCheck(pRing, (const char*)ac, 2u);
1596       } else {
1597         r = -1;
1598       }
1599     }
1600     SEGGER_RTT_UNLOCK();
1601   } else {
1602     r = -1;
1603   }
1604   return r;
1605 }
1606 
1607 /*********************************************************************
1608 *
1609 *       SEGGER_RTT_TerminalOut
1610 *
1611 *  Function description
1612 *    Writes a string to the given terminal
1613 *     without changing the terminal for channel 0.
1614 *
1615 *  Parameters
1616 *    TerminalId   Index of the terminal.
1617 *    s            String to be printed on the terminal.
1618 *
1619 *  Return value
1620 *    >= 0 - Number of bytes written.
1621 *     < 0 - Error.
1622 *
1623 */
1624 int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) {
1625   int                   Status;
1626   unsigned              FragLen;
1627   unsigned              Avail;
1628   SEGGER_RTT_BUFFER_UP* pRing;
1629   //
1630   INIT();
1631   //
1632   // Validate terminal ID.
1633   //
1634   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1635     //
1636     // Get "to-host" ring buffer.
1637     //
1638     pRing = &_SEGGER_RTT.aUp[0];
1639     //
1640     // Need to be able to change terminal, write data, change back.
1641     // Compute the fixed and variable sizes.
1642     //
1643     FragLen = STRLEN(s);
1644     //
1645     // How we output depends upon the mode...
1646     //
1647     SEGGER_RTT_LOCK();
1648     Avail = _GetAvailWriteSpace(pRing);
1649     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1650     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1651       //
1652       // If we are in skip mode and there is no space for the whole
1653       // of this output, don't bother switching terminals at all.
1654       //
1655       if (Avail < (FragLen + 4u)) {
1656         Status = 0;
1657       } else {
1658         _PostTerminalSwitch(pRing, TerminalId);
1659         Status = (int)_WriteBlocking(pRing, s, FragLen);
1660         _PostTerminalSwitch(pRing, _ActiveTerminal);
1661       }
1662       break;
1663     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1664       //
1665       // If we are in trim mode and there is not enough space for everything,
1666       // trim the output but always include the terminal switch.  If no room
1667       // for terminal switch, skip that totally.
1668       //
1669       if (Avail < 4u) {
1670         Status = -1;
1671       } else {
1672         _PostTerminalSwitch(pRing, TerminalId);
1673         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1674         _PostTerminalSwitch(pRing, _ActiveTerminal);
1675       }
1676       break;
1677     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1678       //
1679       // If we are in blocking mode, output everything.
1680       //
1681       _PostTerminalSwitch(pRing, TerminalId);
1682       Status = (int)_WriteBlocking(pRing, s, FragLen);
1683       _PostTerminalSwitch(pRing, _ActiveTerminal);
1684       break;
1685     default:
1686       Status = -1;
1687       break;
1688     }
1689     //
1690     // Finish up.
1691     //
1692     SEGGER_RTT_UNLOCK();
1693   } else {
1694     Status = -1;
1695   }
1696   return Status;
1697 }
1698 
1699 /*********************************************************************
1700 *
1701 *       SEGGER_RTT_GetAvailWriteSpace
1702 *    Returns the number of bytes that can be written to the ring
1703 *    buffer without blocking.
1704 *
1705 *  Parameters
1706 *    BufferIndex  Index of the buffer.
1707 *
1708 *  Return value
1709 *    Number of bytes that are free in the buffer.
1710 */
1711 
1712 unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){
1713   return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]);
1714 }
1715 
1716 
1717 /*************************** End of file ****************************/
1718