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