1 /*********************************************************************
2 * SEGGER Microcontroller GmbH *
3 * The Embedded Experts *
4 **********************************************************************
5 * *
6 * (c) 1995 - 2021 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 * condition is met: *
25 * *
26 * o Redistributions of source code must retain the above copyright *
27 * notice, this condition and the following disclaimer. *
28 * *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
33 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
34 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
40 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
41 * DAMAGE. *
42 * *
43 **********************************************************************
44 * *
45 * RTT version: 7.22 *
46 * *
47 **********************************************************************
48
49 ---------------------------END-OF-HEADER------------------------------
50 File : SEGGER_RTT.c
51 Purpose : Implementation of SEGGER real-time transfer (RTT) which
52 allows real-time communication on targets which support
53 debugger memory accesses while the CPU is running.
54 Revision: $Rev: 22333 $
55
56 Additional information:
57 Type "int" is assumed to be 32-bits in size
58 H->T Host to target communication
59 T->H Target to host communication
60
61 RTT channel 0 is always present and reserved for Terminal usage.
62 Name is fixed to "Terminal"
63
64 Effective buffer size: SizeOfBuffer - 1
65
66 WrOff == RdOff: Buffer is empty
67 WrOff == (RdOff - 1): Buffer is full
68 WrOff > RdOff: Free space includes wrap-around
69 WrOff < RdOff: Used space includes wrap-around
70 (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):
71 Buffer full and wrap-around after next byte
72
73
74 ----------------------------------------------------------------------
75 */
76
77 #include "SEGGER_RTT.h"
78
79 #include <string.h> // for memcpy
80
81 /*
82 * For CMSIS pack RTE.
83 * CMSIS pack RTE generates "RTC_Components.h" which contains the statements
84 * of the related <RTE_Components_h> element for all selected software components.
85 */
86 #ifdef _RTE_
87 #include "RTE_Components.h"
88 #endif
89
90 /*********************************************************************
91 *
92 * Configuration, default values
93 *
94 **********************************************************************
95 */
96
97 #if SEGGER_RTT_CPU_CACHE_LINE_SIZE
98 #ifdef SEGGER_RTT_CB_ALIGN
99 #error "Custom SEGGER_RTT_CB_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
100 #endif
101 #ifdef SEGGER_RTT_BUFFER_ALIGN
102 #error "Custom SEGGER_RTT_BUFFER_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
103 #endif
104 #ifdef SEGGER_RTT_PUT_CB_SECTION
105 #error "Custom SEGGER_RTT_PUT_CB_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
106 #endif
107 #ifdef SEGGER_RTT_PUT_BUFFER_SECTION
108 #error "Custom SEGGER_RTT_PUT_BUFFER_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
109 #endif
110 #ifdef SEGGER_RTT_BUFFER_ALIGNMENT
111 #error "Custom SEGGER_RTT_BUFFER_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
112 #endif
113 #ifdef SEGGER_RTT_ALIGNMENT
114 #error "Custom SEGGER_RTT_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
115 #endif
116 #endif
117
118 #ifndef BUFFER_SIZE_UP
119 #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host
120 #endif
121
122 #ifndef BUFFER_SIZE_DOWN
123 #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input)
124 #endif
125
126 #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
127 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target
128 #endif
129
130 #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
131 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target
132 #endif
133
134 #ifndef SEGGER_RTT_BUFFER_SECTION
135 #if defined(SEGGER_RTT_SECTION)
136 #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
137 #endif
138 #endif
139
140 #ifndef SEGGER_RTT_ALIGNMENT
141 #define SEGGER_RTT_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE
142 #endif
143
144 #ifndef SEGGER_RTT_BUFFER_ALIGNMENT
145 #define SEGGER_RTT_BUFFER_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE
146 #endif
147
148 #ifndef SEGGER_RTT_MODE_DEFAULT
149 #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
150 #endif
151
152 #ifndef SEGGER_RTT_LOCK
153 #define SEGGER_RTT_LOCK()
154 #endif
155
156 #ifndef SEGGER_RTT_UNLOCK
157 #define SEGGER_RTT_UNLOCK()
158 #endif
159
160 #ifndef STRLEN
161 #define STRLEN(a) strlen((a))
162 #endif
163
164 #ifndef STRCPY
165 #define STRCPY(pDest, pSrc) strcpy((pDest), (pSrc))
166 #endif
167
168 #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
169 #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0
170 #endif
171
172 #ifndef SEGGER_RTT_MEMCPY
173 #ifdef MEMCPY
174 #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes))
175 #else
176 #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
177 #endif
178 #endif
179
180 #ifndef MIN
181 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
182 #endif
183
184 #ifndef MAX
185 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
186 #endif
187 //
188 // For some environments, NULL may not be defined until certain headers are included
189 //
190 #ifndef NULL
191 #define NULL 0
192 #endif
193
194 /*********************************************************************
195 *
196 * Defines, fixed
197 *
198 **********************************************************************
199 */
200 #if (defined __ICCARM__) || (defined __ICCRX__)
201 #define RTT_PRAGMA(P) _Pragma(#P)
202 #endif
203
204 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
205 #if (defined __GNUC__)
206 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__((aligned(Alignment)))
207 #elif (defined __ICCARM__) || (defined __ICCRX__)
208 #define PRAGMA(A) _Pragma(#A)
209 #define SEGGER_RTT_ALIGN(Var, Alignment) \
210 RTT_PRAGMA(data_alignment = Alignment) \
211 Var
212 #elif (defined __CC_ARM)
213 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__((aligned(Alignment)))
214 #else
215 #error "Alignment not supported for this compiler."
216 #endif
217 #else
218 #define SEGGER_RTT_ALIGN(Var, Alignment) Var
219 #endif
220
221 #if defined(SEGGER_RTT_SECTION) || defined(SEGGER_RTT_BUFFER_SECTION)
222 #if (defined __GNUC__)
223 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__((section(Section))) Var
224 #elif (defined __ICCARM__) || (defined __ICCRX__)
225 #define SEGGER_RTT_PUT_SECTION(Var, Section) \
226 RTT_PRAGMA(location = Section) \
227 Var
228 #elif (defined __CC_ARM)
229 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__((section(Section), zero_init)) Var
230 #else
231 #error "Section placement not supported for this compiler."
232 #endif
233 #else
234 #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
235 #endif
236
237 #if SEGGER_RTT_ALIGNMENT
238 #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
239 #else
240 #define SEGGER_RTT_CB_ALIGN(Var) Var
241 #endif
242
243 #if SEGGER_RTT_BUFFER_ALIGNMENT
244 #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
245 #else
246 #define SEGGER_RTT_BUFFER_ALIGN(Var) Var
247 #endif
248
249 #if defined(SEGGER_RTT_SECTION)
250 #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
251 #else
252 #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
253 #endif
254
255 #if defined(SEGGER_RTT_BUFFER_SECTION)
256 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
257 #else
258 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
259 #endif
260
261 /*********************************************************************
262 *
263 * Static const data
264 *
265 **********************************************************************
266 */
267
268 static unsigned char _aTerminalId[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
269 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
270
271 /*********************************************************************
272 *
273 * Static data
274 *
275 **********************************************************************
276 */
277
278 //
279 // RTT Control Block and allocate buffers for channel 0
280 //
281 SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
282 SEGGER_RTT_PUT_BUFFER_SECTION(
283 SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)]));
284 SEGGER_RTT_PUT_BUFFER_SECTION(
285 SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)]));
286
287 static unsigned char _ActiveTerminal;
288
289 /*********************************************************************
290 *
291 * Static functions
292 *
293 **********************************************************************
294 */
295
296 /*********************************************************************
297 *
298 * _DoInit()
299 *
300 * Function description
301 * Initializes the control block an buffers.
302 * May only be called via INIT() to avoid overriding settings.
303 *
304 */
305 #define INIT() \
306 { \
307 volatile SEGGER_RTT_CB *pRTTCBInit; \
308 pRTTCBInit = (volatile SEGGER_RTT_CB *)((char *)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \
309 do \
310 { \
311 if (pRTTCBInit->acID[0] == '\0') \
312 { \
313 _DoInit(); \
314 } \
315 } while (0); \
316 }
317
_DoInit(void)318 static void _DoInit(void)
319 {
320 volatile SEGGER_RTT_CB
321 *p; // Volatile to make sure that compiler cannot change the order of accesses to the control block
322 //
323 // Initialize control block
324 //
325 p = (volatile SEGGER_RTT_CB
326 *)((char *)&_SEGGER_RTT +
327 SEGGER_RTT_UNCACHED_OFF); // Access control block uncached so that nothing in the cache ever becomes
328 // dirty and all changes are visible in HW directly
329 p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
330 p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
331 //
332 // Initialize up buffer 0
333 //
334 p->aUp[0].sName = "Terminal";
335 p->aUp[0].pBuffer = _acUpBuffer;
336 p->aUp[0].SizeOfBuffer = BUFFER_SIZE_UP;
337 p->aUp[0].RdOff = 0u;
338 p->aUp[0].WrOff = 0u;
339 p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
340 //
341 // Initialize down buffer 0
342 //
343 p->aDown[0].sName = "Terminal";
344 p->aDown[0].pBuffer = _acDownBuffer;
345 p->aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN;
346 p->aDown[0].RdOff = 0u;
347 p->aDown[0].WrOff = 0u;
348 p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
349 //
350 // Finish initialization of the control block.
351 // Copy Id string in three steps to make sure "SEGGER RTT" is not found
352 // in initializer memory (usually flash) by J-Link
353 //
354 STRCPY((char *)&p->acID[7], "RTT");
355 RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
356 STRCPY((char *)&p->acID[0], "SEGGER");
357 RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
358 p->acID[6] = ' ';
359 RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
360 }
361
362 /*********************************************************************
363 *
364 * _WriteBlocking()
365 *
366 * Function description
367 * Stores a specified number of characters in SEGGER RTT ring buffer
368 * and updates the associated write pointer which is periodically
369 * read by the host.
370 * The caller is responsible for managing the write chunk sizes as
371 * _WriteBlocking() will block until all data has been posted successfully.
372 *
373 * Parameters
374 * pRing Ring buffer to post to.
375 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
376 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
377 *
378 * Return value
379 * >= 0 - Number of bytes written into buffer.
380 */
_WriteBlocking(SEGGER_RTT_BUFFER_UP * pRing,const char * pBuffer,unsigned NumBytes)381 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP *pRing, const char *pBuffer, unsigned NumBytes)
382 {
383 unsigned NumBytesToWrite;
384 unsigned NumBytesWritten;
385 unsigned RdOff;
386 unsigned WrOff;
387 volatile char *pDst;
388 //
389 // Write data to buffer and handle wrap-around if necessary
390 //
391 NumBytesWritten = 0u;
392 WrOff = pRing->WrOff;
393 do
394 {
395 RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime
396 if (RdOff > WrOff)
397 {
398 NumBytesToWrite = RdOff - WrOff - 1u;
399 }
400 else
401 {
402 NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
403 }
404 NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer -
405 WrOff)); // Number of bytes that can be written until buffer wrap-around
406 NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
407 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
408 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
409 NumBytesWritten += NumBytesToWrite;
410 NumBytes -= NumBytesToWrite;
411 WrOff += NumBytesToWrite;
412 while (NumBytesToWrite--)
413 {
414 *pDst++ = *pBuffer++;
415 };
416 #else
417 SEGGER_RTT_MEMCPY((void *)pDst, pBuffer, NumBytesToWrite);
418 NumBytesWritten += NumBytesToWrite;
419 pBuffer += NumBytesToWrite;
420 NumBytes -= NumBytesToWrite;
421 WrOff += NumBytesToWrite;
422 #endif
423 if (WrOff == pRing->SizeOfBuffer)
424 {
425 WrOff = 0u;
426 }
427 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
428 // order of memory accesses
429 pRing->WrOff = WrOff;
430 } while (NumBytes);
431 return NumBytesWritten;
432 }
433
434 /*********************************************************************
435 *
436 * _WriteNoCheck()
437 *
438 * Function description
439 * Stores a specified number of characters in SEGGER RTT ring buffer
440 * and updates the associated write pointer which is periodically
441 * read by the host.
442 * It is callers responsibility to make sure data actually fits in buffer.
443 *
444 * Parameters
445 * pRing Ring buffer to post to.
446 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
447 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
448 *
449 * Notes
450 * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
451 */
_WriteNoCheck(SEGGER_RTT_BUFFER_UP * pRing,const char * pData,unsigned NumBytes)452 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP *pRing, const char *pData, unsigned NumBytes)
453 {
454 unsigned NumBytesAtOnce;
455 unsigned WrOff;
456 unsigned Rem;
457 volatile char *pDst;
458
459 WrOff = pRing->WrOff;
460 Rem = pRing->SizeOfBuffer - WrOff;
461 if (Rem > NumBytes)
462 {
463 //
464 // All data fits before wrap around
465 //
466 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
467 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
468 WrOff += NumBytes;
469 while (NumBytes--)
470 {
471 *pDst++ = *pData++;
472 };
473 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
474 // order of memory accesses
475 pRing->WrOff = WrOff;
476 #else
477 SEGGER_RTT_MEMCPY((void *)pDst, pData, NumBytes);
478 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
479 // order of memory accesses
480 pRing->WrOff = WrOff + NumBytes;
481 #endif
482 }
483 else
484 {
485 //
486 // We reach the end of the buffer, so need to wrap around
487 //
488 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
489 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
490 NumBytesAtOnce = Rem;
491 while (NumBytesAtOnce--)
492 {
493 *pDst++ = *pData++;
494 };
495 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
496 NumBytesAtOnce = NumBytes - Rem;
497 while (NumBytesAtOnce--)
498 {
499 *pDst++ = *pData++;
500 };
501 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
502 // order of memory accesses
503 pRing->WrOff = NumBytes - Rem;
504 #else
505 NumBytesAtOnce = Rem;
506 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
507 SEGGER_RTT_MEMCPY((void *)pDst, pData, NumBytesAtOnce);
508 NumBytesAtOnce = NumBytes - Rem;
509 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
510 SEGGER_RTT_MEMCPY((void *)pDst, pData + Rem, NumBytesAtOnce);
511 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
512 // order of memory accesses
513 pRing->WrOff = NumBytesAtOnce;
514 #endif
515 }
516 }
517
518 /*********************************************************************
519 *
520 * _PostTerminalSwitch()
521 *
522 * Function description
523 * Switch terminal to the given terminal ID. It is the caller's
524 * responsibility to ensure the terminal ID is correct and there is
525 * enough space in the buffer for this to complete successfully.
526 *
527 * Parameters
528 * pRing Ring buffer to post to.
529 * TerminalId Terminal ID to switch to.
530 */
_PostTerminalSwitch(SEGGER_RTT_BUFFER_UP * pRing,unsigned char TerminalId)531 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP *pRing, unsigned char TerminalId)
532 {
533 unsigned char ac[2];
534
535 ac[0] = 0xFFu;
536 ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
537 _WriteBlocking(pRing, (const char *)ac, 2u);
538 }
539
540 /*********************************************************************
541 *
542 * _GetAvailWriteSpace()
543 *
544 * Function description
545 * Returns the number of bytes that can be written to the ring
546 * buffer without blocking.
547 *
548 * Parameters
549 * pRing Ring buffer to check.
550 *
551 * Return value
552 * Number of bytes that are free in the buffer.
553 */
_GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP * pRing)554 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP *pRing)
555 {
556 unsigned RdOff;
557 unsigned WrOff;
558 unsigned r;
559 //
560 // Avoid warnings regarding volatile access order. It's not a problem
561 // in this case, but dampen compiler enthusiasm.
562 //
563 RdOff = pRing->RdOff;
564 WrOff = pRing->WrOff;
565 if (RdOff <= WrOff)
566 {
567 r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
568 }
569 else
570 {
571 r = RdOff - WrOff - 1u;
572 }
573 return r;
574 }
575
576 /*********************************************************************
577 *
578 * Public code
579 *
580 **********************************************************************
581 */
582
583 /*********************************************************************
584 *
585 * SEGGER_RTT_ReadUpBufferNoLock()
586 *
587 * Function description
588 * Reads characters from SEGGER real-time-terminal control block
589 * which have been previously stored by the application.
590 * Do not lock against interrupts and multiple access.
591 * Used to do the same operation that J-Link does, to transfer
592 * RTT data via other channels, such as TCP/IP or UART.
593 *
594 * Parameters
595 * BufferIndex Index of Up-buffer to be used.
596 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
597 * BufferSize Size of the target application buffer.
598 *
599 * Return value
600 * Number of bytes that have been read.
601 *
602 * Additional information
603 * This function must not be called when J-Link might also do RTT.
604 */
SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)605 unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void *pData, unsigned BufferSize)
606 {
607 unsigned NumBytesRem;
608 unsigned NumBytesRead;
609 unsigned RdOff;
610 unsigned WrOff;
611 unsigned char *pBuffer;
612 SEGGER_RTT_BUFFER_UP *pRing;
613 volatile char *pSrc;
614
615 INIT();
616 pRing =
617 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
618 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
619 // J-Link side and all of our changes go into HW directly
620 pBuffer = (unsigned char *)pData;
621 RdOff = pRing->RdOff;
622 WrOff = pRing->WrOff;
623 NumBytesRead = 0u;
624 //
625 // Read from current read position to wrap-around of buffer, first
626 //
627 if (RdOff > WrOff)
628 {
629 NumBytesRem = pRing->SizeOfBuffer - RdOff;
630 NumBytesRem = MIN(NumBytesRem, BufferSize);
631 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
632 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
633 NumBytesRead += NumBytesRem;
634 BufferSize -= NumBytesRem;
635 RdOff += NumBytesRem;
636 while (NumBytesRem--)
637 {
638 *pBuffer++ = *pSrc++;
639 };
640 #else
641 SEGGER_RTT_MEMCPY(pBuffer, (void *)pSrc, NumBytesRem);
642 NumBytesRead += NumBytesRem;
643 pBuffer += NumBytesRem;
644 BufferSize -= NumBytesRem;
645 RdOff += NumBytesRem;
646 #endif
647 //
648 // Handle wrap-around of buffer
649 //
650 if (RdOff == pRing->SizeOfBuffer)
651 {
652 RdOff = 0u;
653 }
654 }
655 //
656 // Read remaining items of buffer
657 //
658 NumBytesRem = WrOff - RdOff;
659 NumBytesRem = MIN(NumBytesRem, BufferSize);
660 if (NumBytesRem > 0u)
661 {
662 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
663 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
664 NumBytesRead += NumBytesRem;
665 BufferSize -= NumBytesRem;
666 RdOff += NumBytesRem;
667 while (NumBytesRem--)
668 {
669 *pBuffer++ = *pSrc++;
670 };
671 #else
672 SEGGER_RTT_MEMCPY(pBuffer, (void *)pSrc, NumBytesRem);
673 NumBytesRead += NumBytesRem;
674 pBuffer += NumBytesRem;
675 BufferSize -= NumBytesRem;
676 RdOff += NumBytesRem;
677 #endif
678 }
679 //
680 // Update read offset of buffer
681 //
682 if (NumBytesRead)
683 {
684 pRing->RdOff = RdOff;
685 }
686 //
687 return NumBytesRead;
688 }
689
690 /*********************************************************************
691 *
692 * SEGGER_RTT_ReadNoLock()
693 *
694 * Function description
695 * Reads characters from SEGGER real-time-terminal control block
696 * which have been previously stored by the host.
697 * Do not lock against interrupts and multiple access.
698 *
699 * Parameters
700 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
701 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
702 * BufferSize Size of the target application buffer.
703 *
704 * Return value
705 * Number of bytes that have been read.
706 */
SEGGER_RTT_ReadNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)707 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void *pData, unsigned BufferSize)
708 {
709 unsigned NumBytesRem;
710 unsigned NumBytesRead;
711 unsigned RdOff;
712 unsigned WrOff;
713 unsigned char *pBuffer;
714 SEGGER_RTT_BUFFER_DOWN *pRing;
715 volatile char *pSrc;
716 //
717 INIT();
718 pRing =
719 (SEGGER_RTT_BUFFER_DOWN *)((char *)&_SEGGER_RTT.aDown[BufferIndex] +
720 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
721 // J-Link side and all of our changes go into HW directly
722 pBuffer = (unsigned char *)pData;
723 RdOff = pRing->RdOff;
724 WrOff = pRing->WrOff;
725 NumBytesRead = 0u;
726 //
727 // Read from current read position to wrap-around of buffer, first
728 //
729 if (RdOff > WrOff)
730 {
731 NumBytesRem = pRing->SizeOfBuffer - RdOff;
732 NumBytesRem = MIN(NumBytesRem, BufferSize);
733 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
734 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
735 NumBytesRead += NumBytesRem;
736 BufferSize -= NumBytesRem;
737 RdOff += NumBytesRem;
738 while (NumBytesRem--)
739 {
740 *pBuffer++ = *pSrc++;
741 };
742 #else
743 SEGGER_RTT_MEMCPY(pBuffer, (void *)pSrc, NumBytesRem);
744 NumBytesRead += NumBytesRem;
745 pBuffer += NumBytesRem;
746 BufferSize -= NumBytesRem;
747 RdOff += NumBytesRem;
748 #endif
749 //
750 // Handle wrap-around of buffer
751 //
752 if (RdOff == pRing->SizeOfBuffer)
753 {
754 RdOff = 0u;
755 }
756 }
757 //
758 // Read remaining items of buffer
759 //
760 NumBytesRem = WrOff - RdOff;
761 NumBytesRem = MIN(NumBytesRem, BufferSize);
762 if (NumBytesRem > 0u)
763 {
764 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF;
765 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
766 NumBytesRead += NumBytesRem;
767 BufferSize -= NumBytesRem;
768 RdOff += NumBytesRem;
769 while (NumBytesRem--)
770 {
771 *pBuffer++ = *pSrc++;
772 };
773 #else
774 SEGGER_RTT_MEMCPY(pBuffer, (void *)pSrc, NumBytesRem);
775 NumBytesRead += NumBytesRem;
776 pBuffer += NumBytesRem;
777 BufferSize -= NumBytesRem;
778 RdOff += NumBytesRem;
779 #endif
780 }
781 if (NumBytesRead)
782 {
783 pRing->RdOff = RdOff;
784 }
785 //
786 return NumBytesRead;
787 }
788
789 /*********************************************************************
790 *
791 * SEGGER_RTT_ReadUpBuffer
792 *
793 * Function description
794 * Reads characters from SEGGER real-time-terminal control block
795 * which have been previously stored by the application.
796 * Used to do the same operation that J-Link does, to transfer
797 * RTT data via other channels, such as TCP/IP or UART.
798 *
799 * Parameters
800 * BufferIndex Index of Up-buffer to be used.
801 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
802 * BufferSize Size of the target application buffer.
803 *
804 * Return value
805 * Number of bytes that have been read.
806 *
807 * Additional information
808 * This function must not be called when J-Link might also do RTT.
809 * This function locks against all other RTT operations. I.e. during
810 * the read operation, writing is also locked.
811 * If only one consumer reads from the up buffer,
812 * call sEGGER_RTT_ReadUpBufferNoLock() instead.
813 */
SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex,void * pBuffer,unsigned BufferSize)814 unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void *pBuffer, unsigned BufferSize)
815 {
816 unsigned NumBytesRead;
817
818 SEGGER_RTT_LOCK();
819 //
820 // Call the non-locking read function
821 //
822 NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize);
823 //
824 // Finish up.
825 //
826 SEGGER_RTT_UNLOCK();
827 //
828 return NumBytesRead;
829 }
830
831 /*********************************************************************
832 *
833 * SEGGER_RTT_Read
834 *
835 * Function description
836 * Reads characters from SEGGER real-time-terminal control block
837 * which have been previously stored by the host.
838 *
839 * Parameters
840 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
841 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
842 * BufferSize Size of the target application buffer.
843 *
844 * Return value
845 * Number of bytes that have been read.
846 */
SEGGER_RTT_Read(unsigned BufferIndex,void * pBuffer,unsigned BufferSize)847 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void *pBuffer, unsigned BufferSize)
848 {
849 unsigned NumBytesRead;
850
851 SEGGER_RTT_LOCK();
852 //
853 // Call the non-locking read function
854 //
855 NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
856 //
857 // Finish up.
858 //
859 SEGGER_RTT_UNLOCK();
860 //
861 return NumBytesRead;
862 }
863
864 /*********************************************************************
865 *
866 * SEGGER_RTT_WriteWithOverwriteNoLock
867 *
868 * Function description
869 * Stores a specified number of characters in SEGGER RTT
870 * control block.
871 * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application
872 * and overwrites data if the data does not fit into the buffer.
873 *
874 * Parameters
875 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
876 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
877 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
878 *
879 * Notes
880 * (1) If there is not enough space in the "Up"-buffer, data is overwritten.
881 * (2) For performance reasons this function does not call Init()
882 * and may only be called after RTT has been initialized.
883 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
884 * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link
885 * connection reads RTT data.
886 */
SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)887 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
888 {
889 const char *pData;
890 SEGGER_RTT_BUFFER_UP *pRing;
891 unsigned Avail;
892 volatile char *pDst;
893 //
894 // Get "to-host" ring buffer and copy some elements into local variables.
895 //
896 pData = (const char *)pBuffer;
897 pRing =
898 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
899 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
900 // J-Link side and all of our changes go into HW directly
901 //
902 // Check if we will overwrite data and need to adjust the RdOff.
903 //
904 if (pRing->WrOff == pRing->RdOff)
905 {
906 Avail = pRing->SizeOfBuffer - 1u;
907 }
908 else if (pRing->WrOff < pRing->RdOff)
909 {
910 Avail = pRing->RdOff - pRing->WrOff - 1u;
911 }
912 else
913 {
914 Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
915 }
916 if (NumBytes > Avail)
917 {
918 pRing->RdOff += (NumBytes - Avail);
919 while (pRing->RdOff >= pRing->SizeOfBuffer)
920 {
921 pRing->RdOff -= pRing->SizeOfBuffer;
922 }
923 }
924 //
925 // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
926 //
927 Avail = pRing->SizeOfBuffer - pRing->WrOff;
928 do
929 {
930 if (Avail > NumBytes)
931 {
932 //
933 // Last round
934 //
935 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
936 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
937 Avail = NumBytes;
938 while (NumBytes--)
939 {
940 *pDst++ = *pData++;
941 };
942 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
943 // the order of memory accesses
944 pRing->WrOff += Avail;
945 #else
946 SEGGER_RTT_MEMCPY((void *)pDst, pData, NumBytes);
947 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
948 // the order of memory accesses
949 pRing->WrOff += NumBytes;
950 #endif
951 break;
952 }
953 else
954 {
955 //
956 // Wrap-around necessary, write until wrap-around and reset WrOff
957 //
958 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
959 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
960 NumBytes -= Avail;
961 while (Avail--)
962 {
963 *pDst++ = *pData++;
964 };
965 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
966 // the order of memory accesses
967 pRing->WrOff = 0;
968 #else
969 SEGGER_RTT_MEMCPY((void *)pDst, pData, Avail);
970 pData += Avail;
971 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
972 // the order of memory accesses
973 pRing->WrOff = 0;
974 NumBytes -= Avail;
975 #endif
976 Avail = (pRing->SizeOfBuffer - 1);
977 }
978 } while (NumBytes);
979 }
980
981 /*********************************************************************
982 *
983 * SEGGER_RTT_WriteSkipNoLock
984 *
985 * Function description
986 * Stores a specified number of characters in SEGGER RTT
987 * control block which is then read by the host.
988 * SEGGER_RTT_WriteSkipNoLock does not lock the application and
989 * skips all data, if the data does not fit into the buffer.
990 *
991 * Parameters
992 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
993 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
994 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
995 * MUST be > 0!!!
996 * This is done for performance reasons, so no initial check has do be done.
997 *
998 * Return value
999 * 1: Data has been copied
1000 * 0: No space, data has not been copied
1001 *
1002 * Notes
1003 * (1) If there is not enough space in the "Up"-buffer, all data is dropped.
1004 * (2) For performance reasons this function does not call Init()
1005 * and may only be called after RTT has been initialized.
1006 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1007 */
1008 #if (RTT_USE_ASM == 0)
SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1009 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
1010 {
1011 const char *pData;
1012 SEGGER_RTT_BUFFER_UP *pRing;
1013 unsigned Avail;
1014 unsigned RdOff;
1015 unsigned WrOff;
1016 unsigned Rem;
1017 volatile char *pDst;
1018 //
1019 // Cases:
1020 // 1) RdOff <= WrOff => Space until wrap-around is sufficient
1021 // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
1022 // 3) RdOff < WrOff => No space in buf
1023 // 4) RdOff > WrOff => Space is sufficient
1024 // 5) RdOff > WrOff => No space in buf
1025 //
1026 // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
1027 //
1028 pData = (const char *)pBuffer;
1029 pRing =
1030 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1031 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1032 // J-Link side and all of our changes go into HW directly
1033 RdOff = pRing->RdOff;
1034 WrOff = pRing->WrOff;
1035 if (RdOff <= WrOff)
1036 { // Case 1), 2) or 3)
1037 Avail = pRing->SizeOfBuffer - WrOff -
1038 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
1039 if (Avail >= NumBytes)
1040 { // Case 1)?
1041 CopyStraight:
1042 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
1043 memcpy((void *)pDst, pData, NumBytes);
1044 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
1045 // the order of memory accesses
1046 pRing->WrOff = WrOff + NumBytes;
1047 return 1;
1048 }
1049 Avail += RdOff; // Space incl. wrap-around
1050 if (Avail >= NumBytes)
1051 { // Case 2? => If not, we have case 3) (does not fit)
1052 Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
1053 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
1054 memcpy((void *)pDst, pData, Rem); // Copy 1st chunk
1055 NumBytes -= Rem;
1056 //
1057 // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could
1058 // not be used But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is
1059 // not 0, so we can use the last element In this case, we may use a copy straight until buffer end anyway
1060 // without needing to copy 2 chunks Therefore, check if 2nd memcpy is necessary at all
1061 //
1062 if (NumBytes)
1063 {
1064 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF;
1065 memcpy((void *)pDst, pData + Rem, NumBytes);
1066 }
1067 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change
1068 // the order of memory accesses
1069 pRing->WrOff = NumBytes;
1070 return 1;
1071 }
1072 }
1073 else
1074 { // Potential case 4)
1075 Avail = RdOff - WrOff - 1u;
1076 if (Avail >= NumBytes)
1077 { // Case 4)? => If not, we have case 5) (does not fit)
1078 goto CopyStraight;
1079 }
1080 }
1081 return 0; // No space in buffer
1082 }
1083 #endif
1084
1085 /*********************************************************************
1086 *
1087 * SEGGER_RTT_WriteDownBufferNoLock
1088 *
1089 * Function description
1090 * Stores a specified number of characters in SEGGER RTT
1091 * control block inside a <Down> buffer.
1092 * SEGGER_RTT_WriteDownBufferNoLock does not lock the application.
1093 * Used to do the same operation that J-Link does, to transfer
1094 * RTT data from other channels, such as TCP/IP or UART.
1095 *
1096 * Parameters
1097 * BufferIndex Index of "Down"-buffer to be used.
1098 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
1099 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
1100 *
1101 * Return value
1102 * Number of bytes which have been stored in the "Down"-buffer.
1103 *
1104 * Notes
1105 * (1) Data is stored according to buffer flags.
1106 * (2) For performance reasons this function does not call Init()
1107 * and may only be called after RTT has been initialized.
1108 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1109 *
1110 * Additional information
1111 * This function must not be called when J-Link might also do RTT.
1112 */
SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1113 unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
1114 {
1115 unsigned Status;
1116 unsigned Avail;
1117 const char *pData;
1118 SEGGER_RTT_BUFFER_UP *pRing;
1119 //
1120 // Get "to-target" ring buffer.
1121 // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be
1122 // modified by J-Link.
1123 //
1124 pData = (const char *)pBuffer;
1125 pRing =
1126 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aDown[BufferIndex] +
1127 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1128 // J-Link side and all of our changes go into HW directly
1129 //
1130 // How we output depends upon the mode...
1131 //
1132 switch (pRing->Flags)
1133 {
1134 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1135 //
1136 // If we are in skip mode and there is no space for the whole
1137 // of this output, don't bother.
1138 //
1139 Avail = _GetAvailWriteSpace(pRing);
1140 if (Avail < NumBytes)
1141 {
1142 Status = 0u;
1143 }
1144 else
1145 {
1146 Status = NumBytes;
1147 _WriteNoCheck(pRing, pData, NumBytes);
1148 }
1149 break;
1150 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1151 //
1152 // If we are in trim mode, trim to what we can output without blocking.
1153 //
1154 Avail = _GetAvailWriteSpace(pRing);
1155 Status = Avail < NumBytes ? Avail : NumBytes;
1156 _WriteNoCheck(pRing, pData, Status);
1157 break;
1158 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1159 //
1160 // If we are in blocking mode, output everything.
1161 //
1162 Status = _WriteBlocking(pRing, pData, NumBytes);
1163 break;
1164 default:
1165 Status = 0u;
1166 break;
1167 }
1168 //
1169 // Finish up.
1170 //
1171 return Status;
1172 }
1173
1174 /*********************************************************************
1175 *
1176 * SEGGER_RTT_WriteNoLock
1177 *
1178 * Function description
1179 * Stores a specified number of characters in SEGGER RTT
1180 * control block which is then read by the host.
1181 * SEGGER_RTT_WriteNoLock does not lock the application.
1182 *
1183 * Parameters
1184 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1185 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
1186 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
1187 *
1188 * Return value
1189 * Number of bytes which have been stored in the "Up"-buffer.
1190 *
1191 * Notes
1192 * (1) Data is stored according to buffer flags.
1193 * (2) For performance reasons this function does not call Init()
1194 * and may only be called after RTT has been initialized.
1195 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1196 */
SEGGER_RTT_WriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1197 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
1198 {
1199 unsigned Status;
1200 unsigned Avail;
1201 const char *pData;
1202 SEGGER_RTT_BUFFER_UP *pRing;
1203 //
1204 // Get "to-host" ring buffer.
1205 //
1206 pData = (const char *)pBuffer;
1207 pRing =
1208 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1209 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1210 // J-Link side and all of our changes go into HW directly
1211 //
1212 // How we output depends upon the mode...
1213 //
1214 switch (pRing->Flags)
1215 {
1216 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1217 //
1218 // If we are in skip mode and there is no space for the whole
1219 // of this output, don't bother.
1220 //
1221 Avail = _GetAvailWriteSpace(pRing);
1222 if (Avail < NumBytes)
1223 {
1224 Status = 0u;
1225 }
1226 else
1227 {
1228 Status = NumBytes;
1229 _WriteNoCheck(pRing, pData, NumBytes);
1230 }
1231 break;
1232 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1233 //
1234 // If we are in trim mode, trim to what we can output without blocking.
1235 //
1236 Avail = _GetAvailWriteSpace(pRing);
1237 Status = Avail < NumBytes ? Avail : NumBytes;
1238 _WriteNoCheck(pRing, pData, Status);
1239 break;
1240 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1241 //
1242 // If we are in blocking mode, output everything.
1243 //
1244 Status = _WriteBlocking(pRing, pData, NumBytes);
1245 break;
1246 default:
1247 Status = 0u;
1248 break;
1249 }
1250 //
1251 // Finish up.
1252 //
1253 return Status;
1254 }
1255
1256 /*********************************************************************
1257 *
1258 * SEGGER_RTT_WriteDownBuffer
1259 *
1260 * Function description
1261 * Stores a specified number of characters in SEGGER RTT control block in a <Down> buffer.
1262 *
1263 * Parameters
1264 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1265 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
1266 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
1267 *
1268 * Return value
1269 * Number of bytes which have been stored in the "Down"-buffer.
1270 *
1271 * Notes
1272 * (1) Data is stored according to buffer flags.
1273 *
1274 * Additional information
1275 * This function must not be called when J-Link might also do RTT.
1276 * This function locks against all other RTT operations. I.e. during
1277 * the write operation, writing from the application is also locked.
1278 * If only one consumer writes to the down buffer,
1279 * call SEGGER_RTT_WriteDownBufferNoLock() instead.
1280 */
SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1281 unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
1282 {
1283 unsigned Status;
1284
1285 INIT();
1286 SEGGER_RTT_LOCK();
1287 Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function
1288 SEGGER_RTT_UNLOCK();
1289 return Status;
1290 }
1291
1292 /*********************************************************************
1293 *
1294 * SEGGER_RTT_Write
1295 *
1296 * Function description
1297 * Stores a specified number of characters in SEGGER RTT
1298 * control block which is then read by the host.
1299 *
1300 * Parameters
1301 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1302 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
1303 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
1304 *
1305 * Return value
1306 * Number of bytes which have been stored in the "Up"-buffer.
1307 *
1308 * Notes
1309 * (1) Data is stored according to buffer flags.
1310 */
SEGGER_RTT_Write(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)1311 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
1312 {
1313 unsigned Status;
1314
1315 INIT();
1316 SEGGER_RTT_LOCK();
1317 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function
1318 SEGGER_RTT_UNLOCK();
1319 return Status;
1320 }
1321
1322 /*********************************************************************
1323 *
1324 * SEGGER_RTT_WriteString
1325 *
1326 * Function description
1327 * Stores string in SEGGER RTT control block.
1328 * This data is read by the host.
1329 *
1330 * Parameters
1331 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1332 * s Pointer to string.
1333 *
1334 * Return value
1335 * Number of bytes which have been stored in the "Up"-buffer.
1336 *
1337 * Notes
1338 * (1) Data is stored according to buffer flags.
1339 * (2) String passed to this function has to be \0 terminated
1340 * (3) \0 termination character is *not* stored in RTT buffer
1341 */
SEGGER_RTT_WriteString(unsigned BufferIndex,const char * s)1342 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char *s)
1343 {
1344 unsigned Len;
1345
1346 Len = STRLEN(s);
1347 return SEGGER_RTT_Write(BufferIndex, s, Len);
1348 }
1349
1350 /*********************************************************************
1351 *
1352 * SEGGER_RTT_PutCharSkipNoLock
1353 *
1354 * Function description
1355 * Stores a single character/byte in SEGGER RTT buffer.
1356 * SEGGER_RTT_PutCharSkipNoLock does not lock the application and
1357 * skips the byte, if it does not fit into the buffer.
1358 *
1359 * Parameters
1360 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1361 * c Byte to be stored.
1362 *
1363 * Return value
1364 * Number of bytes which have been stored in the "Up"-buffer.
1365 *
1366 * Notes
1367 * (1) If there is not enough space in the "Up"-buffer, the character is dropped.
1368 * (2) For performance reasons this function does not call Init()
1369 * and may only be called after RTT has been initialized.
1370 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
1371 */
1372
SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex,char c)1373 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c)
1374 {
1375 SEGGER_RTT_BUFFER_UP *pRing;
1376 unsigned WrOff;
1377 unsigned Status;
1378 volatile char *pDst;
1379 //
1380 // Get "to-host" ring buffer.
1381 //
1382 pRing =
1383 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1384 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1385 // J-Link side and all of our changes go into HW directly
1386 //
1387 // Get write position and handle wrap-around if necessary
1388 //
1389 WrOff = pRing->WrOff + 1;
1390 if (WrOff == pRing->SizeOfBuffer)
1391 {
1392 WrOff = 0;
1393 }
1394 //
1395 // Output byte if free space is available
1396 //
1397 if (WrOff != pRing->RdOff)
1398 {
1399 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1400 *pDst = c;
1401 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1402 // order of memory accesses
1403 pRing->WrOff = WrOff;
1404 Status = 1;
1405 }
1406 else
1407 {
1408 Status = 0;
1409 }
1410 //
1411 return Status;
1412 }
1413
1414 /*********************************************************************
1415 *
1416 * SEGGER_RTT_PutCharSkip
1417 *
1418 * Function description
1419 * Stores a single character/byte in SEGGER RTT buffer.
1420 *
1421 * Parameters
1422 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1423 * c Byte to be stored.
1424 *
1425 * Return value
1426 * Number of bytes which have been stored in the "Up"-buffer.
1427 *
1428 * Notes
1429 * (1) If there is not enough space in the "Up"-buffer, the character is dropped.
1430 */
1431
SEGGER_RTT_PutCharSkip(unsigned BufferIndex,char c)1432 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c)
1433 {
1434 SEGGER_RTT_BUFFER_UP *pRing;
1435 unsigned WrOff;
1436 unsigned Status;
1437 volatile char *pDst;
1438 //
1439 // Prepare
1440 //
1441 INIT();
1442 SEGGER_RTT_LOCK();
1443 //
1444 // Get "to-host" ring buffer.
1445 //
1446 pRing =
1447 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1448 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1449 // J-Link side and all of our changes go into HW directly
1450 //
1451 // Get write position and handle wrap-around if necessary
1452 //
1453 WrOff = pRing->WrOff + 1;
1454 if (WrOff == pRing->SizeOfBuffer)
1455 {
1456 WrOff = 0;
1457 }
1458 //
1459 // Output byte if free space is available
1460 //
1461 if (WrOff != pRing->RdOff)
1462 {
1463 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1464 *pDst = c;
1465 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1466 // order of memory accesses
1467 pRing->WrOff = WrOff;
1468 Status = 1;
1469 }
1470 else
1471 {
1472 Status = 0;
1473 }
1474 //
1475 // Finish up.
1476 //
1477 SEGGER_RTT_UNLOCK();
1478 //
1479 return Status;
1480 }
1481
1482 /*********************************************************************
1483 *
1484 * SEGGER_RTT_PutChar
1485 *
1486 * Function description
1487 * Stores a single character/byte in SEGGER RTT buffer.
1488 *
1489 * Parameters
1490 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
1491 * c Byte to be stored.
1492 *
1493 * Return value
1494 * Number of bytes which have been stored in the "Up"-buffer.
1495 *
1496 * Notes
1497 * (1) Data is stored according to buffer flags.
1498 */
1499
SEGGER_RTT_PutChar(unsigned BufferIndex,char c)1500 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c)
1501 {
1502 SEGGER_RTT_BUFFER_UP *pRing;
1503 unsigned WrOff;
1504 unsigned Status;
1505 volatile char *pDst;
1506 //
1507 // Prepare
1508 //
1509 INIT();
1510 SEGGER_RTT_LOCK();
1511 //
1512 // Get "to-host" ring buffer.
1513 //
1514 pRing =
1515 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1516 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1517 // J-Link side and all of our changes go into HW directly
1518 //
1519 // Get write position and handle wrap-around if necessary
1520 //
1521 WrOff = pRing->WrOff + 1;
1522 if (WrOff == pRing->SizeOfBuffer)
1523 {
1524 WrOff = 0;
1525 }
1526 //
1527 // Wait for free space if mode is set to blocking
1528 //
1529 if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL)
1530 {
1531 while (WrOff == pRing->RdOff)
1532 {
1533 ;
1534 }
1535 }
1536 //
1537 // Output byte if free space is available
1538 //
1539 if (WrOff != pRing->RdOff)
1540 {
1541 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF;
1542 *pDst = c;
1543 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1544 // order of memory accesses
1545 pRing->WrOff = WrOff;
1546 Status = 1;
1547 }
1548 else
1549 {
1550 Status = 0;
1551 }
1552 //
1553 // Finish up.
1554 //
1555 SEGGER_RTT_UNLOCK();
1556 return Status;
1557 }
1558
1559 /*********************************************************************
1560 *
1561 * SEGGER_RTT_GetKey
1562 *
1563 * Function description
1564 * Reads one character from the SEGGER RTT buffer.
1565 * Host has previously stored data there.
1566 *
1567 * Return value
1568 * < 0 - No character available (buffer empty).
1569 * >= 0 - Character which has been read. (Possible values: 0 - 255)
1570 *
1571 * Notes
1572 * (1) This function is only specified for accesses to RTT buffer 0.
1573 */
SEGGER_RTT_GetKey(void)1574 int SEGGER_RTT_GetKey(void)
1575 {
1576 char c;
1577 int r;
1578
1579 r = (int)SEGGER_RTT_Read(0u, &c, 1u);
1580 if (r == 1)
1581 {
1582 r = (int)(unsigned char)c;
1583 }
1584 else
1585 {
1586 r = -1;
1587 }
1588 return r;
1589 }
1590
1591 /*********************************************************************
1592 *
1593 * SEGGER_RTT_WaitKey
1594 *
1595 * Function description
1596 * Waits until at least one character is avaible in the SEGGER RTT buffer.
1597 * Once a character is available, it is read and this function returns.
1598 *
1599 * Return value
1600 * >=0 - Character which has been read.
1601 *
1602 * Notes
1603 * (1) This function is only specified for accesses to RTT buffer 0
1604 * (2) This function is blocking if no character is present in RTT buffer
1605 */
SEGGER_RTT_WaitKey(void)1606 int SEGGER_RTT_WaitKey(void)
1607 {
1608 int r;
1609
1610 do
1611 {
1612 r = SEGGER_RTT_GetKey();
1613 } while (r < 0);
1614 return r;
1615 }
1616
1617 /*********************************************************************
1618 *
1619 * SEGGER_RTT_HasKey
1620 *
1621 * Function description
1622 * Checks if at least one character for reading is available in the SEGGER RTT buffer.
1623 *
1624 * Return value
1625 * == 0 - No characters are available to read.
1626 * == 1 - At least one character is available.
1627 *
1628 * Notes
1629 * (1) This function is only specified for accesses to RTT buffer 0
1630 */
SEGGER_RTT_HasKey(void)1631 int SEGGER_RTT_HasKey(void)
1632 {
1633 SEGGER_RTT_BUFFER_DOWN *pRing;
1634 unsigned RdOff;
1635 int r;
1636
1637 INIT();
1638 pRing =
1639 (SEGGER_RTT_BUFFER_DOWN *)((char *)&_SEGGER_RTT.aDown[0] +
1640 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1641 // J-Link side and all of our changes go into HW directly
1642 RdOff = pRing->RdOff;
1643 if (RdOff != pRing->WrOff)
1644 {
1645 r = 1;
1646 }
1647 else
1648 {
1649 r = 0;
1650 }
1651 return r;
1652 }
1653
1654 /*********************************************************************
1655 *
1656 * SEGGER_RTT_HasData
1657 *
1658 * Function description
1659 * Check if there is data from the host in the given buffer.
1660 *
1661 * Return value:
1662 * ==0: No data
1663 * !=0: Data in buffer
1664 *
1665 */
SEGGER_RTT_HasData(unsigned BufferIndex)1666 unsigned SEGGER_RTT_HasData(unsigned BufferIndex)
1667 {
1668 SEGGER_RTT_BUFFER_DOWN *pRing;
1669 unsigned v;
1670
1671 pRing =
1672 (SEGGER_RTT_BUFFER_DOWN *)((char *)&_SEGGER_RTT.aDown[BufferIndex] +
1673 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1674 // J-Link side and all of our changes go into HW directly
1675 v = pRing->WrOff;
1676 return v - pRing->RdOff;
1677 }
1678
1679 /*********************************************************************
1680 *
1681 * SEGGER_RTT_HasDataUp
1682 *
1683 * Function description
1684 * Check if there is data remaining to be sent in the given buffer.
1685 *
1686 * Return value:
1687 * ==0: No data
1688 * !=0: Data in buffer
1689 *
1690 */
SEGGER_RTT_HasDataUp(unsigned BufferIndex)1691 unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex)
1692 {
1693 SEGGER_RTT_BUFFER_UP *pRing;
1694 unsigned v;
1695
1696 pRing =
1697 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
1698 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
1699 // J-Link side and all of our changes go into HW directly
1700 v = pRing->RdOff;
1701 return pRing->WrOff - v;
1702 }
1703
1704 /*********************************************************************
1705 *
1706 * SEGGER_RTT_AllocDownBuffer
1707 *
1708 * Function description
1709 * Run-time configuration of the next down-buffer (H->T).
1710 * The next buffer, which is not used yet is configured.
1711 * This includes: Buffer address, size, name, flags, ...
1712 *
1713 * Parameters
1714 * sName Pointer to a constant name string.
1715 * pBuffer Pointer to a buffer to be used.
1716 * BufferSize Size of the buffer.
1717 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1718 *
1719 * Return value
1720 * >= 0 - O.K. Buffer Index
1721 * < 0 - Error
1722 */
SEGGER_RTT_AllocDownBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1723 int SEGGER_RTT_AllocDownBuffer(const char *sName, void *pBuffer, unsigned BufferSize, unsigned Flags)
1724 {
1725 int BufferIndex;
1726 volatile SEGGER_RTT_CB *pRTTCB;
1727
1728 INIT();
1729 SEGGER_RTT_LOCK();
1730 pRTTCB = (volatile SEGGER_RTT_CB
1731 *)((unsigned char *)&_SEGGER_RTT +
1732 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
1733 // side and all of our changes go into HW directly
1734 BufferIndex = 0;
1735 do
1736 {
1737 if (pRTTCB->aDown[BufferIndex].pBuffer == NULL)
1738 {
1739 break;
1740 }
1741 BufferIndex++;
1742 } while (BufferIndex < pRTTCB->MaxNumDownBuffers);
1743 if (BufferIndex < pRTTCB->MaxNumDownBuffers)
1744 {
1745 pRTTCB->aDown[BufferIndex].sName = sName;
1746 pRTTCB->aDown[BufferIndex].pBuffer = (char *)pBuffer;
1747 pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize;
1748 pRTTCB->aDown[BufferIndex].RdOff = 0u;
1749 pRTTCB->aDown[BufferIndex].WrOff = 0u;
1750 pRTTCB->aDown[BufferIndex].Flags = Flags;
1751 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1752 // order of memory accesses
1753 }
1754 else
1755 {
1756 BufferIndex = -1;
1757 }
1758 SEGGER_RTT_UNLOCK();
1759 return BufferIndex;
1760 }
1761
1762 /*********************************************************************
1763 *
1764 * SEGGER_RTT_AllocUpBuffer
1765 *
1766 * Function description
1767 * Run-time configuration of the next up-buffer (T->H).
1768 * The next buffer, which is not used yet is configured.
1769 * This includes: Buffer address, size, name, flags, ...
1770 *
1771 * Parameters
1772 * sName Pointer to a constant name string.
1773 * pBuffer Pointer to a buffer to be used.
1774 * BufferSize Size of the buffer.
1775 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1776 *
1777 * Return value
1778 * >= 0 - O.K. Buffer Index
1779 * < 0 - Error
1780 */
SEGGER_RTT_AllocUpBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1781 int SEGGER_RTT_AllocUpBuffer(const char *sName, void *pBuffer, unsigned BufferSize, unsigned Flags)
1782 {
1783 int BufferIndex;
1784 volatile SEGGER_RTT_CB *pRTTCB;
1785
1786 INIT();
1787 SEGGER_RTT_LOCK();
1788 pRTTCB = (volatile SEGGER_RTT_CB
1789 *)((unsigned char *)&_SEGGER_RTT +
1790 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
1791 // side and all of our changes go into HW directly
1792 BufferIndex = 0;
1793 do
1794 {
1795 if (pRTTCB->aUp[BufferIndex].pBuffer == NULL)
1796 {
1797 break;
1798 }
1799 BufferIndex++;
1800 } while (BufferIndex < pRTTCB->MaxNumUpBuffers);
1801 if (BufferIndex < pRTTCB->MaxNumUpBuffers)
1802 {
1803 pRTTCB->aUp[BufferIndex].sName = sName;
1804 pRTTCB->aUp[BufferIndex].pBuffer = (char *)pBuffer;
1805 pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize;
1806 pRTTCB->aUp[BufferIndex].RdOff = 0u;
1807 pRTTCB->aUp[BufferIndex].WrOff = 0u;
1808 pRTTCB->aUp[BufferIndex].Flags = Flags;
1809 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1810 // order of memory accesses
1811 }
1812 else
1813 {
1814 BufferIndex = -1;
1815 }
1816 SEGGER_RTT_UNLOCK();
1817 return BufferIndex;
1818 }
1819
1820 /*********************************************************************
1821 *
1822 * SEGGER_RTT_ConfigUpBuffer
1823 *
1824 * Function description
1825 * Run-time configuration of a specific up-buffer (T->H).
1826 * Buffer to be configured is specified by index.
1827 * This includes: Buffer address, size, name, flags, ...
1828 *
1829 * Parameters
1830 * BufferIndex Index of the buffer to configure.
1831 * sName Pointer to a constant name string.
1832 * pBuffer Pointer to a buffer to be used.
1833 * BufferSize Size of the buffer.
1834 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1835 *
1836 * Return value
1837 * >= 0 - O.K.
1838 * < 0 - Error
1839 *
1840 * Additional information
1841 * Buffer 0 is configured on compile-time.
1842 * May only be called once per buffer.
1843 * Buffer name and flags can be reconfigured using the appropriate functions.
1844 */
SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1845 int SEGGER_RTT_ConfigUpBuffer(
1846 unsigned BufferIndex, const char *sName, void *pBuffer, unsigned BufferSize, unsigned Flags)
1847 {
1848 int r;
1849 volatile SEGGER_RTT_CB *pRTTCB;
1850 volatile SEGGER_RTT_BUFFER_UP *pUp;
1851
1852 INIT();
1853 pRTTCB = (volatile SEGGER_RTT_CB
1854 *)((unsigned char *)&_SEGGER_RTT +
1855 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
1856 // side and all of our changes go into HW directly
1857 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS)
1858 {
1859 SEGGER_RTT_LOCK();
1860 pUp = &pRTTCB->aUp[BufferIndex];
1861 if (BufferIndex)
1862 {
1863 pUp->sName = sName;
1864 pUp->pBuffer = (char *)pBuffer;
1865 pUp->SizeOfBuffer = BufferSize;
1866 pUp->RdOff = 0u;
1867 pUp->WrOff = 0u;
1868 }
1869 pUp->Flags = Flags;
1870 SEGGER_RTT_UNLOCK();
1871 r = 0;
1872 }
1873 else
1874 {
1875 r = -1;
1876 }
1877 return r;
1878 }
1879
1880 /*********************************************************************
1881 *
1882 * SEGGER_RTT_ConfigDownBuffer
1883 *
1884 * Function description
1885 * Run-time configuration of a specific down-buffer (H->T).
1886 * Buffer to be configured is specified by index.
1887 * This includes: Buffer address, size, name, flags, ...
1888 *
1889 * Parameters
1890 * BufferIndex Index of the buffer to configure.
1891 * sName Pointer to a constant name string.
1892 * pBuffer Pointer to a buffer to be used.
1893 * BufferSize Size of the buffer.
1894 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1895 *
1896 * Return value
1897 * >= 0 O.K.
1898 * < 0 Error
1899 *
1900 * Additional information
1901 * Buffer 0 is configured on compile-time.
1902 * May only be called once per buffer.
1903 * Buffer name and flags can be reconfigured using the appropriate functions.
1904 */
SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1905 int SEGGER_RTT_ConfigDownBuffer(
1906 unsigned BufferIndex, const char *sName, void *pBuffer, unsigned BufferSize, unsigned Flags)
1907 {
1908 int r;
1909 volatile SEGGER_RTT_CB *pRTTCB;
1910 volatile SEGGER_RTT_BUFFER_DOWN *pDown;
1911
1912 INIT();
1913 pRTTCB = (volatile SEGGER_RTT_CB
1914 *)((unsigned char *)&_SEGGER_RTT +
1915 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
1916 // side and all of our changes go into HW directly
1917 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS)
1918 {
1919 SEGGER_RTT_LOCK();
1920 pDown = &pRTTCB->aDown[BufferIndex];
1921 if (BufferIndex)
1922 {
1923 pDown->sName = sName;
1924 pDown->pBuffer = (char *)pBuffer;
1925 pDown->SizeOfBuffer = BufferSize;
1926 pDown->RdOff = 0u;
1927 pDown->WrOff = 0u;
1928 }
1929 pDown->Flags = Flags;
1930 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the
1931 // order of memory accesses
1932 SEGGER_RTT_UNLOCK();
1933 r = 0;
1934 }
1935 else
1936 {
1937 r = -1;
1938 }
1939 return r;
1940 }
1941
1942 /*********************************************************************
1943 *
1944 * SEGGER_RTT_SetNameUpBuffer
1945 *
1946 * Function description
1947 * Run-time configuration of a specific up-buffer name (T->H).
1948 * Buffer to be configured is specified by index.
1949 *
1950 * Parameters
1951 * BufferIndex Index of the buffer to renamed.
1952 * sName Pointer to a constant name string.
1953 *
1954 * Return value
1955 * >= 0 O.K.
1956 * < 0 Error
1957 */
SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex,const char * sName)1958 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char *sName)
1959 {
1960 int r;
1961 volatile SEGGER_RTT_CB *pRTTCB;
1962 volatile SEGGER_RTT_BUFFER_UP *pUp;
1963
1964 INIT();
1965 pRTTCB = (volatile SEGGER_RTT_CB
1966 *)((unsigned char *)&_SEGGER_RTT +
1967 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
1968 // side and all of our changes go into HW directly
1969 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS)
1970 {
1971 SEGGER_RTT_LOCK();
1972 pUp = &pRTTCB->aUp[BufferIndex];
1973 pUp->sName = sName;
1974 SEGGER_RTT_UNLOCK();
1975 r = 0;
1976 }
1977 else
1978 {
1979 r = -1;
1980 }
1981 return r;
1982 }
1983
1984 /*********************************************************************
1985 *
1986 * SEGGER_RTT_SetNameDownBuffer
1987 *
1988 * Function description
1989 * Run-time configuration of a specific Down-buffer name (T->H).
1990 * Buffer to be configured is specified by index.
1991 *
1992 * Parameters
1993 * BufferIndex Index of the buffer to renamed.
1994 * sName Pointer to a constant name string.
1995 *
1996 * Return value
1997 * >= 0 O.K.
1998 * < 0 Error
1999 */
SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex,const char * sName)2000 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char *sName)
2001 {
2002 int r;
2003 volatile SEGGER_RTT_CB *pRTTCB;
2004 volatile SEGGER_RTT_BUFFER_DOWN *pDown;
2005
2006 INIT();
2007 pRTTCB = (volatile SEGGER_RTT_CB
2008 *)((unsigned char *)&_SEGGER_RTT +
2009 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
2010 // side and all of our changes go into HW directly
2011 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS)
2012 {
2013 SEGGER_RTT_LOCK();
2014 pDown = &pRTTCB->aDown[BufferIndex];
2015 pDown->sName = sName;
2016 SEGGER_RTT_UNLOCK();
2017 r = 0;
2018 }
2019 else
2020 {
2021 r = -1;
2022 }
2023 return r;
2024 }
2025
2026 /*********************************************************************
2027 *
2028 * SEGGER_RTT_SetFlagsUpBuffer
2029 *
2030 * Function description
2031 * Run-time configuration of specific up-buffer flags (T->H).
2032 * Buffer to be configured is specified by index.
2033 *
2034 * Parameters
2035 * BufferIndex Index of the buffer.
2036 * Flags Flags to set for the buffer.
2037 *
2038 * Return value
2039 * >= 0 O.K.
2040 * < 0 Error
2041 */
SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex,unsigned Flags)2042 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags)
2043 {
2044 int r;
2045 volatile SEGGER_RTT_CB *pRTTCB;
2046 volatile SEGGER_RTT_BUFFER_UP *pUp;
2047
2048 INIT();
2049 pRTTCB = (volatile SEGGER_RTT_CB
2050 *)((unsigned char *)&_SEGGER_RTT +
2051 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
2052 // side and all of our changes go into HW directly
2053 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS)
2054 {
2055 SEGGER_RTT_LOCK();
2056 pUp = &pRTTCB->aUp[BufferIndex];
2057 pUp->Flags = Flags;
2058 SEGGER_RTT_UNLOCK();
2059 r = 0;
2060 }
2061 else
2062 {
2063 r = -1;
2064 }
2065 return r;
2066 }
2067
2068 /*********************************************************************
2069 *
2070 * SEGGER_RTT_SetFlagsDownBuffer
2071 *
2072 * Function description
2073 * Run-time configuration of specific Down-buffer flags (T->H).
2074 * Buffer to be configured is specified by index.
2075 *
2076 * Parameters
2077 * BufferIndex Index of the buffer to renamed.
2078 * Flags Flags to set for the buffer.
2079 *
2080 * Return value
2081 * >= 0 O.K.
2082 * < 0 Error
2083 */
SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex,unsigned Flags)2084 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags)
2085 {
2086 int r;
2087 volatile SEGGER_RTT_CB *pRTTCB;
2088 volatile SEGGER_RTT_BUFFER_DOWN *pDown;
2089
2090 INIT();
2091 pRTTCB = (volatile SEGGER_RTT_CB
2092 *)((unsigned char *)&_SEGGER_RTT +
2093 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
2094 // side and all of our changes go into HW directly
2095 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS)
2096 {
2097 SEGGER_RTT_LOCK();
2098 pDown = &pRTTCB->aDown[BufferIndex];
2099 pDown->Flags = Flags;
2100 SEGGER_RTT_UNLOCK();
2101 r = 0;
2102 }
2103 else
2104 {
2105 r = -1;
2106 }
2107 return r;
2108 }
2109
2110 /*********************************************************************
2111 *
2112 * SEGGER_RTT_Init
2113 *
2114 * Function description
2115 * Initializes the RTT Control Block.
2116 * Should be used in RAM targets, at start of the application.
2117 *
2118 */
SEGGER_RTT_Init(void)2119 void SEGGER_RTT_Init(void)
2120 {
2121 _DoInit();
2122 }
2123
2124 /*********************************************************************
2125 *
2126 * SEGGER_RTT_SetTerminal
2127 *
2128 * Function description
2129 * Sets the terminal to be used for output on channel 0.
2130 *
2131 * Parameters
2132 * TerminalId Index of the terminal.
2133 *
2134 * Return value
2135 * >= 0 O.K.
2136 * < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new
2137 * terminal Id)
2138 *
2139 * Notes
2140 * (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
2141 */
SEGGER_RTT_SetTerminal(unsigned char TerminalId)2142 int SEGGER_RTT_SetTerminal(unsigned char TerminalId)
2143 {
2144 unsigned char ac[2];
2145 SEGGER_RTT_BUFFER_UP *pRing;
2146 unsigned Avail;
2147 int r;
2148
2149 INIT();
2150 r = 0;
2151 ac[0] = 0xFFu;
2152 if (TerminalId < sizeof(_aTerminalId))
2153 { // We only support a certain number of channels
2154 ac[1] = _aTerminalId[TerminalId];
2155 pRing = (SEGGER_RTT_BUFFER_UP
2156 *)((char *)&_SEGGER_RTT.aUp[0] +
2157 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side
2158 // and all of our changes go into HW directly
2159 SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of
2160 // free bytes in buffer does not change downwards after checking and before writing
2161 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL)
2162 {
2163 _ActiveTerminal = TerminalId;
2164 _WriteBlocking(pRing, (const char *)ac, 2u);
2165 }
2166 else
2167 { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
2168 Avail = _GetAvailWriteSpace(pRing);
2169 if (Avail >= 2)
2170 {
2171 _ActiveTerminal = TerminalId; // Only change active terminal in case of success
2172 _WriteNoCheck(pRing, (const char *)ac, 2u);
2173 }
2174 else
2175 {
2176 r = -1;
2177 }
2178 }
2179 SEGGER_RTT_UNLOCK();
2180 }
2181 else
2182 {
2183 r = -1;
2184 }
2185 return r;
2186 }
2187
2188 /*********************************************************************
2189 *
2190 * SEGGER_RTT_TerminalOut
2191 *
2192 * Function description
2193 * Writes a string to the given terminal
2194 * without changing the terminal for channel 0.
2195 *
2196 * Parameters
2197 * TerminalId Index of the terminal.
2198 * s String to be printed on the terminal.
2199 *
2200 * Return value
2201 * >= 0 - Number of bytes written.
2202 * < 0 - Error.
2203 *
2204 */
SEGGER_RTT_TerminalOut(unsigned char TerminalId,const char * s)2205 int SEGGER_RTT_TerminalOut(unsigned char TerminalId, const char *s)
2206 {
2207 int Status;
2208 unsigned FragLen;
2209 unsigned Avail;
2210 SEGGER_RTT_BUFFER_UP *pRing;
2211 //
2212 INIT();
2213 //
2214 // Validate terminal ID.
2215 //
2216 if (TerminalId < (char)sizeof(_aTerminalId))
2217 { // We only support a certain number of channels
2218 //
2219 // Get "to-host" ring buffer.
2220 //
2221 pRing = (SEGGER_RTT_BUFFER_UP
2222 *)((char *)&_SEGGER_RTT.aUp[0] +
2223 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side
2224 // and all of our changes go into HW directly
2225 //
2226 // Need to be able to change terminal, write data, change back.
2227 // Compute the fixed and variable sizes.
2228 //
2229 FragLen = STRLEN(s);
2230 //
2231 // How we output depends upon the mode...
2232 //
2233 SEGGER_RTT_LOCK();
2234 Avail = _GetAvailWriteSpace(pRing);
2235 switch (pRing->Flags & SEGGER_RTT_MODE_MASK)
2236 {
2237 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
2238 //
2239 // If we are in skip mode and there is no space for the whole
2240 // of this output, don't bother switching terminals at all.
2241 //
2242 if (Avail < (FragLen + 4u))
2243 {
2244 Status = 0;
2245 }
2246 else
2247 {
2248 _PostTerminalSwitch(pRing, TerminalId);
2249 Status = (int)_WriteBlocking(pRing, s, FragLen);
2250 _PostTerminalSwitch(pRing, _ActiveTerminal);
2251 }
2252 break;
2253 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
2254 //
2255 // If we are in trim mode and there is not enough space for everything,
2256 // trim the output but always include the terminal switch. If no room
2257 // for terminal switch, skip that totally.
2258 //
2259 if (Avail < 4u)
2260 {
2261 Status = -1;
2262 }
2263 else
2264 {
2265 _PostTerminalSwitch(pRing, TerminalId);
2266 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
2267 _PostTerminalSwitch(pRing, _ActiveTerminal);
2268 }
2269 break;
2270 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
2271 //
2272 // If we are in blocking mode, output everything.
2273 //
2274 _PostTerminalSwitch(pRing, TerminalId);
2275 Status = (int)_WriteBlocking(pRing, s, FragLen);
2276 _PostTerminalSwitch(pRing, _ActiveTerminal);
2277 break;
2278 default:
2279 Status = -1;
2280 break;
2281 }
2282 //
2283 // Finish up.
2284 //
2285 SEGGER_RTT_UNLOCK();
2286 }
2287 else
2288 {
2289 Status = -1;
2290 }
2291 return Status;
2292 }
2293
2294 /*********************************************************************
2295 *
2296 * SEGGER_RTT_GetAvailWriteSpace
2297 *
2298 * Function description
2299 * Returns the number of bytes available in the ring buffer.
2300 *
2301 * Parameters
2302 * BufferIndex Index of the up buffer.
2303 *
2304 * Return value
2305 * Number of bytes that are free in the selected up buffer.
2306 */
SEGGER_RTT_GetAvailWriteSpace(unsigned BufferIndex)2307 unsigned SEGGER_RTT_GetAvailWriteSpace(unsigned BufferIndex)
2308 {
2309 SEGGER_RTT_BUFFER_UP *pRing;
2310
2311 pRing =
2312 (SEGGER_RTT_BUFFER_UP *)((char *)&_SEGGER_RTT.aUp[BufferIndex] +
2313 SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the
2314 // J-Link side and all of our changes go into HW directly
2315 return _GetAvailWriteSpace(pRing);
2316 }
2317
2318 /*********************************************************************
2319 *
2320 * SEGGER_RTT_GetBytesInBuffer()
2321 *
2322 * Function description
2323 * Returns the number of bytes currently used in the up buffer.
2324 *
2325 * Parameters
2326 * BufferIndex Index of the up buffer.
2327 *
2328 * Return value
2329 * Number of bytes that are used in the buffer.
2330 */
SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex)2331 unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex)
2332 {
2333 unsigned RdOff;
2334 unsigned WrOff;
2335 unsigned r;
2336 volatile SEGGER_RTT_CB *pRTTCB;
2337 //
2338 // Avoid warnings regarding volatile access order. It's not a problem
2339 // in this case, but dampen compiler enthusiasm.
2340 //
2341 pRTTCB = (volatile SEGGER_RTT_CB
2342 *)((unsigned char *)&_SEGGER_RTT +
2343 SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link
2344 // side and all of our changes go into HW directly
2345 RdOff = pRTTCB->aUp[BufferIndex].RdOff;
2346 WrOff = pRTTCB->aUp[BufferIndex].WrOff;
2347 if (RdOff <= WrOff)
2348 {
2349 r = WrOff - RdOff;
2350 }
2351 else
2352 {
2353 r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff);
2354 }
2355 return r;
2356 }
2357
2358 /*************************** End of file ****************************/
2359