source: trunk/firmware/SES/Drivers/RTT/SEGGER_RTT.c@ 9

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