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