1 /*********************************************************************
2 * SEGGER MICROCONTROLLER GmbH & Co. KG *
3 * Solutions for real time microcontroller applications *
4 **********************************************************************
5 * *
6 * (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG *
7 * *
8 * www.segger.com Support: support@segger.com *
9 * *
10 **********************************************************************
11 * *
12 * SEGGER RTT * Real Time Transfer for embedded targets *
13 * *
14 **********************************************************************
15 * *
16 * All rights reserved. *
17 * *
18 * * This software may in its unmodified form be freely redistributed *
19 * in source, linkable, or executable form. *
20 * * The source code may be modified, provided the source code *
21 * retains the above copyright notice, this list of conditions and *
22 * the following disclaimer. *
23 * * Modified versions of this software in source, executable, or *
24 * linkable form may not be distributed without prior consent of *
25 * SEGGER. *
26 * * This software may only be used for communication with SEGGER *
27 * J-Link debug probes. *
28 * *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
33 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
34 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
40 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
41 * DAMAGE. *
42 * *
43 **********************************************************************
44 * *
45 * RTT version: 6.00e *
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: 4079 $
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 #ifndef BUFFER_SIZE_UP
88 #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host
89 #endif
90
91 #ifndef BUFFER_SIZE_DOWN
92 #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input)
93 #endif
94
95 #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
96 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target
97 #endif
98
99 #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
100 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target
101 #endif
102
103 #ifndef SEGGER_RTT_BUFFER_SECTION
104 #if defined(SEGGER_RTT_SECTION)
105 #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
106 #endif
107 #endif
108
109 #ifndef SEGGER_RTT_ALIGNMENT
110 #define SEGGER_RTT_ALIGNMENT 0
111 #endif
112
113 #ifndef SEGGER_RTT_BUFFER_ALIGNMENT
114 #define SEGGER_RTT_BUFFER_ALIGNMENT 0
115 #endif
116
117 #ifndef SEGGER_RTT_MODE_DEFAULT
118 #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
119 #endif
120
121 #ifndef SEGGER_RTT_LOCK
122 #define SEGGER_RTT_LOCK()
123 #endif
124
125 #ifndef SEGGER_RTT_UNLOCK
126 #define SEGGER_RTT_UNLOCK()
127 #endif
128
129 #ifndef STRLEN
130 #define STRLEN(a) strlen((a))
131 #endif
132
133 #ifndef MEMCPY
134 #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
135 #endif
136
137 #ifndef MIN
138 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
139 #endif
140
141 #ifndef MAX
142 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
143 #endif
144 //
145 // For some environments, NULL may not be defined until certain headers are included
146 //
147 #ifndef NULL
148 #define NULL 0
149 #endif
150
151 /*********************************************************************
152 *
153 * Defines, fixed
154 *
155 **********************************************************************
156 */
157 #if (defined __ICCARM__) || (defined __ICCRX__)
158 #define RTT_PRAGMA(P) _Pragma(#P)
159 #endif
160
161 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
162 #if (defined __GNUC__)
163 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
164 #elif (defined __ICCARM__) || (defined __ICCRX__)
165 #define PRAGMA(A) _Pragma(#A)
166 #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
167 Var
168 #elif (defined __CC_ARM__)
169 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
170 #else
171 #error "Alignment not supported for this compiler."
172 #endif
173 #else
174 #define SEGGER_RTT_ALIGN(Var, Alignment) Var
175 #endif
176
177 #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
178 #if (defined __GNUC__)
179 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
180 #elif (defined __ICCARM__) || (defined __ICCRX__)
181 #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
182 Var
183 #elif (defined __CC_ARM__)
184 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var
185 #else
186 #error "Section placement not supported for this compiler."
187 #endif
188 #else
189 #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
190 #endif
191
192
193 #if SEGGER_RTT_ALIGNMENT
194 #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
195 #else
196 #define SEGGER_RTT_CB_ALIGN(Var) Var
197 #endif
198
199 #if SEGGER_RTT_BUFFER_ALIGNMENT
200 #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
201 #else
202 #define SEGGER_RTT_BUFFER_ALIGN(Var) Var
203 #endif
204
205
206 #if defined(SEGGER_RTT_SECTION)
207 #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
208 #else
209 #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
210 #endif
211
212 #if defined(SEGGER_RTT_BUFFER_SECTION)
213 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
214 #else
215 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
216 #endif
217
218 /*********************************************************************
219 *
220 * Static const data
221 *
222 **********************************************************************
223 */
224
225 static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
226
227 /*********************************************************************
228 *
229 * Static data
230 *
231 **********************************************************************
232 */
233 //
234 // RTT Control Block and allocate buffers for channel 0
235 //
236 SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
237
238 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP]));
239 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
240
241 static char _ActiveTerminal;
242
243 /*********************************************************************
244 *
245 * Static functions
246 *
247 **********************************************************************
248 */
249
250 /*********************************************************************
251 *
252 * _DoInit()
253 *
254 * Function description
255 * Initializes the control block an buffers.
256 * May only be called via INIT() to avoid overriding settings.
257 *
258 */
259 #define INIT() do { \
260 if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \
261 } while (0)
_DoInit(void)262 static void _DoInit(void) {
263 SEGGER_RTT_CB* p;
264 //
265 // Initialize control block
266 //
267 p = &_SEGGER_RTT;
268 p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
269 p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
270 //
271 // Initialize up buffer 0
272 //
273 p->aUp[0].sName = "Terminal";
274 p->aUp[0].pBuffer = _acUpBuffer;
275 p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer);
276 p->aUp[0].RdOff = 0u;
277 p->aUp[0].WrOff = 0u;
278 p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
279 //
280 // Initialize down buffer 0
281 //
282 p->aDown[0].sName = "Terminal";
283 p->aDown[0].pBuffer = _acDownBuffer;
284 p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer);
285 p->aDown[0].RdOff = 0u;
286 p->aDown[0].WrOff = 0u;
287 p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
288 //
289 // Finish initialization of the control block.
290 // Copy Id string in three steps to make sure "SEGGER RTT" is not found
291 // in initializer memory (usually flash) by J-Link
292 //
293 strcpy(&p->acID[7], "RTT");
294 strcpy(&p->acID[0], "SEGGER");
295 p->acID[6] = ' ';
296 }
297
298 /*********************************************************************
299 *
300 * _WriteBlocking()
301 *
302 * Function description
303 * Stores a specified number of characters in SEGGER RTT ring buffer
304 * and updates the associated write pointer which is periodically
305 * read by the host.
306 * The caller is responsible for managing the write chunk sizes as
307 * _WriteBlocking() will block until all data has been posted successfully.
308 *
309 * Parameters
310 * pRing Ring buffer to post to.
311 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
312 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
313 *
314 * Return value
315 * >= 0 - Number of bytes written into buffer.
316 */
_WriteBlocking(SEGGER_RTT_BUFFER_UP * pRing,const char * pBuffer,unsigned NumBytes)317 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
318 unsigned NumBytesToWrite;
319 unsigned NumBytesWritten;
320 unsigned RdOff;
321 unsigned WrOff;
322 //
323 // Write data to buffer and handle wrap-around if necessary
324 //
325 NumBytesWritten = 0u;
326 WrOff = pRing->WrOff;
327 do {
328 RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime
329 if (RdOff > WrOff) {
330 NumBytesToWrite = RdOff - WrOff - 1u;
331 } else {
332 NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
333 }
334 NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around
335 NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
336 memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
337 NumBytesWritten += NumBytesToWrite;
338 pBuffer += NumBytesToWrite;
339 NumBytes -= NumBytesToWrite;
340 WrOff += NumBytesToWrite;
341 if (WrOff == pRing->SizeOfBuffer) {
342 WrOff = 0u;
343 }
344 pRing->WrOff = WrOff;
345 } while (NumBytes);
346 //
347 return NumBytesWritten;
348 }
349
350 /*********************************************************************
351 *
352 * _WriteNoCheck()
353 *
354 * Function description
355 * Stores a specified number of characters in SEGGER RTT ring buffer
356 * and updates the associated write pointer which is periodically
357 * read by the host.
358 * It is callers responsibility to make sure data actually fits in buffer.
359 *
360 * Parameters
361 * pRing Ring buffer to post to.
362 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
363 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
364 *
365 * Notes
366 * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
367 */
_WriteNoCheck(SEGGER_RTT_BUFFER_UP * pRing,const char * pData,unsigned NumBytes)368 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
369 unsigned NumBytesAtOnce;
370 unsigned WrOff;
371 unsigned Rem;
372
373 WrOff = pRing->WrOff;
374 Rem = pRing->SizeOfBuffer - WrOff;
375 if (Rem > NumBytes) {
376 //
377 // All data fits before wrap around
378 //
379 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
380 pRing->WrOff = WrOff + NumBytes;
381 } else {
382 //
383 // We reach the end of the buffer, so need to wrap around
384 //
385 NumBytesAtOnce = Rem;
386 memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
387 NumBytesAtOnce = NumBytes - Rem;
388 memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
389 pRing->WrOff = NumBytesAtOnce;
390 }
391 }
392
393 /*********************************************************************
394 *
395 * _PostTerminalSwitch()
396 *
397 * Function description
398 * Switch terminal to the given terminal ID. It is the caller's
399 * responsibility to ensure the terminal ID is correct and there is
400 * enough space in the buffer for this to complete successfully.
401 *
402 * Parameters
403 * pRing Ring buffer to post to.
404 * TerminalId Terminal ID to switch to.
405 */
_PostTerminalSwitch(SEGGER_RTT_BUFFER_UP * pRing,unsigned char TerminalId)406 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
407 char ac[2];
408
409 ac[0] = 0xFFu;
410 ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
411 _WriteBlocking(pRing, ac, 2u);
412 }
413
414 /*********************************************************************
415 *
416 * _GetAvailWriteSpace()
417 *
418 * Function description
419 * Returns the number of bytes that can be written to the ring
420 * buffer without blocking.
421 *
422 * Parameters
423 * pRing Ring buffer to check.
424 *
425 * Return value
426 * Number of bytes that are free in the buffer.
427 */
_GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP * pRing)428 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
429 unsigned RdOff;
430 unsigned WrOff;
431 unsigned r;
432 //
433 // Avoid warnings regarding volatile access order. It's not a problem
434 // in this case, but dampen compiler enthusiasm.
435 //
436 RdOff = pRing->RdOff;
437 WrOff = pRing->WrOff;
438 if (RdOff <= WrOff) {
439 r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
440 } else {
441 r = RdOff - WrOff - 1u;
442 }
443 return r;
444 }
445
446 /*********************************************************************
447 *
448 * Public code
449 *
450 **********************************************************************
451 */
452 /*********************************************************************
453 *
454 * SEGGER_RTT_ReadNoLock()
455 *
456 * Function description
457 * Reads characters from SEGGER real-time-terminal control block
458 * which have been previously stored by the host.
459 * Do not lock against interrupts and multiple access.
460 *
461 * Parameters
462 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
463 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
464 * BufferSize Size of the target application buffer.
465 *
466 * Return value
467 * Number of bytes that have been read.
468 */
SEGGER_RTT_ReadNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)469 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
470 unsigned NumBytesRem;
471 unsigned NumBytesRead;
472 unsigned RdOff;
473 unsigned WrOff;
474 unsigned char* pBuffer;
475 SEGGER_RTT_BUFFER_DOWN* pRing;
476 //
477 INIT();
478 pRing = &_SEGGER_RTT.aDown[BufferIndex];
479 pBuffer = (unsigned char*)pData;
480 RdOff = pRing->RdOff;
481 WrOff = pRing->WrOff;
482 NumBytesRead = 0u;
483 //
484 // Read from current read position to wrap-around of buffer, first
485 //
486 if (RdOff > WrOff) {
487 NumBytesRem = pRing->SizeOfBuffer - RdOff;
488 NumBytesRem = MIN(NumBytesRem, BufferSize);
489 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
490 NumBytesRead += NumBytesRem;
491 pBuffer += NumBytesRem;
492 BufferSize -= NumBytesRem;
493 RdOff += NumBytesRem;
494 //
495 // Handle wrap-around of buffer
496 //
497 if (RdOff == pRing->SizeOfBuffer) {
498 RdOff = 0u;
499 }
500 }
501 //
502 // Read remaining items of buffer
503 //
504 NumBytesRem = WrOff - RdOff;
505 NumBytesRem = MIN(NumBytesRem, BufferSize);
506 if (NumBytesRem > 0u) {
507 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
508 NumBytesRead += NumBytesRem;
509 pBuffer += NumBytesRem;
510 BufferSize -= NumBytesRem;
511 RdOff += NumBytesRem;
512 }
513 if (NumBytesRead) {
514 pRing->RdOff = RdOff;
515 }
516 //
517 return NumBytesRead;
518 }
519
520 /*********************************************************************
521 *
522 * SEGGER_RTT_Read
523 *
524 * Function description
525 * Reads characters from SEGGER real-time-terminal control block
526 * which have been previously stored by the host.
527 *
528 * Parameters
529 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
530 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
531 * BufferSize Size of the target application buffer.
532 *
533 * Return value
534 * Number of bytes that have been read.
535 */
SEGGER_RTT_Read(unsigned BufferIndex,void * pBuffer,unsigned BufferSize)536 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
537 unsigned NumBytesRead;
538 //
539 SEGGER_RTT_LOCK();
540 //
541 // Call the non-locking read function
542 //
543 NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
544 //
545 // Finish up.
546 //
547 SEGGER_RTT_UNLOCK();
548 //
549 return NumBytesRead;
550 }
551
552 /*********************************************************************
553 *
554 * SEGGER_RTT_WriteWithOverwriteNoLock
555 *
556 * Function description
557 * Stores a specified number of characters in SEGGER RTT
558 * control block.
559 * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application
560 * and overwrites data if the data does not fit into the buffer.
561 *
562 * Parameters
563 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
564 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
565 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
566 *
567 * Notes
568 * (1) If there is not enough space in the "Up"-buffer, data is overwritten.
569 * (2) For performance reasons this function does not call Init()
570 * and may only be called after RTT has been initialized.
571 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
572 * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link
573 * connection reads RTT data.
574 */
SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)575 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
576 const char* pData;
577 SEGGER_RTT_BUFFER_UP* pRing;
578 unsigned Avail;
579
580 pData = (const char *)pBuffer;
581 //
582 // Get "to-host" ring buffer and copy some elements into local variables.
583 //
584 pRing = &_SEGGER_RTT.aUp[BufferIndex];
585 //
586 // Check if we will overwrite data and need to adjust the RdOff.
587 //
588 if (pRing->WrOff == pRing->RdOff) {
589 Avail = pRing->SizeOfBuffer - 1u;
590 } else if ( pRing->WrOff < pRing->RdOff) {
591 Avail = pRing->RdOff - pRing->WrOff - 1u;
592 } else {
593 Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
594 }
595 if (NumBytes > Avail) {
596 pRing->RdOff += (NumBytes - Avail);
597 while (pRing->RdOff >= pRing->SizeOfBuffer) {
598 pRing->RdOff -= pRing->SizeOfBuffer;
599 }
600 }
601 //
602 // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
603 //
604 Avail = pRing->SizeOfBuffer - pRing->WrOff;
605 do {
606 if (Avail > NumBytes) {
607 //
608 // Last round
609 //
610 #if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
611 char* pDst;
612 pDst = pRing->pBuffer + pRing->WrOff;
613 pRing->WrOff += NumBytes;
614 do {
615 *pDst++ = *pData++;
616 } while (--NumBytes);
617 #else
618 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
619 pRing->WrOff += NumBytes;
620 #endif
621 break; //Alternatively: NumBytes = 0;
622 } else {
623 //
624 // Wrap-around necessary, write until wrap-around and reset WrOff
625 //
626 memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
627 pData += Avail;
628 pRing->WrOff = 0;
629 NumBytes -= Avail;
630 Avail = (pRing->SizeOfBuffer - 1);
631 }
632 } while (NumBytes);
633 }
634
635 /*********************************************************************
636 *
637 * SEGGER_RTT_WriteSkipNoLock
638 *
639 * Function description
640 * Stores a specified number of characters in SEGGER RTT
641 * control block which is then read by the host.
642 * SEGGER_RTT_WriteSkipNoLock does not lock the application and
643 * skips all data, if the data does not fit into the buffer.
644 *
645 * Parameters
646 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
647 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
648 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
649 *
650 * Return value
651 * Number of bytes which have been stored in the "Up"-buffer.
652 *
653 * Notes
654 * (1) If there is not enough space in the "Up"-buffer, all data is dropped.
655 * (2) For performance reasons this function does not call Init()
656 * and may only be called after RTT has been initialized.
657 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
658 */
SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)659 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
660 const char* pData;
661 SEGGER_RTT_BUFFER_UP* pRing;
662 unsigned Avail;
663 unsigned RdOff;
664 unsigned WrOff;
665 unsigned Rem;
666
667 pData = (const char *)pBuffer;
668 //
669 // Get "to-host" ring buffer and copy some elements into local variables.
670 //
671 pRing = &_SEGGER_RTT.aUp[BufferIndex];
672 RdOff = pRing->RdOff;
673 WrOff = pRing->WrOff;
674 //
675 // Handle the most common cases fastest.
676 // Which is:
677 // RdOff <= WrOff -> Space until wrap around is free.
678 // AND
679 // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary.
680 //
681 // OR
682 //
683 // RdOff > WrOff -> Space until RdOff - 1 is free.
684 // AND
685 // WrOff + NumBytes < RdOff -> Data fits into buffer
686 //
687 if (RdOff <= WrOff) {
688 //
689 // Get space until WrOff will be at wrap around.
690 //
691 Avail = pRing->SizeOfBuffer - 1u - WrOff ;
692 if (Avail >= NumBytes) {
693 #if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
694 char* pDst;
695 pDst = pRing->pBuffer + WrOff;
696 WrOff += NumBytes;
697 do {
698 *pDst++ = *pData++;
699 } while (--NumBytes);
700 pRing->WrOff = WrOff + NumBytes;
701 #else
702 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
703 pRing->WrOff = WrOff + NumBytes;
704 #endif
705 return 1;
706 }
707 //
708 // If data did not fit into space until wrap around calculate complete space in buffer.
709 //
710 Avail += RdOff;
711 //
712 // If there is still no space for the whole of this output, don't bother.
713 //
714 if (Avail >= NumBytes) {
715 //
716 // OK, we have enough space in buffer. Copy in one or 2 chunks
717 //
718 Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
719 if (Rem > NumBytes) {
720 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
721 pRing->WrOff = WrOff + NumBytes;
722 } else {
723 //
724 // We reach the end of the buffer, so need to wrap around
725 //
726 memcpy(pRing->pBuffer + WrOff, pData, Rem);
727 memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
728 pRing->WrOff = NumBytes - Rem;
729 }
730 return 1;
731 }
732 } else {
733 Avail = RdOff - WrOff - 1u;
734 if (Avail >= NumBytes) {
735 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
736 pRing->WrOff = WrOff + NumBytes;
737 return 1;
738 }
739 }
740 //
741 // If we reach this point no data has been written
742 //
743 return 0;
744 }
745
746 /*********************************************************************
747 *
748 * SEGGER_RTT_WriteNoLock
749 *
750 * Function description
751 * Stores a specified number of characters in SEGGER RTT
752 * control block which is then read by the host.
753 * SEGGER_RTT_WriteNoLock does not lock the application.
754 *
755 * Parameters
756 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
757 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
758 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
759 *
760 * Return value
761 * Number of bytes which have been stored in the "Up"-buffer.
762 *
763 * Notes
764 * (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
765 * (2) For performance reasons this function does not call Init()
766 * and may only be called after RTT has been initialized.
767 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
768 */
SEGGER_RTT_WriteNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)769 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
770 unsigned Status;
771 unsigned Avail;
772 const char* pData;
773 SEGGER_RTT_BUFFER_UP* pRing;
774
775 pData = (const char *)pBuffer;
776 //
777 // Get "to-host" ring buffer.
778 //
779 pRing = &_SEGGER_RTT.aUp[BufferIndex];
780 //
781 // How we output depends upon the mode...
782 //
783 switch (pRing->Flags) {
784 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
785 //
786 // If we are in skip mode and there is no space for the whole
787 // of this output, don't bother.
788 //
789 Avail = _GetAvailWriteSpace(pRing);
790 if (Avail < NumBytes) {
791 Status = 0u;
792 } else {
793 Status = NumBytes;
794 _WriteNoCheck(pRing, pData, NumBytes);
795 }
796 break;
797 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
798 //
799 // If we are in trim mode, trim to what we can output without blocking.
800 //
801 Avail = _GetAvailWriteSpace(pRing);
802 Status = Avail < NumBytes ? Avail : NumBytes;
803 _WriteNoCheck(pRing, pData, Status);
804 break;
805 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
806 //
807 // If we are in blocking mode, output everything.
808 //
809 Status = _WriteBlocking(pRing, pData, NumBytes);
810 break;
811 default:
812 Status = 0u;
813 break;
814 }
815 //
816 // Finish up.
817 //
818 return Status;
819 }
820
821 /*********************************************************************
822 *
823 * SEGGER_RTT_Write
824 *
825 * Function description
826 * Stores a specified number of characters in SEGGER RTT
827 * control block which is then read by the host.
828 *
829 * Parameters
830 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
831 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
832 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
833 *
834 * Return value
835 * Number of bytes which have been stored in the "Up"-buffer.
836 *
837 * Notes
838 * (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
839 */
SEGGER_RTT_Write(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)840 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
841 unsigned Status;
842 //
843 INIT();
844 SEGGER_RTT_LOCK();
845 //
846 // Call the non-locking write function
847 //
848 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
849 //
850 // Finish up.
851 //
852 SEGGER_RTT_UNLOCK();
853 //
854 return Status;
855 }
856
857 /*********************************************************************
858 *
859 * SEGGER_RTT_WriteString
860 *
861 * Function description
862 * Stores string in SEGGER RTT control block.
863 * This data is read by the host.
864 *
865 * Parameters
866 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
867 * s Pointer to string.
868 *
869 * Return value
870 * Number of bytes which have been stored in the "Up"-buffer.
871 *
872 * Notes
873 * (1) If there is not enough space in the "Up"-buffer, depending on configuration,
874 * remaining characters may be dropped or RTT module waits until there is more space in the buffer.
875 * (2) String passed to this function has to be \0 terminated
876 * (3) \0 termination character is *not* stored in RTT buffer
877 */
SEGGER_RTT_WriteString(unsigned BufferIndex,const char * s)878 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
879 unsigned Len;
880
881 Len = STRLEN(s);
882 return SEGGER_RTT_Write(BufferIndex, s, Len);
883 }
884
885 /*********************************************************************
886 *
887 * SEGGER_RTT_GetKey
888 *
889 * Function description
890 * Reads one character from the SEGGER RTT buffer.
891 * Host has previously stored data there.
892 *
893 * Return value
894 * < 0 - No character available (buffer empty).
895 * >= 0 - Character which has been read. (Possible values: 0 - 255)
896 *
897 * Notes
898 * (1) This function is only specified for accesses to RTT buffer 0.
899 */
SEGGER_RTT_GetKey(void)900 int SEGGER_RTT_GetKey(void) {
901 char c;
902 int r;
903
904 r = (int)SEGGER_RTT_Read(0u, &c, 1u);
905 if (r == 1) {
906 r = (int)(unsigned char)c;
907 } else {
908 r = -1;
909 }
910 return r;
911 }
912
913 /*********************************************************************
914 *
915 * SEGGER_RTT_WaitKey
916 *
917 * Function description
918 * Waits until at least one character is avaible in the SEGGER RTT buffer.
919 * Once a character is available, it is read and this function returns.
920 *
921 * Return value
922 * >=0 - Character which has been read.
923 *
924 * Notes
925 * (1) This function is only specified for accesses to RTT buffer 0
926 * (2) This function is blocking if no character is present in RTT buffer
927 */
SEGGER_RTT_WaitKey(void)928 int SEGGER_RTT_WaitKey(void) {
929 int r;
930
931 do {
932 r = SEGGER_RTT_GetKey();
933 } while (r < 0);
934 return r;
935 }
936
937 /*********************************************************************
938 *
939 * SEGGER_RTT_HasKey
940 *
941 * Function description
942 * Checks if at least one character for reading is available in the SEGGER RTT buffer.
943 *
944 * Return value
945 * == 0 - No characters are available to read.
946 * == 1 - At least one character is available.
947 *
948 * Notes
949 * (1) This function is only specified for accesses to RTT buffer 0
950 */
SEGGER_RTT_HasKey(void)951 int SEGGER_RTT_HasKey(void) {
952 unsigned RdOff;
953 int r;
954
955 INIT();
956 RdOff = _SEGGER_RTT.aDown[0].RdOff;
957 if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
958 r = 1;
959 } else {
960 r = 0;
961 }
962 return r;
963 }
964
965 /*********************************************************************
966 *
967 * SEGGER_RTT_HasData
968 *
969 * Function description
970 * Check if there is data from the host in the given buffer.
971 *
972 * Return value:
973 * ==0: No data
974 * !=0: Data in buffer
975 *
976 */
SEGGER_RTT_HasData(unsigned BufferIndex)977 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
978 SEGGER_RTT_BUFFER_DOWN* pRing;
979 unsigned v;
980
981 pRing = &_SEGGER_RTT.aDown[BufferIndex];
982 v = pRing->WrOff;
983 return v - pRing->RdOff;
984 }
985
986 /*********************************************************************
987 *
988 * SEGGER_RTT_AllocDownBuffer
989 *
990 * Function description
991 * Run-time configuration of the next down-buffer (H->T).
992 * The next buffer, which is not used yet is configured.
993 * This includes: Buffer address, size, name, flags, ...
994 *
995 * Parameters
996 * sName Pointer to a constant name string.
997 * pBuffer Pointer to a buffer to be used.
998 * BufferSize Size of the buffer.
999 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1000 *
1001 * Return value
1002 * >= 0 - O.K. Buffer Index
1003 * < 0 - Error
1004 */
SEGGER_RTT_AllocDownBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1005 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1006 int BufferIndex;
1007
1008 INIT();
1009 SEGGER_RTT_LOCK();
1010 BufferIndex = 0;
1011 do {
1012 if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
1013 break;
1014 }
1015 BufferIndex++;
1016 } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
1017 if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
1018 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1019 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
1020 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1021 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
1022 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
1023 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1024 } else {
1025 BufferIndex = -1;
1026 }
1027 SEGGER_RTT_UNLOCK();
1028 return BufferIndex;
1029 }
1030
1031 /*********************************************************************
1032 *
1033 * SEGGER_RTT_AllocUpBuffer
1034 *
1035 * Function description
1036 * Run-time configuration of the next up-buffer (T->H).
1037 * The next buffer, which is not used yet is configured.
1038 * This includes: Buffer address, size, name, flags, ...
1039 *
1040 * Parameters
1041 * sName Pointer to a constant name string.
1042 * pBuffer Pointer to a buffer to be used.
1043 * BufferSize Size of the buffer.
1044 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1045 *
1046 * Return value
1047 * >= 0 - O.K. Buffer Index
1048 * < 0 - Error
1049 */
SEGGER_RTT_AllocUpBuffer(const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1050 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1051 int BufferIndex;
1052
1053 INIT();
1054 SEGGER_RTT_LOCK();
1055 BufferIndex = 0;
1056 do {
1057 if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
1058 break;
1059 }
1060 BufferIndex++;
1061 } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
1062 if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
1063 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1064 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
1065 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1066 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
1067 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
1068 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1069 } else {
1070 BufferIndex = -1;
1071 }
1072 SEGGER_RTT_UNLOCK();
1073 return BufferIndex;
1074 }
1075
1076 /*********************************************************************
1077 *
1078 * SEGGER_RTT_ConfigUpBuffer
1079 *
1080 * Function description
1081 * Run-time configuration of a specific up-buffer (T->H).
1082 * Buffer to be configured is specified by index.
1083 * This includes: Buffer address, size, name, flags, ...
1084 *
1085 * Parameters
1086 * BufferIndex Index of the buffer to configure.
1087 * sName Pointer to a constant name string.
1088 * pBuffer Pointer to a buffer to be used.
1089 * BufferSize Size of the buffer.
1090 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1091 *
1092 * Return value
1093 * >= 0 - O.K.
1094 * < 0 - Error
1095 *
1096 * Additional information
1097 * Buffer 0 is configured on compile-time.
1098 * May only be called once per buffer.
1099 * Buffer name and flags can be reconfigured using the appropriate functions.
1100 */
SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1101 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1102 int r;
1103
1104 INIT();
1105 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1106 SEGGER_RTT_LOCK();
1107 if (BufferIndex > 0u) {
1108 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1109 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
1110 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1111 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
1112 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
1113 }
1114 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1115 SEGGER_RTT_UNLOCK();
1116 r = 0;
1117 } else {
1118 r = -1;
1119 }
1120 return r;
1121 }
1122
1123 /*********************************************************************
1124 *
1125 * SEGGER_RTT_ConfigDownBuffer
1126 *
1127 * Function description
1128 * Run-time configuration of a specific down-buffer (H->T).
1129 * Buffer to be configured is specified by index.
1130 * This includes: Buffer address, size, name, flags, ...
1131 *
1132 * Parameters
1133 * BufferIndex Index of the buffer to configure.
1134 * sName Pointer to a constant name string.
1135 * pBuffer Pointer to a buffer to be used.
1136 * BufferSize Size of the buffer.
1137 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1138 *
1139 * Return value
1140 * >= 0 O.K.
1141 * < 0 Error
1142 *
1143 * Additional information
1144 * Buffer 0 is configured on compile-time.
1145 * May only be called once per buffer.
1146 * Buffer name and flags can be reconfigured using the appropriate functions.
1147 */
SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)1148 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
1149 int r;
1150
1151 INIT();
1152 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1153 SEGGER_RTT_LOCK();
1154 if (BufferIndex > 0u) {
1155 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1156 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
1157 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1158 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
1159 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
1160 }
1161 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1162 SEGGER_RTT_UNLOCK();
1163 r = 0;
1164 } else {
1165 r = -1;
1166 }
1167 return r;
1168 }
1169
1170 /*********************************************************************
1171 *
1172 * SEGGER_RTT_SetNameUpBuffer
1173 *
1174 * Function description
1175 * Run-time configuration of a specific up-buffer name (T->H).
1176 * Buffer to be configured is specified by index.
1177 *
1178 * Parameters
1179 * BufferIndex Index of the buffer to renamed.
1180 * sName Pointer to a constant name string.
1181 *
1182 * Return value
1183 * >= 0 O.K.
1184 * < 0 Error
1185 */
SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex,const char * sName)1186 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
1187 int r;
1188
1189 INIT();
1190 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1191 SEGGER_RTT_LOCK();
1192 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1193 SEGGER_RTT_UNLOCK();
1194 r = 0;
1195 } else {
1196 r = -1;
1197 }
1198 return r;
1199 }
1200
1201 /*********************************************************************
1202 *
1203 * SEGGER_RTT_SetNameDownBuffer
1204 *
1205 * Function description
1206 * Run-time configuration of a specific Down-buffer name (T->H).
1207 * Buffer to be configured is specified by index.
1208 *
1209 * Parameters
1210 * BufferIndex Index of the buffer to renamed.
1211 * sName Pointer to a constant name string.
1212 *
1213 * Return value
1214 * >= 0 O.K.
1215 * < 0 Error
1216 */
SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex,const char * sName)1217 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
1218 int r;
1219
1220 INIT();
1221 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1222 SEGGER_RTT_LOCK();
1223 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1224 SEGGER_RTT_UNLOCK();
1225 r = 0;
1226 } else {
1227 r = -1;
1228 }
1229 return r;
1230 }
1231
1232 /*********************************************************************
1233 *
1234 * SEGGER_RTT_SetFlagsUpBuffer
1235 *
1236 * Function description
1237 * Run-time configuration of specific up-buffer flags (T->H).
1238 * Buffer to be configured is specified by index.
1239 *
1240 * Parameters
1241 * BufferIndex Index of the buffer.
1242 * Flags Flags to set for the buffer.
1243 *
1244 * Return value
1245 * >= 0 O.K.
1246 * < 0 Error
1247 */
SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex,unsigned Flags)1248 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
1249 int r;
1250
1251 INIT();
1252 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1253 SEGGER_RTT_LOCK();
1254 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1255 SEGGER_RTT_UNLOCK();
1256 r = 0;
1257 } else {
1258 r = -1;
1259 }
1260 return r;
1261 }
1262
1263 /*********************************************************************
1264 *
1265 * SEGGER_RTT_SetFlagsDownBuffer
1266 *
1267 * Function description
1268 * Run-time configuration of specific Down-buffer flags (T->H).
1269 * Buffer to be configured is specified by index.
1270 *
1271 * Parameters
1272 * BufferIndex Index of the buffer to renamed.
1273 * Flags Flags to set for the buffer.
1274 *
1275 * Return value
1276 * >= 0 O.K.
1277 * < 0 Error
1278 */
SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex,unsigned Flags)1279 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
1280 int r;
1281
1282 INIT();
1283 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1284 SEGGER_RTT_LOCK();
1285 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1286 SEGGER_RTT_UNLOCK();
1287 r = 0;
1288 } else {
1289 r = -1;
1290 }
1291 return r;
1292 }
1293
1294 /*********************************************************************
1295 *
1296 * SEGGER_RTT_Init
1297 *
1298 * Function description
1299 * Initializes the RTT Control Block.
1300 * Should be used in RAM targets, at start of the application.
1301 *
1302 */
SEGGER_RTT_Init(void)1303 void SEGGER_RTT_Init (void) {
1304 _DoInit();
1305 }
1306
1307 /*********************************************************************
1308 *
1309 * SEGGER_RTT_SetTerminal
1310 *
1311 * Function description
1312 * Sets the terminal to be used for output on channel 0.
1313 *
1314 * Parameters
1315 * TerminalId Index of the terminal.
1316 *
1317 * Return value
1318 * >= 0 O.K.
1319 * < 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)
1320 */
SEGGER_RTT_SetTerminal(char TerminalId)1321 int SEGGER_RTT_SetTerminal (char TerminalId) {
1322 char ac[2];
1323 SEGGER_RTT_BUFFER_UP* pRing;
1324 unsigned Avail;
1325 int r;
1326 //
1327 INIT();
1328 //
1329 r = 0;
1330 ac[0] = 0xFFU;
1331 if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1332 ac[1] = _aTerminalId[(unsigned char)TerminalId];
1333 pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
1334 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
1335 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1336 _ActiveTerminal = TerminalId;
1337 _WriteBlocking(pRing, ac, 2u);
1338 } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
1339 Avail = _GetAvailWriteSpace(pRing);
1340 if (Avail >= 2) {
1341 _ActiveTerminal = TerminalId; // Only change active terminal in case of success
1342 _WriteNoCheck(pRing, ac, 2u);
1343 } else {
1344 r = -1;
1345 }
1346 }
1347 SEGGER_RTT_UNLOCK();
1348 } else {
1349 r = -1;
1350 }
1351 return r;
1352 }
1353
1354 /*********************************************************************
1355 *
1356 * SEGGER_RTT_TerminalOut
1357 *
1358 * Function description
1359 * Writes a string to the given terminal
1360 * without changing the terminal for channel 0.
1361 *
1362 * Parameters
1363 * TerminalId Index of the terminal.
1364 * s String to be printed on the terminal.
1365 *
1366 * Return value
1367 * >= 0 - Number of bytes written.
1368 * < 0 - Error.
1369 *
1370 */
SEGGER_RTT_TerminalOut(char TerminalId,const char * s)1371 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
1372 int Status;
1373 unsigned FragLen;
1374 unsigned Avail;
1375 SEGGER_RTT_BUFFER_UP* pRing;
1376 //
1377 INIT();
1378 //
1379 // Validate terminal ID.
1380 //
1381 if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
1382 //
1383 // Get "to-host" ring buffer.
1384 //
1385 pRing = &_SEGGER_RTT.aUp[0];
1386 //
1387 // Need to be able to change terminal, write data, change back.
1388 // Compute the fixed and variable sizes.
1389 //
1390 FragLen = strlen(s);
1391 //
1392 // How we output depends upon the mode...
1393 //
1394 SEGGER_RTT_LOCK();
1395 Avail = _GetAvailWriteSpace(pRing);
1396 switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1397 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1398 //
1399 // If we are in skip mode and there is no space for the whole
1400 // of this output, don't bother switching terminals at all.
1401 //
1402 if (Avail < (FragLen + 4u)) {
1403 Status = 0;
1404 } else {
1405 _PostTerminalSwitch(pRing, TerminalId);
1406 Status = (int)_WriteBlocking(pRing, s, FragLen);
1407 _PostTerminalSwitch(pRing, _ActiveTerminal);
1408 }
1409 break;
1410 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1411 //
1412 // If we are in trim mode and there is not enough space for everything,
1413 // trim the output but always include the terminal switch. If no room
1414 // for terminal switch, skip that totally.
1415 //
1416 if (Avail < 4u) {
1417 Status = -1;
1418 } else {
1419 _PostTerminalSwitch(pRing, TerminalId);
1420 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1421 _PostTerminalSwitch(pRing, _ActiveTerminal);
1422 }
1423 break;
1424 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1425 //
1426 // If we are in blocking mode, output everything.
1427 //
1428 _PostTerminalSwitch(pRing, TerminalId);
1429 Status = (int)_WriteBlocking(pRing, s, FragLen);
1430 _PostTerminalSwitch(pRing, _ActiveTerminal);
1431 break;
1432 default:
1433 Status = -1;
1434 break;
1435 }
1436 //
1437 // Finish up.
1438 //
1439 SEGGER_RTT_UNLOCK();
1440 } else {
1441 Status = -1;
1442 }
1443 return Status;
1444 }
1445
1446
1447 /*************************** End of file ****************************/
1448