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