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------------------------------
40File : SEGGER_RTT.c
41Purpose : 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
45Additional 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
124static 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//
135static char _acUpBuffer [BUFFER_SIZE_UP];
136static char _acDownBuffer[BUFFER_SIZE_DOWN];
137//
138// Initialize SEGGER Real-time-Terminal control block (CB)
139//
140SEGGER_RTT_CB _SEGGER_RTT;
141
142static 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)
163static 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*/
218static 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*/
269static 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*/
307static 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*/
329static 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*/
370unsigned 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*/
437unsigned 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*/
478unsigned 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*/
578unsigned 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*/
649unsigned 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*/
688unsigned 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*/
710int 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*/
738int 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*/
761int 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*/
787unsigned 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*/
817int 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*/
860int 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*/
899int 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*/
931int 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*/
956void 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*/
974int 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*/
1025int 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 ****************************/