Contiki-NG
segger-rtt.c
1 /*********************************************************************
2 * SEGGER MICROCONTROLLER GmbH & Co. KG *
3 * Solutions for real time microcontroller applications *
4 **********************************************************************
5 * *
6 * (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG *
7 * *
8 * www.segger.com Support: support@segger.com *
9 * *
10 **********************************************************************
11 * *
12 * All rights reserved. *
13 * *
14 * * This software may in its unmodified form be freely redistributed *
15 * in source form. *
16 * * The source code may be modified, provided the source code *
17 * retains the above copyright notice, this list of conditions and *
18 * the following disclaimer. *
19 * * Modified versions of this software in source or linkable form *
20 * may not be distributed without prior consent of SEGGER. *
21 * * This software may only be used for communication with SEGGER *
22 * J-Link debug probes. *
23 * *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
28 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
35 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
36 * DAMAGE. *
37 * *
38 **********************************************************************
39 ---------------------------END-OF-HEADER------------------------------
40 File : SEGGER_RTT.c
41 Purpose : Implementation of SEGGER real-time transfer (RTT) which
42  allows real-time communication on targets which support
43  debugger memory accesses while the CPU is running.
44 
45 Additional information:
46  Type "int" is assumed to be 32-bits in size
47  H->T Host to target communication
48  T->H Target to host communication
49 
50  RTT channel 0 is always present and reserved for Terminal usage.
51  Name is fixed to "Terminal"
52 
53 ----------------------------------------------------------------------
54 */
55 
56 #include "segger-rtt.h"
57 
58 #include <string.h> // for memcpy
59 
60 /*********************************************************************
61 *
62 * Configuration, default values
63 *
64 **********************************************************************
65 */
66 
67 #ifndef BUFFER_SIZE_UP
68  #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host
69 #endif
70 
71 #ifndef BUFFER_SIZE_DOWN
72  #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input)
73 #endif
74 
75 #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
76  #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target
77 #endif
78 
79 #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
80  #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target
81 #endif
82 
83 #ifndef SEGGER_RTT_MODE_DEFAULT
84  #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
85 #endif
86 
87 #ifndef SEGGER_RTT_LOCK
88  #define SEGGER_RTT_LOCK(SavedState)
89 #endif
90 
91 #ifndef SEGGER_RTT_UNLOCK
92  #define SEGGER_RTT_UNLOCK(SavedState)
93 #endif
94 
95 #ifndef STRLEN
96  #define STRLEN(a) strlen((a))
97 #endif
98 
99 #ifndef MEMCPY
100  #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
101 #endif
102 
103 #ifndef MIN
104  #define MIN(a, b) (((a) < (b)) ? (a) : (b))
105 #endif
106 
107 #ifndef MAX
108  #define MAX(a, b) (((a) > (b)) ? (a) : (b))
109 #endif
110 //
111 // For some environments, NULL may not be defined until certain headers are included
112 //
113 #ifndef NULL
114  #define NULL 0
115 #endif
116 
117 /*********************************************************************
118 *
119 * Static const data
120 *
121 **********************************************************************
122 */
123 
124 static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
125 
126 /*********************************************************************
127 *
128 * Static data
129 *
130 **********************************************************************
131 */
132 //
133 // Allocate buffers for channel 0
134 //
135 static char _acUpBuffer [BUFFER_SIZE_UP];
136 static char _acDownBuffer[BUFFER_SIZE_DOWN];
137 //
138 // Initialize SEGGER Real-time-Terminal control block (CB)
139 //
140 SEGGER_RTT_CB _SEGGER_RTT;
141 
142 static char _ActiveTerminal;
143 
144 /*********************************************************************
145 *
146 * Static functions
147 *
148 **********************************************************************
149 */
150 
151 /*********************************************************************
152 *
153 * _DoInit()
154 *
155 * Function description
156 * Initializes the control block an buffers.
157 * May only be called via INIT() to avoid overriding settings.
158 *
159 */
160 #define INIT() do { \
161  if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \
162  } while (0)
163 static void _DoInit(void) {
164  SEGGER_RTT_CB* p;
165  //
166  // Initialize control block
167  //
168  p = &_SEGGER_RTT;
169  p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
170  p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
171  //
172  // Initialize up buffer 0
173  //
174  p->aUp[0].sName = "Terminal";
175  p->aUp[0].pBuffer = _acUpBuffer;
176  p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer);
177  p->aUp[0].RdOff = 0u;
178  p->aUp[0].WrOff = 0u;
179  p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
180  //
181  // Initialize down buffer 0
182  //
183  p->aDown[0].sName = "Terminal";
184  p->aDown[0].pBuffer = _acDownBuffer;
185  p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer);
186  p->aDown[0].RdOff = 0u;
187  p->aDown[0].WrOff = 0u;
188  p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
189  //
190  // Finish initialization of the control block.
191  // Copy Id string in three steps to make sure "SEGGER RTT" is not found
192  // in initializer memory (usually flash) by J-Link
193  //
194  strcpy(&p->acID[7], "RTT");
195  strcpy(&p->acID[0], "SEGGER");
196  p->acID[6] = ' ';
197 }
198 
199 /*********************************************************************
200 *
201 * _WriteBlocking()
202 *
203 * Function description
204 * Stores a specified number of characters in SEGGER RTT ring buffer
205 * and updates the associated write pointer which is periodically
206 * read by the host.
207 * The caller is responsible for managing the write chunk sizes as
208 * _WriteBlocking() will block until all data has been posted successfully.
209 *
210 * Parameters
211 * pRing Ring buffer to post to.
212 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
213 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
214 *
215 * Return value
216 * >= 0 - Number of bytes written into buffer.
217 */
218 static unsigned _WriteBlocking(SEGGER_RTT_RING_BUFFER *pRing, const char* pBuffer, unsigned NumBytes) {
219  unsigned NumBytesToWrite;
220  unsigned NumBytesWritten;
221  unsigned RdOff;
222  unsigned WrOff;
223  //
224  // Write data to buffer and handle wrap-around if necessary
225  //
226  NumBytesWritten = 0u;
227  WrOff = pRing->WrOff;
228  do {
229  RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime
230  if (RdOff > WrOff) {
231  NumBytesToWrite = RdOff - WrOff - 1u;
232  } else {
233  NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
234  }
235  NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around
236  NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
237  memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
238  NumBytesWritten += NumBytesToWrite;
239  pBuffer += NumBytesToWrite;
240  NumBytes -= NumBytesToWrite;
241  WrOff += NumBytesToWrite;
242  if (WrOff == pRing->SizeOfBuffer) {
243  WrOff = 0u;
244  }
245  pRing->WrOff = WrOff;
246  } while (NumBytes);
247  //
248  return NumBytesWritten;
249 }
250 
251 /*********************************************************************
252 *
253 * _WriteNoCheck()
254 *
255 * Function description
256 * Stores a specified number of characters in SEGGER RTT ring buffer
257 * and updates the associated write pointer which is periodically
258 * read by the host.
259 * It is callers responsibility to make sure data actually fits in buffer.
260 *
261 * Parameters
262 * pRing Ring buffer to post to.
263 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
264 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
265 *
266 * Notes
267 * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
268 */
269 static void _WriteNoCheck(SEGGER_RTT_RING_BUFFER *pRing, const char* pData, unsigned NumBytes) {
270  unsigned NumBytesAtOnce;
271  unsigned WrOff;
272  unsigned Rem;
273 
274  WrOff = pRing->WrOff;
275  Rem = pRing->SizeOfBuffer - WrOff;
276  if (Rem > NumBytes) {
277  //
278  // All data fits before wrap around
279  //
280  memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
281  pRing->WrOff = WrOff + NumBytes;
282  } else {
283  //
284  // We reach the end of the buffer, so need to wrap around
285  //
286  NumBytesAtOnce = Rem;
287  memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
288  NumBytesAtOnce = NumBytes - Rem;
289  memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
290  pRing->WrOff = NumBytesAtOnce;
291  }
292 }
293 
294 /*********************************************************************
295 *
296 * _PostTerminalSwitch()
297 *
298 * Function description
299 * Switch terminal to the given terminal ID. It is the caller's
300 * responsibility to ensure the terminal ID is correct and there is
301 * enough space in the buffer for this to complete successfully.
302 *
303 * Parameters
304 * pRing Ring buffer to post to.
305 * TerminalId Terminal ID to switch to.
306 */
307 static void _PostTerminalSwitch(SEGGER_RTT_RING_BUFFER *pRing, char TerminalId) {
308  char ac[2];
309 
310  ac[0] = 0xFFu;
311  ac[1] = _aTerminalId[(int)TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
312  _WriteBlocking(pRing, ac, 2u);
313 }
314 
315 /*********************************************************************
316 *
317 * _GetAvailWriteSpace()
318 *
319 * Function description
320 * Returns the number of bytes that can be written to the ring
321 * buffer without blocking.
322 *
323 * Parameters
324 * pRing Ring buffer to check.
325 *
326 * Return value
327 * Number of bytes that are free in the buffer.
328 */
329 static unsigned _GetAvailWriteSpace(SEGGER_RTT_RING_BUFFER *pRing) {
330  unsigned RdOff;
331  unsigned WrOff;
332  unsigned r;
333  //
334  // Avoid warnings regarding volatile access order. It's not a problem
335  // in this case, but dampen compiler enthusiasm.
336  //
337  RdOff = pRing->RdOff;
338  WrOff = pRing->WrOff;
339  if (RdOff <= WrOff) {
340  r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
341  } else {
342  r = RdOff - WrOff - 1u;
343  }
344  return r;
345 }
346 
347 /*********************************************************************
348 *
349 * Public code
350 *
351 **********************************************************************
352 */
353 /*********************************************************************
354 *
355 * SEGGER_RTT_ReadNoLock()
356 *
357 * Function description
358 * Reads characters from SEGGER real-time-terminal control block
359 * which have been previously stored by the host.
360 * Do not lock against interrupts and multiple access.
361 *
362 * Parameters
363 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
364 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
365 * BufferSize Size of the target application buffer.
366 *
367 * Return value
368 * Number of bytes that have been read.
369 */
370 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
371  unsigned NumBytesRem;
372  unsigned NumBytesRead;
373  unsigned RdOff;
374  unsigned WrOff;
375  unsigned char* pBuffer;
376  SEGGER_RTT_RING_BUFFER* pRing;
377  //
378  INIT();
379  pRing = &_SEGGER_RTT.aDown[BufferIndex];
380  pBuffer = (unsigned char*)pData;
381  RdOff = pRing->RdOff;
382  WrOff = pRing->WrOff;
383  NumBytesRead = 0u;
384  //
385  // Read from current read position to wrap-around of buffer, first
386  //
387  if (RdOff > WrOff) {
388  NumBytesRem = pRing->SizeOfBuffer - RdOff;
389  NumBytesRem = MIN(NumBytesRem, BufferSize);
390  memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
391  NumBytesRead += NumBytesRem;
392  pBuffer += NumBytesRem;
393  BufferSize -= NumBytesRem;
394  RdOff += NumBytesRem;
395  //
396  // Handle wrap-around of buffer
397  //
398  if (RdOff == pRing->SizeOfBuffer) {
399  RdOff = 0u;
400  }
401  }
402  //
403  // Read remaining items of buffer
404  //
405  NumBytesRem = WrOff - RdOff;
406  NumBytesRem = MIN(NumBytesRem, BufferSize);
407  if (NumBytesRem > 0u) {
408  memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
409  NumBytesRead += NumBytesRem;
410  pBuffer += NumBytesRem;
411  BufferSize -= NumBytesRem;
412  RdOff += NumBytesRem;
413  }
414  if (NumBytesRead) {
415  pRing->RdOff = RdOff;
416  }
417  //
418  return NumBytesRead;
419 }
420 
421 /*********************************************************************
422 *
423 * SEGGER_RTT_Read
424 *
425 * Function description
426 * Reads characters from SEGGER real-time-terminal control block
427 * which have been previously stored by the host.
428 *
429 * Parameters
430 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
431 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
432 * BufferSize Size of the target application buffer.
433 *
434 * Return value
435 * Number of bytes that have been read.
436 */
437 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
438  unsigned NumBytesRead;
439  volatile unsigned SavedState;
440  //
441  SEGGER_RTT_LOCK(SavedState);
442  //
443  // Call the non-locking read function
444  //
445  NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
446  //
447  // Finish up.
448  //
449  SEGGER_RTT_UNLOCK(SavedState);
450  //
451  return NumBytesRead;
452 }
453 
454 /*********************************************************************
455 *
456 * SEGGER_RTT_WriteSkipNoLock
457 *
458 * Function description
459 * Stores a specified number of characters in SEGGER RTT
460 * control block which is then read by the host.
461 * SEGGER_RTT_WriteSkipNoLock does not lock the application and
462 * skips all data, if the data does not fit into the buffer.
463 *
464 * Parameters
465 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
466 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
467 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
468 *
469 * Return value
470 * Number of bytes which have been stored in the "Up"-buffer.
471 *
472 * Notes
473 * (1) If there is not enough space in the "Up"-buffer, all data is dropped.
474 * (2) For performance reasons this function does not call Init()
475 * and may only be called after RTT has been initialized.
476 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
477 */
478 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
479  const char* pData;
480  SEGGER_RTT_RING_BUFFER* pRing;
481  unsigned Avail;
482  unsigned RdOff;
483  unsigned WrOff;
484  unsigned Rem;
485 
486  pData = (const char *)pBuffer;
487  //
488  // Get "to-host" ring buffer and copy some elements into local variables.
489  //
490  pRing = &_SEGGER_RTT.aUp[BufferIndex];
491  RdOff = pRing->RdOff;
492  WrOff = pRing->WrOff;
493  //
494  // Handle the most common cases fastest.
495  // Which is:
496  // RdOff <= WrOff -> Space until wrap around is free.
497  // AND
498  // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary.
499  //
500  // OR
501  //
502  // RdOff > WrOff -> Space until RdOff - 1 is free.
503  // AND
504  // WrOff + NumBytes < RdOff -> Data fits into buffer
505  //
506  if (RdOff <= WrOff) {
507  //
508  // Get space until WrOff will be at wrap around.
509  //
510  Avail = pRing->SizeOfBuffer - 1u - WrOff ;
511  if (Avail >= NumBytes) {
512  memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
513  pRing->WrOff = WrOff + NumBytes;
514  return 1;
515  }
516  //
517  // If data did not fit into space until wrap around calculate complete space in buffer.
518  //
519  Avail += RdOff;
520  //
521  // If there is still no space for the whole of this output, don't bother.
522  //
523  if (Avail >= NumBytes) {
524  //
525  // OK, we have enough space in buffer. Copy in one or 2 chunks
526  //
527  Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
528  if (Rem > NumBytes) {
529  memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
530  pRing->WrOff = WrOff + NumBytes;
531  } else {
532  //
533  // We reach the end of the buffer, so need to wrap around
534  //
535  memcpy(pRing->pBuffer + WrOff, pData, Rem);
536  memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
537  pRing->WrOff = NumBytes - Rem;
538  }
539  return 1;
540  }
541  } else {
542  Avail = RdOff - WrOff - 1u;
543  if (Avail >= NumBytes) {
544  memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
545  pRing->WrOff = WrOff + NumBytes;
546  return 1;
547  }
548  }
549  //
550  // If we reach this point no data has been written
551  //
552  return 0;
553 }
554 
555 /*********************************************************************
556 *
557 * SEGGER_RTT_WriteNoLock
558 *
559 * Function description
560 * Stores a specified number of characters in SEGGER RTT
561 * control block which is then read by the host.
562 * SEGGER_RTT_WriteNoLock does not lock the application.
563 *
564 * Parameters
565 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
566 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
567 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
568 *
569 * Return value
570 * Number of bytes which have been stored in the "Up"-buffer.
571 *
572 * Notes
573 * (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
574 * (2) For performance reasons this function does not call Init()
575 * and may only be called after RTT has been initialized.
576 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
577 */
578 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
579  unsigned Status;
580  unsigned Avail;
581  const char* pData;
582  SEGGER_RTT_RING_BUFFER *pRing;
583 
584  pData = (const char *)pBuffer;
585  //
586  // Get "to-host" ring buffer.
587  //
588  pRing = &_SEGGER_RTT.aUp[BufferIndex];
589  //
590  // How we output depends upon the mode...
591  //
592  switch (pRing->Flags) {
593  case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
594  //
595  // If we are in skip mode and there is no space for the whole
596  // of this output, don't bother.
597  //
598  Avail = _GetAvailWriteSpace(pRing);
599  if (Avail < NumBytes) {
600  Status = 0u;
601  } else {
602  Status = NumBytes;
603  _WriteNoCheck(pRing, pData, NumBytes);
604  }
605  break;
606  case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
607  //
608  // If we are in trim mode, trim to what we can output without blocking.
609  //
610  Avail = _GetAvailWriteSpace(pRing);
611  Status = Avail < NumBytes ? Avail : NumBytes;
612  _WriteNoCheck(pRing, pData, Status);
613  break;
614  case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
615  //
616  // If we are in blocking mode, output everything.
617  //
618  Status = _WriteBlocking(pRing, pData, NumBytes);
619  break;
620  default:
621  Status = 0u;
622  break;
623  }
624  //
625  // Finish up.
626  //
627  return Status;
628 }
629 
630 /*********************************************************************
631 *
632 * SEGGER_RTT_Write
633 *
634 * Function description
635 * Stores a specified number of characters in SEGGER RTT
636 * control block which is then read by the host.
637 *
638 * Parameters
639 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
640 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
641 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
642 *
643 * Return value
644 * Number of bytes which have been stored in the "Up"-buffer.
645 *
646 * Notes
647 * (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
648 */
649 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
650  unsigned Status;
651  volatile unsigned SavedState;
652  //
653  INIT();
654  SEGGER_RTT_LOCK(SavedState);
655  //
656  // Call the non-locking write function
657  //
658  Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
659  //
660  // Finish up.
661  //
662  SEGGER_RTT_UNLOCK(SavedState);
663  //
664  return Status;
665 }
666 
667 /*********************************************************************
668 *
669 * SEGGER_RTT_WriteString
670 *
671 * Function description
672 * Stores string in SEGGER RTT control block.
673 * This data is read by the host.
674 *
675 * Parameters
676 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
677 * s Pointer to string.
678 *
679 * Return value
680 * Number of bytes which have been stored in the "Up"-buffer.
681 *
682 * Notes
683 * (1) If there is not enough space in the "Up"-buffer, depending on configuration,
684 * remaining characters may be dropped or RTT module waits until there is more space in the buffer.
685 * (2) String passed to this function has to be \0 terminated
686 * (3) \0 termination character is *not* stored in RTT buffer
687 */
688 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
689  unsigned Len;
690 
691  Len = STRLEN(s);
692  return SEGGER_RTT_Write(BufferIndex, s, Len);
693 }
694 
695 /*********************************************************************
696 *
697 * SEGGER_RTT_GetKey
698 *
699 * Function description
700 * Reads one character from the SEGGER RTT buffer.
701 * Host has previously stored data there.
702 *
703 * Return value
704 * < 0 - No character available (buffer empty).
705 * >= 0 - Character which has been read. (Possible values: 0 - 255)
706 *
707 * Notes
708 * (1) This function is only specified for accesses to RTT buffer 0.
709 */
710 int SEGGER_RTT_GetKey(void) {
711  char c;
712  int r;
713 
714  r = (int)SEGGER_RTT_Read(0u, &c, 1u);
715  if (r == 1) {
716  r = (int)(unsigned char)c;
717  } else {
718  r = -1;
719  }
720  return r;
721 }
722 
723 /*********************************************************************
724 *
725 * SEGGER_RTT_WaitKey
726 *
727 * Function description
728 * Waits until at least one character is avaible in the SEGGER RTT buffer.
729 * Once a character is available, it is read and this function returns.
730 *
731 * Return value
732 * >=0 - Character which has been read.
733 *
734 * Notes
735 * (1) This function is only specified for accesses to RTT buffer 0
736 * (2) This function is blocking if no character is present in RTT buffer
737 */
738 int SEGGER_RTT_WaitKey(void) {
739  int r;
740 
741  do {
742  r = SEGGER_RTT_GetKey();
743  } while (r < 0);
744  return r;
745 }
746 
747 /*********************************************************************
748 *
749 * SEGGER_RTT_HasKey
750 *
751 * Function description
752 * Checks if at least one character for reading is available in the SEGGER RTT buffer.
753 *
754 * Return value
755 * == 0 - No characters are available to read.
756 * == 1 - At least one character is available.
757 *
758 * Notes
759 * (1) This function is only specified for accesses to RTT buffer 0
760 */
761 int SEGGER_RTT_HasKey(void) {
762  unsigned RdOff;
763  int r;
764 
765  INIT();
766  RdOff = _SEGGER_RTT.aDown[0].RdOff;
767  if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
768  r = 1;
769  } else {
770  r = 0;
771  }
772  return r;
773 }
774 
775 /*********************************************************************
776 *
777 * SEGGER_RTT_HasData
778 *
779 * Function description
780 * Check if there is data from the host in the given buffer.
781 *
782 * Return value:
783 * ==0: No data
784 * !=0: Data in buffer
785 *
786 */
787 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
788  SEGGER_RTT_RING_BUFFER *pRing;
789  unsigned v;
790 
791  pRing = &_SEGGER_RTT.aDown[BufferIndex];
792  v = pRing->WrOff;
793  return v - pRing->RdOff;
794 }
795 
796 
797 /*********************************************************************
798 *
799 * SEGGER_RTT_ConfigUpBuffer
800 *
801 * Function description
802 * Run-time configuration of a specific up-buffer (T->H).
803 * Buffer to be configured is specified by index.
804 * This includes: Buffer address, size, name, flags, ...
805 *
806 * Parameters
807 * BufferIndex Index of the buffer to configure.
808 * sName Pointer to a constant name string.
809 * pBuffer Pointer to a buffer to be used.
810 * BufferSize Size of the buffer.
811 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
812 *
813 * Return value
814 * >= 0 - O.K.
815 * < 0 - Error
816 */
817 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
818  int r;
819  volatile unsigned SavedState;
820 
821  INIT();
822  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
823  SEGGER_RTT_LOCK(SavedState);
824  if (BufferIndex > 0u) {
825  _SEGGER_RTT.aUp[BufferIndex].sName = sName;
826  _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer;
827  _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
828  _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
829  _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
830  }
831  _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
832  SEGGER_RTT_UNLOCK(SavedState);
833  r = 0;
834  } else {
835  r = -1;
836  }
837  return r;
838 }
839 
840 /*********************************************************************
841 *
842 * SEGGER_RTT_ConfigDownBuffer
843 *
844 * Function description
845 * Run-time configuration of a specific down-buffer (H->T).
846 * Buffer to be configured is specified by index.
847 * This includes: Buffer address, size, name, flags, ...
848 *
849 * Parameters
850 * BufferIndex Index of the buffer to configure.
851 * sName Pointer to a constant name string.
852 * pBuffer Pointer to a buffer to be used.
853 * BufferSize Size of the buffer.
854 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
855 *
856 * Return value
857 * >= 0 O.K.
858 * < 0 Error
859 */
860 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
861  int r;
862  volatile unsigned SavedState;
863 
864  INIT();
865  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
866  SEGGER_RTT_LOCK(SavedState);
867  if (BufferIndex > 0u) {
868  _SEGGER_RTT.aDown[BufferIndex].sName = sName;
869  _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer;
870  _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
871  _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
872  _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
873  }
874  _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
875  SEGGER_RTT_UNLOCK(SavedState);
876  r = 0;
877  } else {
878  r = -1;
879  }
880  return r;
881 }
882 
883 /*********************************************************************
884 *
885 * SEGGER_RTT_SetNameUpBuffer
886 *
887 * Function description
888 * Run-time configuration of a specific up-buffer name (T->H).
889 * Buffer to be configured is specified by index.
890 *
891 * Parameters
892 * BufferIndex Index of the buffer to renamed.
893 * sName Pointer to a constant name string.
894 *
895 * Return value
896 * >= 0 O.K.
897 * < 0 Error
898 */
899 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
900  int r;
901  volatile unsigned SavedState;
902 
903  INIT();
904  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
905  SEGGER_RTT_LOCK(SavedState);
906  _SEGGER_RTT.aUp[BufferIndex].sName = sName;
907  SEGGER_RTT_UNLOCK(SavedState);
908  r = 0;
909  } else {
910  r = -1;
911  }
912  return r;
913 }
914 
915 /*********************************************************************
916 *
917 * SEGGER_RTT_SetNameDownBuffer
918 *
919 * Function description
920 * Run-time configuration of a specific Down-buffer name (T->H).
921 * Buffer to be configured is specified by index.
922 *
923 * Parameters
924 * BufferIndex Index of the buffer to renamed.
925 * sName Pointer to a constant name string.
926 *
927 * Return value
928 * >= 0 O.K.
929 * < 0 Error
930 */
931 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
932  int r;
933  volatile unsigned SavedState;
934 
935  INIT();
936  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
937  SEGGER_RTT_LOCK(SavedState);
938  _SEGGER_RTT.aDown[BufferIndex].sName = sName;
939  SEGGER_RTT_UNLOCK(SavedState);
940  r = 0;
941  } else {
942  r = -1;
943  }
944  return r;
945 }
946 
947 /*********************************************************************
948 *
949 * SEGGER_RTT_Init
950 *
951 * Function description
952 * Initializes the RTT Control Block.
953 * Should be used in RAM targets, at start of the application.
954 *
955 */
956 void SEGGER_RTT_Init (void) {
957  INIT();
958 }
959 
960 /*********************************************************************
961 *
962 * SEGGER_RTT_SetTerminal
963 *
964 * Function description
965 * Sets the terminal to be used for output on channel 0.
966 *
967 * Parameters
968 * TerminalId Index of the terminal.
969 *
970 * Return value
971 * >= 0 O.K.
972 * < 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)
973 */
974 int SEGGER_RTT_SetTerminal (char TerminalId) {
975  char ac[2];
976  SEGGER_RTT_RING_BUFFER *pRing;
977  volatile unsigned SavedState;
978  unsigned Avail;
979  int r;
980  //
981  INIT();
982  //
983  r = 0;
984  ac[0] = 0xFFU;
985  if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
986  ac[1] = _aTerminalId[(int)TerminalId];
987  pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
988  SEGGER_RTT_LOCK(SavedState); // 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
989  if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
990  _ActiveTerminal = TerminalId;
991  _WriteBlocking(pRing, ac, 2u);
992  } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
993  Avail = _GetAvailWriteSpace(pRing);
994  if (Avail >= 2) {
995  _ActiveTerminal = TerminalId; // Only change active terminal in case of success
996  _WriteNoCheck(pRing, ac, 2u);
997  } else {
998  r = -1;
999  }
1000  }
1001  SEGGER_RTT_UNLOCK(SavedState);
1002  } else {
1003  r = -1;
1004  }
1005  return r;
1006 }
1007 
1008 /*********************************************************************
1009 *
1010 * SEGGER_RTT_TerminalOut
1011 *
1012 * Function description
1013 * Writes a string to the given terminal
1014 * without changing the terminal for channel 0.
1015 *
1016 * Parameters
1017 * TerminalId Index of the terminal.
1018 * s String to be printed on the terminal.
1019 *
1020 * Return value
1021 * >= 0 - Number of bytes written.
1022 * < 0 - Error.
1023 *
1024 */
1025 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
1026  int Status;
1027  unsigned FragLen;
1028  unsigned Avail;
1029  SEGGER_RTT_RING_BUFFER *pRing;
1030  volatile unsigned SavedState;
1031  //
1032  INIT();
1033  //
1034  // Validate terminal ID.
1035  //
1036  if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1037  //
1038  // Get "to-host" ring buffer.
1039  //
1040  pRing = &_SEGGER_RTT.aUp[0];
1041  //
1042  // Need to be able to change terminal, write data, change back.
1043  // Compute the fixed and variable sizes.
1044  //
1045  FragLen = strlen(s);
1046  //
1047  // How we output depends upon the mode...
1048  //
1049  SEGGER_RTT_LOCK(SavedState);
1050  Avail = _GetAvailWriteSpace(pRing);
1051  switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1052  case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1053  //
1054  // If we are in skip mode and there is no space for the whole
1055  // of this output, don't bother switching terminals at all.
1056  //
1057  if (Avail < (FragLen + 4u)) {
1058  Status = 0;
1059  } else {
1060  _PostTerminalSwitch(pRing, TerminalId);
1061  Status = (int)_WriteBlocking(pRing, s, FragLen);
1062  _PostTerminalSwitch(pRing, _ActiveTerminal);
1063  }
1064  break;
1065  case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1066  //
1067  // If we are in trim mode and there is not enough space for everything,
1068  // trim the output but always include the terminal switch. If no room
1069  // for terminal switch, skip that totally.
1070  //
1071  if (Avail < 4u) {
1072  Status = -1;
1073  } else {
1074  _PostTerminalSwitch(pRing, TerminalId);
1075  Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1076  _PostTerminalSwitch(pRing, _ActiveTerminal);
1077  }
1078  break;
1079  case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1080  //
1081  // If we are in blocking mode, output everything.
1082  //
1083  _PostTerminalSwitch(pRing, TerminalId);
1084  Status = (int)_WriteBlocking(pRing, s, FragLen);
1085  _PostTerminalSwitch(pRing, _ActiveTerminal);
1086  break;
1087  default:
1088  Status = -1;
1089  break;
1090  }
1091  //
1092  // Finish up.
1093  //
1094  SEGGER_RTT_UNLOCK(SavedState);
1095  } else {
1096  Status = -1;
1097  }
1098  return Status;
1099 }
1100 
1101 
1102 /*************************** End of file ****************************/