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