source: trunk/firmware/SEGGER_RTT.c @ 14

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