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