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