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