0x6d61726b / mbed-os-retarget-segger-rtt

Dependents:   3_Test_AFE 1_Test_Flash_ADC_RTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SEGGER_RTT.c Source File

SEGGER_RTT.c

00001 /*********************************************************************
00002 *                    SEGGER Microcontroller GmbH                     *
00003 *                        The Embedded Experts                        *
00004 **********************************************************************
00005 *                                                                    *
00006 *            (c) 1995 - 2019 SEGGER Microcontroller GmbH             *
00007 *                                                                    *
00008 *       www.segger.com     Support: support@segger.com               *
00009 *                                                                    *
00010 **********************************************************************
00011 *                                                                    *
00012 *       SEGGER RTT * Real Time Transfer for embedded targets         *
00013 *                                                                    *
00014 **********************************************************************
00015 *                                                                    *
00016 * All rights reserved.                                               *
00017 *                                                                    *
00018 * SEGGER strongly recommends to not make any changes                 *
00019 * to or modify the source code of this software in order to stay     *
00020 * compatible with the RTT protocol and J-Link.                       *
00021 *                                                                    *
00022 * Redistribution and use in source and binary forms, with or         *
00023 * without modification, are permitted provided that the following    *
00024 * conditions are met:                                                *
00025 *                                                                    *
00026 * o Redistributions of source code must retain the above copyright   *
00027 *   notice, this list of conditions and the following disclaimer.    *
00028 *                                                                    *
00029 * o Redistributions in binary form must reproduce the above          *
00030 *   copyright notice, this list of conditions and the following      *
00031 *   disclaimer in the documentation and/or other materials provided  *
00032 *   with the distribution.                                           *
00033 *                                                                    *
00034 * o Neither the name of SEGGER Microcontroller GmbH                  *
00035 *   nor the names of its contributors may be used to endorse or      *
00036 *   promote products derived from this software without specific     *
00037 *   prior written permission.                                        *
00038 *                                                                    *
00039 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
00040 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
00041 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
00042 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
00043 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
00044 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
00045 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
00046 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
00047 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
00048 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
00049 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
00050 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
00051 * DAMAGE.                                                            *
00052 *                                                                    *
00053 **********************************************************************
00054 *                                                                    *
00055 *       RTT version: 6.44i                                           *
00056 *                                                                    *
00057 **********************************************************************
00058 ---------------------------END-OF-HEADER------------------------------
00059 File    : SEGGER_RTT.c
00060 Purpose : Implementation of SEGGER real-time transfer (RTT) which
00061           allows real-time communication on targets which support
00062           debugger memory accesses while the CPU is running.
00063 Revision: Rev: 13375
00064 
00065 Additional information:
00066           Type "int" is assumed to be 32-bits in size
00067           H->T    Host to target communication
00068           T->H    Target to host communication
00069 
00070           RTT channel 0 is always present and reserved for Terminal usage.
00071           Name is fixed to "Terminal"
00072 
00073           Effective buffer size: SizeOfBuffer - 1
00074 
00075           WrOff == RdOff:       Buffer is empty
00076           WrOff == (RdOff - 1): Buffer is full
00077           WrOff >  RdOff:       Free space includes wrap-around
00078           WrOff <  RdOff:       Used space includes wrap-around
00079           (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):  
00080                                 Buffer full and wrap-around after next byte
00081 
00082 
00083 ----------------------------------------------------------------------
00084 */
00085 
00086 #include "SEGGER_RTT.h"
00087 
00088 #include <string.h>                 // for memcpy
00089 
00090 /*********************************************************************
00091 *
00092 *       Configuration, default values
00093 *
00094 **********************************************************************
00095 */
00096 
00097 #ifndef   BUFFER_SIZE_UP
00098   #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
00099 #endif
00100 
00101 #ifndef   BUFFER_SIZE_DOWN
00102   #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
00103 #endif
00104 
00105 #ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
00106   #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
00107 #endif
00108 
00109 #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
00110   #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
00111 #endif
00112 
00113 #ifndef SEGGER_RTT_BUFFER_SECTION
00114   #if defined(SEGGER_RTT_SECTION)
00115     #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
00116   #endif
00117 #endif
00118 
00119 #ifndef   SEGGER_RTT_ALIGNMENT
00120   #define SEGGER_RTT_ALIGNMENT                            0
00121 #endif
00122 
00123 #ifndef   SEGGER_RTT_BUFFER_ALIGNMENT
00124   #define SEGGER_RTT_BUFFER_ALIGNMENT                     0
00125 #endif
00126 
00127 #ifndef   SEGGER_RTT_MODE_DEFAULT
00128   #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
00129 #endif
00130 
00131 #ifndef   SEGGER_RTT_LOCK
00132   #define SEGGER_RTT_LOCK()
00133 #endif
00134 
00135 #ifndef   SEGGER_RTT_UNLOCK
00136   #define SEGGER_RTT_UNLOCK()
00137 #endif
00138 
00139 #ifndef   STRLEN
00140   #define STRLEN(a)                                       strlen((a))
00141 #endif
00142 
00143 #ifndef   SEGGER_RTT_MEMCPY_USE_BYTELOOP
00144   #define SEGGER_RTT_MEMCPY_USE_BYTELOOP                  0
00145 #endif
00146 
00147 #ifndef   SEGGER_RTT_MEMCPY
00148   #ifdef  MEMCPY
00149     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      MEMCPY((pDest), (pSrc), (NumBytes))
00150   #else
00151     #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes)      memcpy((pDest), (pSrc), (NumBytes))
00152   #endif
00153 #endif
00154 
00155 #ifndef   MIN
00156   #define MIN(a, b)         (((a) < (b)) ? (a) : (b))
00157 #endif
00158 
00159 #ifndef   MAX
00160   #define MAX(a, b)         (((a) > (b)) ? (a) : (b))
00161 #endif
00162 //
00163 // For some environments, NULL may not be defined until certain headers are included
00164 //
00165 #ifndef NULL
00166   #define NULL 0
00167 #endif
00168 
00169 /*********************************************************************
00170 *
00171 *       Defines, fixed
00172 *
00173 **********************************************************************
00174 */
00175 #if (defined __ICCARM__) || (defined __ICCRX__)
00176   #define RTT_PRAGMA(P) _Pragma(#P)
00177 #endif
00178 
00179 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
00180   #if (defined __GNUC__)
00181     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
00182   #elif (defined __ICCARM__) || (defined __ICCRX__)
00183     #define PRAGMA(A) _Pragma(#A)
00184 #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
00185                                   Var
00186   #elif (defined __CC_ARM)
00187     #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
00188   #else
00189     #error "Alignment not supported for this compiler."
00190   #endif
00191 #else
00192   #define SEGGER_RTT_ALIGN(Var, Alignment) Var
00193 #endif
00194 
00195 #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
00196   #if (defined __GNUC__)
00197     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
00198   #elif (defined __ICCARM__) || (defined __ICCRX__)
00199 #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
00200                                         Var
00201   #elif (defined __CC_ARM)
00202     #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init))  Var
00203   #else
00204     #error "Section placement not supported for this compiler."
00205   #endif
00206 #else
00207   #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
00208 #endif
00209 
00210 
00211 #if SEGGER_RTT_ALIGNMENT
00212   #define SEGGER_RTT_CB_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
00213 #else
00214   #define SEGGER_RTT_CB_ALIGN(Var)  Var
00215 #endif
00216 
00217 #if SEGGER_RTT_BUFFER_ALIGNMENT
00218   #define SEGGER_RTT_BUFFER_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
00219 #else
00220   #define SEGGER_RTT_BUFFER_ALIGN(Var)  Var
00221 #endif
00222 
00223 
00224 #if defined(SEGGER_RTT_SECTION)
00225   #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
00226 #else
00227   #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
00228 #endif
00229 
00230 #if defined(SEGGER_RTT_BUFFER_SECTION)
00231   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
00232 #else
00233   #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
00234 #endif
00235 
00236 /*********************************************************************
00237 *
00238 *       Static const data
00239 *
00240 **********************************************************************
00241 */
00242 
00243 static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
00244 
00245 /*********************************************************************
00246 *
00247 *       Static data
00248 *
00249 **********************************************************************
00250 */
00251 //
00252 // RTT Control Block and allocate buffers for channel 0
00253 //
00254 SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
00255 
00256 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer  [BUFFER_SIZE_UP]));
00257 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
00258 
00259 static char _ActiveTerminal;
00260 
00261 /*********************************************************************
00262 *
00263 *       Static functions
00264 *
00265 **********************************************************************
00266 */
00267 
00268 /*********************************************************************
00269 *
00270 *       _DoInit()
00271 *
00272 *  Function description
00273 *    Initializes the control block an buffers.
00274 *    May only be called via INIT() to avoid overriding settings.
00275 *
00276 */
00277 #define INIT()  do {                                            \
00278                   if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); }  \
00279                 } while (0)
00280 static void _DoInit(void) {
00281   SEGGER_RTT_CB* p;
00282   //
00283   // Initialize control block
00284   //
00285   p = &_SEGGER_RTT;
00286   p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
00287   p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
00288   //
00289   // Initialize up buffer 0
00290   //
00291   p->aUp[0].sName         = "Terminal";
00292   p->aUp[0].pBuffer       = _acUpBuffer;
00293   p->aUp[0].SizeOfBuffer  = sizeof(_acUpBuffer);
00294   p->aUp[0].RdOff         = 0u;
00295   p->aUp[0].WrOff         = 0u;
00296   p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
00297   //
00298   // Initialize down buffer 0
00299   //
00300   p->aDown[0].sName         = "Terminal";
00301   p->aDown[0].pBuffer       = _acDownBuffer;
00302   p->aDown[0].SizeOfBuffer  = sizeof(_acDownBuffer);
00303   p->aDown[0].RdOff         = 0u;
00304   p->aDown[0].WrOff         = 0u;
00305   p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
00306   //
00307   // Finish initialization of the control block.
00308   // Copy Id string in three steps to make sure "SEGGER RTT" is not found
00309   // in initializer memory (usually flash) by J-Link
00310   //
00311   strcpy(&p->acID[7], "RTT");
00312   strcpy(&p->acID[0], "SEGGER");
00313   p->acID[6] = ' ';
00314 }
00315 
00316 /*********************************************************************
00317 *
00318 *       _WriteBlocking()
00319 *
00320 *  Function description
00321 *    Stores a specified number of characters in SEGGER RTT ring buffer
00322 *    and updates the associated write pointer which is periodically
00323 *    read by the host.
00324 *    The caller is responsible for managing the write chunk sizes as
00325 *    _WriteBlocking() will block until all data has been posted successfully.
00326 *
00327 *  Parameters
00328 *    pRing        Ring buffer to post to.
00329 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00330 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00331 *
00332 *  Return value
00333 *    >= 0 - Number of bytes written into buffer.
00334 */
00335 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
00336   unsigned NumBytesToWrite;
00337   unsigned NumBytesWritten;
00338   unsigned RdOff;
00339   unsigned WrOff;
00340 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00341   char*    pDst;
00342 #endif
00343   //
00344   // Write data to buffer and handle wrap-around if necessary
00345   //
00346   NumBytesWritten = 0u;
00347   WrOff = pRing->WrOff;
00348   do {
00349     RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
00350     if (RdOff > WrOff) {
00351       NumBytesToWrite = RdOff - WrOff - 1u;
00352     } else {
00353       NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
00354     }
00355     NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
00356     NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
00357 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00358     pDst = pRing->pBuffer + WrOff;
00359     NumBytesWritten += NumBytesToWrite;
00360     NumBytes        -= NumBytesToWrite;
00361     WrOff           += NumBytesToWrite;
00362     while (NumBytesToWrite--) {
00363       *pDst++ = *pBuffer++;
00364     };
00365 #else
00366     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
00367     NumBytesWritten += NumBytesToWrite;
00368     pBuffer         += NumBytesToWrite;
00369     NumBytes        -= NumBytesToWrite;
00370     WrOff           += NumBytesToWrite;
00371 #endif
00372     if (WrOff == pRing->SizeOfBuffer) {
00373       WrOff = 0u;
00374     }
00375     pRing->WrOff = WrOff;
00376   } while (NumBytes);
00377   //
00378   return NumBytesWritten;
00379 }
00380 
00381 /*********************************************************************
00382 *
00383 *       _WriteNoCheck()
00384 *
00385 *  Function description
00386 *    Stores a specified number of characters in SEGGER RTT ring buffer
00387 *    and updates the associated write pointer which is periodically
00388 *    read by the host.
00389 *    It is callers responsibility to make sure data actually fits in buffer.
00390 *
00391 *  Parameters
00392 *    pRing        Ring buffer to post to.
00393 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00394 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00395 *
00396 *  Notes
00397 *    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
00398 */
00399 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
00400   unsigned NumBytesAtOnce;
00401   unsigned WrOff;
00402   unsigned Rem;
00403 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00404   char*    pDst;
00405 #endif
00406 
00407   WrOff = pRing->WrOff;
00408   Rem = pRing->SizeOfBuffer - WrOff;
00409   if (Rem > NumBytes) {
00410     //
00411     // All data fits before wrap around
00412     //
00413 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00414     pDst = pRing->pBuffer + WrOff;
00415     WrOff += NumBytes;
00416     while (NumBytes--) {
00417       *pDst++ = *pData++;
00418     };
00419     pRing->WrOff = WrOff;
00420 #else
00421     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
00422     pRing->WrOff = WrOff + NumBytes;
00423 #endif
00424   } else {
00425     //
00426     // We reach the end of the buffer, so need to wrap around
00427     //
00428 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00429     pDst = pRing->pBuffer + WrOff;
00430     NumBytesAtOnce = Rem;
00431     while (NumBytesAtOnce--) {
00432       *pDst++ = *pData++;
00433     };
00434     pDst = pRing->pBuffer;
00435     NumBytesAtOnce = NumBytes - Rem;
00436     while (NumBytesAtOnce--) {
00437       *pDst++ = *pData++;
00438     };
00439     pRing->WrOff = NumBytes - Rem;
00440 #else
00441     NumBytesAtOnce = Rem;
00442     SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
00443     NumBytesAtOnce = NumBytes - Rem;
00444     SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
00445     pRing->WrOff = NumBytesAtOnce;
00446 #endif
00447   }
00448 }
00449 
00450 /*********************************************************************
00451 *
00452 *       _PostTerminalSwitch()
00453 *
00454 *  Function description
00455 *    Switch terminal to the given terminal ID.  It is the caller's
00456 *    responsibility to ensure the terminal ID is correct and there is
00457 *    enough space in the buffer for this to complete successfully.
00458 *
00459 *  Parameters
00460 *    pRing        Ring buffer to post to.
00461 *    TerminalId   Terminal ID to switch to.
00462 */
00463 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
00464   unsigned char ac[2];
00465 
00466   ac[0] = 0xFFu;
00467   ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
00468   _WriteBlocking(pRing, (const char*)ac, 2u);
00469 }
00470 
00471 /*********************************************************************
00472 *
00473 *       _GetAvailWriteSpace()
00474 *
00475 *  Function description
00476 *    Returns the number of bytes that can be written to the ring
00477 *    buffer without blocking.
00478 *
00479 *  Parameters
00480 *    pRing        Ring buffer to check.
00481 *
00482 *  Return value
00483 *    Number of bytes that are free in the buffer.
00484 */
00485 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
00486   unsigned RdOff;
00487   unsigned WrOff;
00488   unsigned r;
00489   //
00490   // Avoid warnings regarding volatile access order.  It's not a problem
00491   // in this case, but dampen compiler enthusiasm.
00492   //
00493   RdOff = pRing->RdOff;
00494   WrOff = pRing->WrOff;
00495   if (RdOff <= WrOff) {
00496     r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
00497   } else {
00498     r = RdOff - WrOff - 1u;
00499   }
00500   return r;
00501 }
00502 
00503 /*********************************************************************
00504 *
00505 *       Public code
00506 *
00507 **********************************************************************
00508 */
00509 /*********************************************************************
00510 *
00511 *       SEGGER_RTT_ReadNoLock()
00512 *
00513 *  Function description
00514 *    Reads characters from SEGGER real-time-terminal control block
00515 *    which have been previously stored by the host.
00516 *    Do not lock against interrupts and multiple access.
00517 *
00518 *  Parameters
00519 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
00520 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
00521 *    BufferSize   Size of the target application buffer.
00522 *
00523 *  Return value
00524 *    Number of bytes that have been read.
00525 */
00526 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
00527   unsigned                NumBytesRem;
00528   unsigned                NumBytesRead;
00529   unsigned                RdOff;
00530   unsigned                WrOff;
00531   unsigned char*          pBuffer;
00532   SEGGER_RTT_BUFFER_DOWN* pRing;
00533 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00534   const char*             pSrc;
00535 #endif
00536   //
00537   INIT();
00538   pRing = &_SEGGER_RTT.aDown[BufferIndex];
00539   pBuffer = (unsigned char*)pData;
00540   RdOff = pRing->RdOff;
00541   WrOff = pRing->WrOff;
00542   NumBytesRead = 0u;
00543   //
00544   // Read from current read position to wrap-around of buffer, first
00545   //
00546   if (RdOff > WrOff) {
00547     NumBytesRem = pRing->SizeOfBuffer - RdOff;
00548     NumBytesRem = MIN(NumBytesRem, BufferSize);
00549 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00550     pSrc = pRing->pBuffer + RdOff;
00551     NumBytesRead += NumBytesRem;
00552     BufferSize   -= NumBytesRem;
00553     RdOff        += NumBytesRem;
00554     while (NumBytesRem--) {
00555       *pBuffer++ = *pSrc++;
00556     };
00557 #else
00558     SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
00559     NumBytesRead += NumBytesRem;
00560     pBuffer      += NumBytesRem;
00561     BufferSize   -= NumBytesRem;
00562     RdOff        += NumBytesRem;
00563 #endif
00564     //
00565     // Handle wrap-around of buffer
00566     //
00567     if (RdOff == pRing->SizeOfBuffer) {
00568       RdOff = 0u;
00569     }
00570   }
00571   //
00572   // Read remaining items of buffer
00573   //
00574   NumBytesRem = WrOff - RdOff;
00575   NumBytesRem = MIN(NumBytesRem, BufferSize);
00576   if (NumBytesRem > 0u) {
00577 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00578     pSrc = pRing->pBuffer + RdOff;
00579     NumBytesRead += NumBytesRem;
00580     BufferSize   -= NumBytesRem;
00581     RdOff        += NumBytesRem;
00582     while (NumBytesRem--) {
00583       *pBuffer++ = *pSrc++;
00584     };
00585 #else
00586     SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
00587     NumBytesRead += NumBytesRem;
00588     pBuffer      += NumBytesRem;
00589     BufferSize   -= NumBytesRem;
00590     RdOff        += NumBytesRem;
00591 #endif
00592   }
00593   if (NumBytesRead) {
00594     pRing->RdOff = RdOff;
00595   }
00596   //
00597   return NumBytesRead;
00598 }
00599 
00600 /*********************************************************************
00601 *
00602 *       SEGGER_RTT_Read
00603 *
00604 *  Function description
00605 *    Reads characters from SEGGER real-time-terminal control block
00606 *    which have been previously stored by the host.
00607 *
00608 *  Parameters
00609 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
00610 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
00611 *    BufferSize   Size of the target application buffer.
00612 *
00613 *  Return value
00614 *    Number of bytes that have been read.
00615 */
00616 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
00617   unsigned NumBytesRead;
00618   //
00619   SEGGER_RTT_LOCK();
00620   //
00621   // Call the non-locking read function
00622   //
00623   NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
00624   //
00625   // Finish up.
00626   //
00627   SEGGER_RTT_UNLOCK();
00628   //
00629   return NumBytesRead;
00630 }
00631 
00632 /*********************************************************************
00633 *
00634 *       SEGGER_RTT_WriteWithOverwriteNoLock
00635 *
00636 *  Function description
00637 *    Stores a specified number of characters in SEGGER RTT
00638 *    control block.
00639 *    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 
00640 *    and overwrites data if the data does not fit into the buffer.
00641 *
00642 *  Parameters
00643 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00644 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00645 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00646 *
00647 *  Notes
00648 *    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
00649 *    (2) For performance reasons this function does not call Init()
00650 *        and may only be called after RTT has been initialized.
00651 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00652 *    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 
00653 *        connection reads RTT data.
00654 */
00655 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00656   const char*           pData;
00657   SEGGER_RTT_BUFFER_UP* pRing;
00658   unsigned              Avail;
00659 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00660   char*                 pDst;
00661 #endif
00662 
00663   pData = (const char *)pBuffer;
00664   //
00665   // Get "to-host" ring buffer and copy some elements into local variables.
00666   //
00667   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00668   //
00669   // Check if we will overwrite data and need to adjust the RdOff.
00670   //
00671   if (pRing->WrOff == pRing->RdOff) {
00672     Avail = pRing->SizeOfBuffer - 1u;
00673   } else if ( pRing->WrOff < pRing->RdOff) {
00674     Avail = pRing->RdOff - pRing->WrOff - 1u;
00675   } else {
00676     Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
00677   }
00678   if (NumBytes > Avail) {
00679     pRing->RdOff += (NumBytes - Avail);
00680     while (pRing->RdOff >= pRing->SizeOfBuffer) {
00681       pRing->RdOff -= pRing->SizeOfBuffer;
00682     }
00683   }
00684   //
00685   // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
00686   //
00687   Avail = pRing->SizeOfBuffer - pRing->WrOff;
00688   do {
00689     if (Avail > NumBytes) {
00690       //
00691       // Last round
00692       //
00693 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00694       pDst = pRing->pBuffer + pRing->WrOff;
00695       Avail = NumBytes;
00696       while (NumBytes--) {
00697         *pDst++ = *pData++;
00698       };
00699       pRing->WrOff += Avail;
00700 #else
00701       SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes);
00702       pRing->WrOff += NumBytes;
00703 #endif
00704       break;
00705     } else {
00706       //
00707       //  Wrap-around necessary, write until wrap-around and reset WrOff
00708       //
00709 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP
00710       pDst = pRing->pBuffer + pRing->WrOff;
00711       NumBytes -= Avail;
00712       while (Avail--) {
00713         *pDst++ = *pData++;
00714       };
00715       pRing->WrOff = 0;
00716 #else
00717       SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail);
00718       pData += Avail;
00719       pRing->WrOff = 0;
00720       NumBytes -= Avail;
00721 #endif
00722       Avail = (pRing->SizeOfBuffer - 1);
00723     }
00724   } while (NumBytes);
00725 }
00726 
00727 /*********************************************************************
00728 *
00729 *       SEGGER_RTT_WriteSkipNoLock
00730 *
00731 *  Function description
00732 *    Stores a specified number of characters in SEGGER RTT
00733 *    control block which is then read by the host.
00734 *    SEGGER_RTT_WriteSkipNoLock does not lock the application and
00735 *    skips all data, if the data does not fit into the buffer.
00736 *
00737 *  Parameters
00738 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00739 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00740 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00741 *                 MUST be > 0!!!
00742 *                 This is done for performance reasons, so no initial check has do be done.
00743 *
00744 *  Return value
00745 *    1: Data has been copied
00746 *    0: No space, data has not been copied
00747 *
00748 *  Notes
00749 *    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
00750 *    (2) For performance reasons this function does not call Init()
00751 *        and may only be called after RTT has been initialized.
00752 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00753 */
00754 #if (RTT_USE_ASM == 0)
00755 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00756   const char*           pData;
00757   SEGGER_RTT_BUFFER_UP* pRing;
00758   unsigned              Avail;
00759   unsigned              RdOff;
00760   unsigned              WrOff;
00761   unsigned              Rem;
00762   //
00763   // Cases:
00764   //   1) RdOff <= WrOff => Space until wrap-around is sufficient
00765   //   2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
00766   //   3) RdOff <  WrOff => No space in buf
00767   //   4) RdOff >  WrOff => Space is sufficient
00768   //   5) RdOff >  WrOff => No space in buf
00769   //
00770   // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
00771   //
00772   pData = (const char *)pBuffer;
00773   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00774   RdOff = pRing->RdOff;
00775   WrOff = pRing->WrOff;
00776   if (RdOff <= WrOff) {                                 // Case 1), 2) or 3)
00777     Avail = pRing->SizeOfBuffer - WrOff - 1u;           // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
00778     if (Avail >= NumBytes) {                            // Case 1)?
00779 CopyStraight:
00780       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00781       pRing->WrOff = WrOff + NumBytes;
00782       return 1;
00783     }
00784     Avail += RdOff;                                     // Space incl. wrap-around
00785     if (Avail >= NumBytes) {                            // Case 2? => If not, we have case 3) (does not fit)
00786       Rem = pRing->SizeOfBuffer - WrOff;                // Space until end of buffer
00787       memcpy(pRing->pBuffer + WrOff, pData, Rem);       // Copy 1st chunk
00788       NumBytes -= Rem;
00789       //
00790       // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
00791       // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
00792       // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
00793       // Therefore, check if 2nd memcpy is necessary at all
00794       //
00795       if (NumBytes) {
00796         memcpy(pRing->pBuffer, pData + Rem, NumBytes);
00797       }
00798       pRing->WrOff = NumBytes;
00799       return 1;
00800     }
00801   } else {                                             // Potential case 4)
00802     Avail = RdOff - WrOff - 1u;
00803     if (Avail >= NumBytes) {                           // Case 4)? => If not, we have case 5) (does not fit)
00804       goto CopyStraight;
00805     }
00806   }
00807   return 0;     // No space in buffer
00808 }
00809 #endif
00810 
00811 /*********************************************************************
00812 *
00813 *       SEGGER_RTT_WriteNoLock
00814 *
00815 *  Function description
00816 *    Stores a specified number of characters in SEGGER RTT
00817 *    control block which is then read by the host.
00818 *    SEGGER_RTT_WriteNoLock does not lock the application.
00819 *
00820 *  Parameters
00821 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00822 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00823 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00824 *
00825 *  Return value
00826 *    Number of bytes which have been stored in the "Up"-buffer.
00827 *
00828 *  Notes
00829 *    (1) Data is stored according to buffer flags.
00830 *    (2) For performance reasons this function does not call Init()
00831 *        and may only be called after RTT has been initialized.
00832 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00833 */
00834 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00835   unsigned              Status;
00836   unsigned              Avail;
00837   const char*           pData;
00838   SEGGER_RTT_BUFFER_UP* pRing;
00839 
00840   pData = (const char *)pBuffer;
00841   //
00842   // Get "to-host" ring buffer.
00843   //
00844   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00845   //
00846   // How we output depends upon the mode...
00847   //
00848   switch (pRing->Flags) {
00849   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
00850     //
00851     // If we are in skip mode and there is no space for the whole
00852     // of this output, don't bother.
00853     //
00854     Avail = _GetAvailWriteSpace(pRing);
00855     if (Avail < NumBytes) {
00856       Status = 0u;
00857     } else {
00858       Status = NumBytes;
00859       _WriteNoCheck(pRing, pData, NumBytes);
00860     }
00861     break;
00862   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
00863     //
00864     // If we are in trim mode, trim to what we can output without blocking.
00865     //
00866     Avail = _GetAvailWriteSpace(pRing);
00867     Status = Avail < NumBytes ? Avail : NumBytes;
00868     _WriteNoCheck(pRing, pData, Status);
00869     break;
00870   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
00871     //
00872     // If we are in blocking mode, output everything.
00873     //
00874     Status = _WriteBlocking(pRing, pData, NumBytes);
00875     break;
00876   default:
00877     Status = 0u;
00878     break;
00879   }
00880   //
00881   // Finish up.
00882   //
00883   return Status;
00884 }
00885 
00886 /*********************************************************************
00887 *
00888 *       SEGGER_RTT_Write
00889 *
00890 *  Function description
00891 *    Stores a specified number of characters in SEGGER RTT
00892 *    control block which is then read by the host.
00893 *
00894 *  Parameters
00895 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00896 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00897 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00898 *
00899 *  Return value
00900 *    Number of bytes which have been stored in the "Up"-buffer.
00901 *
00902 *  Notes
00903 *    (1) Data is stored according to buffer flags.
00904 */
00905 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00906   unsigned Status;
00907   //
00908   INIT();
00909   SEGGER_RTT_LOCK();
00910   //
00911   // Call the non-locking write function
00912   //
00913   Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
00914   //
00915   // Finish up.
00916   //
00917   SEGGER_RTT_UNLOCK();
00918   //
00919   return Status;
00920 }
00921 
00922 /*********************************************************************
00923 *
00924 *       SEGGER_RTT_WriteString
00925 *
00926 *  Function description
00927 *    Stores string in SEGGER RTT control block.
00928 *    This data is read by the host.
00929 *
00930 *  Parameters
00931 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00932 *    s            Pointer to string.
00933 *
00934 *  Return value
00935 *    Number of bytes which have been stored in the "Up"-buffer.
00936 *
00937 *  Notes
00938 *    (1) Data is stored according to buffer flags.
00939 *    (2) String passed to this function has to be \0 terminated
00940 *    (3) \0 termination character is *not* stored in RTT buffer
00941 */
00942 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
00943   unsigned Len;
00944 
00945   Len = STRLEN(s);
00946   return SEGGER_RTT_Write(BufferIndex, s, Len);
00947 }
00948 
00949 /*********************************************************************
00950 *
00951 *       SEGGER_RTT_PutCharSkipNoLock
00952 *
00953 *  Function description
00954 *    Stores a single character/byte in SEGGER RTT buffer.
00955 *    SEGGER_RTT_PutCharSkipNoLock does not lock the application and
00956 *    skips the byte, if it does not fit into the buffer.
00957 *
00958 *  Parameters
00959 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00960 *    c            Byte to be stored.
00961 *
00962 *  Return value
00963 *    Number of bytes which have been stored in the "Up"-buffer.
00964 *
00965 *  Notes
00966 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
00967 *    (2) For performance reasons this function does not call Init()
00968 *        and may only be called after RTT has been initialized.
00969 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00970 */
00971 
00972 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
00973   SEGGER_RTT_BUFFER_UP* pRing;
00974   unsigned              WrOff;
00975   unsigned              Status;
00976   //
00977   // Get "to-host" ring buffer.
00978   //
00979   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00980   //
00981   // Get write position and handle wrap-around if necessary
00982   //
00983   WrOff = pRing->WrOff + 1;
00984   if (WrOff == pRing->SizeOfBuffer) {
00985     WrOff = 0;
00986   }
00987   //
00988   // Output byte if free space is available
00989   //
00990   if (WrOff != pRing->RdOff) {
00991     pRing->pBuffer[pRing->WrOff] = c;
00992     pRing->WrOff = WrOff;
00993     Status = 1;
00994   } else {
00995     Status = 0;
00996   }
00997   //
00998   return Status;
00999 }
01000 
01001 /*********************************************************************
01002 *
01003 *       SEGGER_RTT_PutCharSkip
01004 *
01005 *  Function description
01006 *    Stores a single character/byte in SEGGER RTT buffer.
01007 *
01008 *  Parameters
01009 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
01010 *    c            Byte to be stored.
01011 *
01012 *  Return value
01013 *    Number of bytes which have been stored in the "Up"-buffer.
01014 *
01015 *  Notes
01016 *    (1) If there is not enough space in the "Up"-buffer, the character is dropped.
01017 */
01018 
01019 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
01020   SEGGER_RTT_BUFFER_UP* pRing;
01021   unsigned              WrOff;
01022   unsigned              Status;
01023   //
01024   // Prepare
01025   //
01026   INIT();
01027   SEGGER_RTT_LOCK();
01028   //
01029   // Get "to-host" ring buffer.
01030   //
01031   pRing = &_SEGGER_RTT.aUp[BufferIndex];
01032   //
01033   // Get write position and handle wrap-around if necessary
01034   //
01035   WrOff = pRing->WrOff + 1;
01036   if (WrOff == pRing->SizeOfBuffer) {
01037     WrOff = 0;
01038   }
01039   //
01040   // Output byte if free space is available
01041   //
01042   if (WrOff != pRing->RdOff) {
01043     pRing->pBuffer[pRing->WrOff] = c;
01044     pRing->WrOff = WrOff;
01045     Status = 1;
01046   } else {
01047     Status = 0;
01048   }
01049   //
01050   // Finish up.
01051   //
01052   SEGGER_RTT_UNLOCK();
01053   //
01054   return Status;
01055 }
01056 
01057  /*********************************************************************
01058 *
01059 *       SEGGER_RTT_PutChar
01060 *
01061 *  Function description
01062 *    Stores a single character/byte in SEGGER RTT buffer.
01063 *
01064 *  Parameters
01065 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
01066 *    c            Byte to be stored.
01067 *
01068 *  Return value
01069 *    Number of bytes which have been stored in the "Up"-buffer.
01070 *
01071 *  Notes
01072 *    (1) Data is stored according to buffer flags.
01073 */
01074 
01075 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
01076   SEGGER_RTT_BUFFER_UP* pRing;
01077   unsigned              WrOff;
01078   unsigned              Status;
01079   //
01080   // Prepare
01081   //
01082   INIT();
01083   SEGGER_RTT_LOCK();
01084   //
01085   // Get "to-host" ring buffer.
01086   //
01087   pRing = &_SEGGER_RTT.aUp[BufferIndex];
01088   //
01089   // Get write position and handle wrap-around if necessary
01090   //
01091   WrOff = pRing->WrOff + 1;
01092   if (WrOff == pRing->SizeOfBuffer) {
01093     WrOff = 0;
01094   }
01095   //
01096   // Wait for free space if mode is set to blocking
01097   //
01098   if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
01099     while (WrOff == pRing->RdOff) {
01100       ;
01101     }
01102   }
01103   //
01104   // Output byte if free space is available
01105   //
01106   if (WrOff != pRing->RdOff) {
01107     pRing->pBuffer[pRing->WrOff] = c;
01108     pRing->WrOff = WrOff;
01109     Status = 1;
01110   } else {
01111     Status = 0;
01112   }
01113   //
01114   // Finish up.
01115   //
01116   SEGGER_RTT_UNLOCK();
01117   //
01118   return Status;
01119 }
01120 
01121 /*********************************************************************
01122 *
01123 *       SEGGER_RTT_GetKey
01124 *
01125 *  Function description
01126 *    Reads one character from the SEGGER RTT buffer.
01127 *    Host has previously stored data there.
01128 *
01129 *  Return value
01130 *    <  0 -   No character available (buffer empty).
01131 *    >= 0 -   Character which has been read. (Possible values: 0 - 255)
01132 *
01133 *  Notes
01134 *    (1) This function is only specified for accesses to RTT buffer 0.
01135 */
01136 int SEGGER_RTT_GetKey(void) {
01137   char c;
01138   int r;
01139 
01140   r = (int)SEGGER_RTT_Read(0u, &c, 1u);
01141   if (r == 1) {
01142     r = (int)(unsigned char)c;
01143   } else {
01144     r = -1;
01145   }
01146   return r;
01147 }
01148 
01149 /*********************************************************************
01150 *
01151 *       SEGGER_RTT_WaitKey
01152 *
01153 *  Function description
01154 *    Waits until at least one character is avaible in the SEGGER RTT buffer.
01155 *    Once a character is available, it is read and this function returns.
01156 *
01157 *  Return value
01158 *    >=0 -   Character which has been read.
01159 *
01160 *  Notes
01161 *    (1) This function is only specified for accesses to RTT buffer 0
01162 *    (2) This function is blocking if no character is present in RTT buffer
01163 */
01164 int SEGGER_RTT_WaitKey(void) {
01165   int r;
01166 
01167   do {
01168     r = SEGGER_RTT_GetKey();
01169   } while (r < 0);
01170   return r;
01171 }
01172 
01173 /*********************************************************************
01174 *
01175 *       SEGGER_RTT_HasKey
01176 *
01177 *  Function description
01178 *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
01179 *
01180 *  Return value
01181 *    == 0 -     No characters are available to read.
01182 *    == 1 -     At least one character is available.
01183 *
01184 *  Notes
01185 *    (1) This function is only specified for accesses to RTT buffer 0
01186 */
01187 int SEGGER_RTT_HasKey(void) {
01188   unsigned RdOff;
01189   int r;
01190 
01191   INIT();
01192   RdOff = _SEGGER_RTT.aDown[0].RdOff;
01193   if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
01194     r = 1;
01195   } else {
01196     r = 0;
01197   }
01198   return r;
01199 }
01200 
01201 /*********************************************************************
01202 *
01203 *       SEGGER_RTT_HasData
01204 *
01205 *  Function description
01206 *    Check if there is data from the host in the given buffer.
01207 *
01208 *  Return value:
01209 *  ==0:  No data
01210 *  !=0:  Data in buffer
01211 *
01212 */
01213 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
01214   SEGGER_RTT_BUFFER_DOWN* pRing;
01215   unsigned                v;
01216 
01217   pRing = &_SEGGER_RTT.aDown[BufferIndex];
01218   v = pRing->WrOff;
01219   return v - pRing->RdOff;
01220 }
01221 
01222 /*********************************************************************
01223 *
01224 *       SEGGER_RTT_HasDataUp
01225 *
01226 *  Function description
01227 *    Check if there is data remaining to be sent in the given buffer.
01228 *
01229 *  Return value:
01230 *  ==0:  No data
01231 *  !=0:  Data in buffer
01232 *
01233 */
01234 unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
01235   SEGGER_RTT_BUFFER_UP* pRing;
01236   unsigned                v;
01237 
01238   pRing = &_SEGGER_RTT.aUp[BufferIndex];
01239   v = pRing->RdOff;
01240   return pRing->WrOff - v;
01241 }
01242 
01243 /*********************************************************************
01244 *
01245 *       SEGGER_RTT_AllocDownBuffer
01246 *
01247 *  Function description
01248 *    Run-time configuration of the next down-buffer (H->T).
01249 *    The next buffer, which is not used yet is configured.
01250 *    This includes: Buffer address, size, name, flags, ...
01251 *
01252 *  Parameters
01253 *    sName        Pointer to a constant name string.
01254 *    pBuffer      Pointer to a buffer to be used.
01255 *    BufferSize   Size of the buffer.
01256 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01257 *
01258 *  Return value
01259 *    >= 0 - O.K. Buffer Index
01260 *     < 0 - Error
01261 */
01262 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01263   int BufferIndex;
01264 
01265   INIT();
01266   SEGGER_RTT_LOCK();
01267   BufferIndex = 0;
01268   do {
01269     if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
01270       break;
01271     }
01272     BufferIndex++;
01273   } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
01274   if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
01275     _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
01276     _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
01277     _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
01278     _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
01279     _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
01280     _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
01281   } else {
01282     BufferIndex = -1;
01283   }
01284   SEGGER_RTT_UNLOCK();
01285   return BufferIndex;
01286 }
01287 
01288 /*********************************************************************
01289 *
01290 *       SEGGER_RTT_AllocUpBuffer
01291 *
01292 *  Function description
01293 *    Run-time configuration of the next up-buffer (T->H).
01294 *    The next buffer, which is not used yet is configured.
01295 *    This includes: Buffer address, size, name, flags, ...
01296 *
01297 *  Parameters
01298 *    sName        Pointer to a constant name string.
01299 *    pBuffer      Pointer to a buffer to be used.
01300 *    BufferSize   Size of the buffer.
01301 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01302 *
01303 *  Return value
01304 *    >= 0 - O.K. Buffer Index
01305 *     < 0 - Error
01306 */
01307 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01308   int BufferIndex;
01309 
01310   INIT();
01311   SEGGER_RTT_LOCK();
01312   BufferIndex = 0;
01313   do {
01314     if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
01315       break;
01316     }
01317     BufferIndex++;
01318   } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
01319   if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
01320     _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
01321     _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
01322     _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
01323     _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
01324     _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
01325     _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
01326   } else {
01327     BufferIndex = -1;
01328   }
01329   SEGGER_RTT_UNLOCK();
01330   return BufferIndex;
01331 }
01332 
01333 /*********************************************************************
01334 *
01335 *       SEGGER_RTT_ConfigUpBuffer
01336 *
01337 *  Function description
01338 *    Run-time configuration of a specific up-buffer (T->H).
01339 *    Buffer to be configured is specified by index.
01340 *    This includes: Buffer address, size, name, flags, ...
01341 *
01342 *  Parameters
01343 *    BufferIndex  Index of the buffer to configure.
01344 *    sName        Pointer to a constant name string.
01345 *    pBuffer      Pointer to a buffer to be used.
01346 *    BufferSize   Size of the buffer.
01347 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01348 *
01349 *  Return value
01350 *    >= 0 - O.K.
01351 *     < 0 - Error
01352 *
01353 *  Additional information
01354 *    Buffer 0 is configured on compile-time.
01355 *    May only be called once per buffer.
01356 *    Buffer name and flags can be reconfigured using the appropriate functions.
01357 */
01358 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01359   int r;
01360 
01361   INIT();
01362   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
01363     SEGGER_RTT_LOCK();
01364     if (BufferIndex > 0u) {
01365       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
01366       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
01367       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
01368       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
01369       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
01370     }
01371     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
01372     SEGGER_RTT_UNLOCK();
01373     r =  0;
01374   } else {
01375     r = -1;
01376   }
01377   return r;
01378 }
01379 
01380 /*********************************************************************
01381 *
01382 *       SEGGER_RTT_ConfigDownBuffer
01383 *
01384 *  Function description
01385 *    Run-time configuration of a specific down-buffer (H->T).
01386 *    Buffer to be configured is specified by index.
01387 *    This includes: Buffer address, size, name, flags, ...
01388 *
01389 *  Parameters
01390 *    BufferIndex  Index of the buffer to configure.
01391 *    sName        Pointer to a constant name string.
01392 *    pBuffer      Pointer to a buffer to be used.
01393 *    BufferSize   Size of the buffer.
01394 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01395 *
01396 *  Return value
01397 *    >= 0  O.K.
01398 *     < 0  Error
01399 *
01400 *  Additional information
01401 *    Buffer 0 is configured on compile-time.
01402 *    May only be called once per buffer.
01403 *    Buffer name and flags can be reconfigured using the appropriate functions.
01404 */
01405 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01406   int r;
01407 
01408   INIT();
01409   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
01410     SEGGER_RTT_LOCK();
01411     if (BufferIndex > 0u) {
01412       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
01413       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
01414       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
01415       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
01416       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
01417     }
01418     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
01419     SEGGER_RTT_UNLOCK();
01420     r =  0;
01421   } else {
01422     r = -1;
01423   }
01424   return r;
01425 }
01426 
01427 /*********************************************************************
01428 *
01429 *       SEGGER_RTT_SetNameUpBuffer
01430 *
01431 *  Function description
01432 *    Run-time configuration of a specific up-buffer name (T->H).
01433 *    Buffer to be configured is specified by index.
01434 *
01435 *  Parameters
01436 *    BufferIndex  Index of the buffer to renamed.
01437 *    sName        Pointer to a constant name string.
01438 *
01439 *  Return value
01440 *    >= 0  O.K.
01441 *     < 0  Error
01442 */
01443 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
01444   int r;
01445 
01446   INIT();
01447   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
01448     SEGGER_RTT_LOCK();
01449     _SEGGER_RTT.aUp[BufferIndex].sName = sName;
01450     SEGGER_RTT_UNLOCK();
01451     r =  0;
01452   } else {
01453     r = -1;
01454   }
01455   return r;
01456 }
01457 
01458 /*********************************************************************
01459 *
01460 *       SEGGER_RTT_SetNameDownBuffer
01461 *
01462 *  Function description
01463 *    Run-time configuration of a specific Down-buffer name (T->H).
01464 *    Buffer to be configured is specified by index.
01465 *
01466 *  Parameters
01467 *    BufferIndex  Index of the buffer to renamed.
01468 *    sName        Pointer to a constant name string.
01469 *
01470 *  Return value
01471 *    >= 0  O.K.
01472 *     < 0  Error
01473 */
01474 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
01475   int r;
01476 
01477   INIT();
01478   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
01479     SEGGER_RTT_LOCK();
01480     _SEGGER_RTT.aDown[BufferIndex].sName = sName;
01481     SEGGER_RTT_UNLOCK();
01482     r =  0;
01483   } else {
01484     r = -1;
01485   }
01486   return r;
01487 }
01488 
01489 /*********************************************************************
01490 *
01491 *       SEGGER_RTT_SetFlagsUpBuffer
01492 *
01493 *  Function description
01494 *    Run-time configuration of specific up-buffer flags (T->H).
01495 *    Buffer to be configured is specified by index.
01496 *
01497 *  Parameters
01498 *    BufferIndex  Index of the buffer.
01499 *    Flags        Flags to set for the buffer.
01500 *
01501 *  Return value
01502 *    >= 0  O.K.
01503 *     < 0  Error
01504 */
01505 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
01506   int r;
01507 
01508   INIT();
01509   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
01510     SEGGER_RTT_LOCK();
01511     _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
01512     SEGGER_RTT_UNLOCK();
01513     r =  0;
01514   } else {
01515     r = -1;
01516   }
01517   return r;
01518 }
01519 
01520 /*********************************************************************
01521 *
01522 *       SEGGER_RTT_SetFlagsDownBuffer
01523 *
01524 *  Function description
01525 *    Run-time configuration of specific Down-buffer flags (T->H).
01526 *    Buffer to be configured is specified by index.
01527 *
01528 *  Parameters
01529 *    BufferIndex  Index of the buffer to renamed.
01530 *    Flags        Flags to set for the buffer.
01531 *
01532 *  Return value
01533 *    >= 0  O.K.
01534 *     < 0  Error
01535 */
01536 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
01537   int r;
01538 
01539   INIT();
01540   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
01541     SEGGER_RTT_LOCK();
01542     _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
01543     SEGGER_RTT_UNLOCK();
01544     r =  0;
01545   } else {
01546     r = -1;
01547   }
01548   return r;
01549 }
01550 
01551 /*********************************************************************
01552 *
01553 *       SEGGER_RTT_Init
01554 *
01555 *  Function description
01556 *    Initializes the RTT Control Block.
01557 *    Should be used in RAM targets, at start of the application.
01558 *
01559 */
01560 void SEGGER_RTT_Init (void) {
01561   _DoInit();
01562 }
01563 
01564 /*********************************************************************
01565 *
01566 *       SEGGER_RTT_SetTerminal
01567 *
01568 *  Function description
01569 *    Sets the terminal to be used for output on channel 0.
01570 *
01571 *  Parameters
01572 *    TerminalId  Index of the terminal.
01573 *
01574 *  Return value
01575 *    >= 0  O.K.
01576 *     < 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)
01577 */
01578 int SEGGER_RTT_SetTerminal (char TerminalId) {
01579   unsigned char         ac[2];
01580   SEGGER_RTT_BUFFER_UP* pRing;
01581   unsigned Avail;
01582   int r;
01583   //
01584   INIT();
01585   //
01586   r = 0;
01587   ac[0] = 0xFFu;
01588   if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
01589     ac[1] = _aTerminalId[(unsigned char)TerminalId];
01590     pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
01591     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
01592     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
01593       _ActiveTerminal = TerminalId;
01594       _WriteBlocking(pRing, (const char*)ac, 2u);
01595     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
01596       Avail = _GetAvailWriteSpace(pRing);
01597       if (Avail >= 2) {
01598         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
01599         _WriteNoCheck(pRing, (const char*)ac, 2u);
01600       } else {
01601         r = -1;
01602       }
01603     }
01604     SEGGER_RTT_UNLOCK();
01605   } else {
01606     r = -1;
01607   }
01608   return r;
01609 }
01610 
01611 /*********************************************************************
01612 *
01613 *       SEGGER_RTT_TerminalOut
01614 *
01615 *  Function description
01616 *    Writes a string to the given terminal
01617 *     without changing the terminal for channel 0.
01618 *
01619 *  Parameters
01620 *    TerminalId   Index of the terminal.
01621 *    s            String to be printed on the terminal.
01622 *
01623 *  Return value
01624 *    >= 0 - Number of bytes written.
01625 *     < 0 - Error.
01626 *
01627 */
01628 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
01629   int                   Status;
01630   unsigned              FragLen;
01631   unsigned              Avail;
01632   SEGGER_RTT_BUFFER_UP* pRing;
01633   //
01634   INIT();
01635   //
01636   // Validate terminal ID.
01637   //
01638   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
01639     //
01640     // Get "to-host" ring buffer.
01641     //
01642     pRing = &_SEGGER_RTT.aUp[0];
01643     //
01644     // Need to be able to change terminal, write data, change back.
01645     // Compute the fixed and variable sizes.
01646     //
01647     FragLen = STRLEN(s);
01648     //
01649     // How we output depends upon the mode...
01650     //
01651     SEGGER_RTT_LOCK();
01652     Avail = _GetAvailWriteSpace(pRing);
01653     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
01654     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
01655       //
01656       // If we are in skip mode and there is no space for the whole
01657       // of this output, don't bother switching terminals at all.
01658       //
01659       if (Avail < (FragLen + 4u)) {
01660         Status = 0;
01661       } else {
01662         _PostTerminalSwitch(pRing, TerminalId);
01663         Status = (int)_WriteBlocking(pRing, s, FragLen);
01664         _PostTerminalSwitch(pRing, _ActiveTerminal);
01665       }
01666       break;
01667     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
01668       //
01669       // If we are in trim mode and there is not enough space for everything,
01670       // trim the output but always include the terminal switch.  If no room
01671       // for terminal switch, skip that totally.
01672       //
01673       if (Avail < 4u) {
01674         Status = -1;
01675       } else {
01676         _PostTerminalSwitch(pRing, TerminalId);
01677         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
01678         _PostTerminalSwitch(pRing, _ActiveTerminal);
01679       }
01680       break;
01681     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
01682       //
01683       // If we are in blocking mode, output everything.
01684       //
01685       _PostTerminalSwitch(pRing, TerminalId);
01686       Status = (int)_WriteBlocking(pRing, s, FragLen);
01687       _PostTerminalSwitch(pRing, _ActiveTerminal);
01688       break;
01689     default:
01690       Status = -1;
01691       break;
01692     }
01693     //
01694     // Finish up.
01695     //
01696     SEGGER_RTT_UNLOCK();
01697   } else {
01698     Status = -1;
01699   }
01700   return Status;
01701 }
01702 
01703 
01704 /*************************** End of file ****************************/