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