Jurica Resetar / aconno_SEGGER_RTT

Dependents:   acnSensa_LIS acd52832_Indoor_Posit_Peripheral acd52832_Indoor_Posit_Central iBeacon acnsensa ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SEGGER_RTT.c Source File

SEGGER_RTT.c

00001 /*********************************************************************
00002 *               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
00003 *       Solutions for real time microcontroller applications         *
00004 **********************************************************************
00005 *                                                                    *
00006 *       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
00007 *                                                                    *
00008 *       www.segger.com     Support: support@segger.com               *
00009 *                                                                    *
00010 **********************************************************************
00011 *                                                                    *
00012 * All rights reserved.                                               *
00013 *                                                                    *
00014 * * This software may in its unmodified form be freely redistributed *
00015 *   in source form.                                                  *
00016 * * The source code may be modified, provided the source code        *
00017 *   retains the above copyright notice, this list of conditions and  *
00018 *   the following disclaimer.                                        *
00019 * * Modified versions of this software in source or linkable form    *
00020 *   may not be distributed without prior consent of SEGGER.          *
00021 * * This software may only be used for communication with SEGGER     *
00022 *   J-Link debug probes.                                             *
00023 *                                                                    *
00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
00025 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
00026 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
00027 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
00028 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
00029 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
00030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
00031 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
00032 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
00033 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
00034 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
00035 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
00036 * DAMAGE.                                                            *
00037 *                                                                    *
00038 **********************************************************************
00039 ---------------------------END-OF-HEADER------------------------------
00040 File    : SEGGER_RTT.c
00041 Purpose : Implementation of SEGGER real-time transfer (RTT) which
00042           allows real-time communication on targets which support
00043           debugger memory accesses while the CPU is running.
00044 
00045 Additional information:
00046           Type "int" is assumed to be 32-bits in size
00047           H->T    Host to target communication
00048           T->H    Target to host communication
00049 
00050           RTT channel 0 is always present and reserved for Terminal usage.
00051           Name is fixed to "Terminal"
00052 
00053           Effective buffer size: SizeOfBuffer - 1
00054 
00055           WrOff == RdOff:       Buffer is empty
00056           WrOff == (RdOff - 1): Buffer is full
00057           WrOff >  RdOff:       Free space includes wrap-around
00058           WrOff <  RdOff:       Used space includes wrap-around
00059           (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):  
00060                                 Buffer full and wrap-around after next byte
00061 
00062 
00063 ----------------------------------------------------------------------
00064 */
00065 
00066 #include "SEGGER_RTT.h"
00067 
00068 #include <string.h>                 // for memcpy
00069 
00070 /*********************************************************************
00071 *
00072 *       Configuration, default values
00073 *
00074 **********************************************************************
00075 */
00076 
00077 #ifndef   BUFFER_SIZE_UP
00078   #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
00079 #endif
00080 
00081 #ifndef   BUFFER_SIZE_DOWN
00082   #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
00083 #endif
00084 
00085 #ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
00086   #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
00087 #endif
00088 
00089 #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
00090   #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
00091 #endif
00092 
00093 #ifndef SEGGER_RTT_BUFFER_SECTION
00094   #if defined SEGGER_RTT_SECTION
00095     #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
00096   #endif
00097 #endif
00098 
00099 #ifndef   SEGGER_RTT_MODE_DEFAULT
00100   #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
00101 #endif
00102 
00103 #ifndef   SEGGER_RTT_LOCK
00104   #define SEGGER_RTT_LOCK()
00105 #endif
00106 
00107 #ifndef   SEGGER_RTT_UNLOCK
00108   #define SEGGER_RTT_UNLOCK()
00109 #endif
00110 
00111 #ifndef   STRLEN
00112   #define STRLEN(a)                                       strlen((a))
00113 #endif
00114 
00115 #ifndef   MEMCPY
00116   #define MEMCPY(pDest, pSrc, NumBytes)                   memcpy((pDest), (pSrc), (NumBytes))
00117 #endif
00118 
00119 #ifndef   MIN
00120   #define MIN(a, b)         (((a) < (b)) ? (a) : (b))
00121 #endif
00122 
00123 #ifndef   MAX
00124   #define MAX(a, b)         (((a) > (b)) ? (a) : (b))
00125 #endif
00126 //
00127 // For some environments, NULL may not be defined until certain headers are included
00128 //
00129 #ifndef NULL
00130   #define NULL 0
00131 #endif
00132 
00133 /*********************************************************************
00134 *
00135 *       Static const data
00136 *
00137 **********************************************************************
00138 */
00139 
00140 static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
00141 
00142 /*********************************************************************
00143 *
00144 *       Static data
00145 *
00146 **********************************************************************
00147 */
00148 //
00149 // RTT Control Block and allocate buffers for channel 0
00150 //
00151 #ifdef SEGGER_RTT_SECTION
00152   #if (defined __GNUC__)
00153     __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT;
00154   #elif (defined __ICCARM__) || (defined __ICCRX__)
00155     #pragma location=SEGGER_RTT_SECTION
00156     SEGGER_RTT_CB _SEGGER_RTT;
00157   #elif (defined __CC_ARM__)
00158     __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT;
00159   #else
00160     SEGGER_RTT_CB _SEGGER_RTT;
00161   #endif
00162 #else
00163     SEGGER_RTT_CB _SEGGER_RTT;
00164 #endif
00165 
00166 #ifdef SEGGER_RTT_BUFFER_SECTION
00167   #if (defined __GNUC__)
00168     __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer  [BUFFER_SIZE_UP];
00169     __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN];
00170   #elif (defined __ICCARM__) || (defined __ICCRX__)
00171     #pragma location=SEGGER_RTT_BUFFER_SECTION
00172     static char _acUpBuffer  [BUFFER_SIZE_UP];
00173     #pragma location=SEGGER_RTT_BUFFER_SECTION
00174     static char _acDownBuffer[BUFFER_SIZE_DOWN];
00175   #elif (defined __CC_ARM__)
00176     __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer  [BUFFER_SIZE_UP];
00177     __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN];
00178   #else
00179     static char _acUpBuffer  [BUFFER_SIZE_UP];
00180     static char _acDownBuffer[BUFFER_SIZE_DOWN];
00181   #endif
00182 #else
00183     static char _acUpBuffer  [BUFFER_SIZE_UP];
00184     static char _acDownBuffer[BUFFER_SIZE_DOWN];
00185 #endif
00186 
00187 static char _ActiveTerminal;
00188 
00189 /*********************************************************************
00190 *
00191 *       Static functions
00192 *
00193 **********************************************************************
00194 */
00195 
00196 /*********************************************************************
00197 *
00198 *       _DoInit()
00199 *
00200 *  Function description
00201 *    Initializes the control block an buffers.
00202 *    May only be called via INIT() to avoid overriding settings.
00203 *
00204 */
00205 #define INIT()  do {                                            \
00206                   if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); }  \
00207                 } while (0)
00208 static void _DoInit(void) {
00209   SEGGER_RTT_CB* p;
00210   //
00211   // Initialize control block
00212   //
00213   p = &_SEGGER_RTT;
00214   p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
00215   p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
00216   //
00217   // Initialize up buffer 0
00218   //
00219   p->aUp[0].sName         = "Terminal";
00220   p->aUp[0].pBuffer       = _acUpBuffer;
00221   p->aUp[0].SizeOfBuffer  = sizeof(_acUpBuffer);
00222   p->aUp[0].RdOff         = 0u;
00223   p->aUp[0].WrOff         = 0u;
00224   p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
00225   //
00226   // Initialize down buffer 0
00227   //
00228   p->aDown[0].sName         = "Terminal";
00229   p->aDown[0].pBuffer       = _acDownBuffer;
00230   p->aDown[0].SizeOfBuffer  = sizeof(_acDownBuffer);
00231   p->aDown[0].RdOff         = 0u;
00232   p->aDown[0].WrOff         = 0u;
00233   p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
00234   //
00235   // Finish initialization of the control block.
00236   // Copy Id string in three steps to make sure "SEGGER RTT" is not found
00237   // in initializer memory (usually flash) by J-Link
00238   //
00239   strcpy(&p->acID[7], "RTT");
00240   strcpy(&p->acID[0], "SEGGER");
00241   p->acID[6] = ' ';
00242 }
00243 
00244 /*********************************************************************
00245 *
00246 *       _WriteBlocking()
00247 *
00248 *  Function description
00249 *    Stores a specified number of characters in SEGGER RTT ring buffer
00250 *    and updates the associated write pointer which is periodically
00251 *    read by the host.
00252 *    The caller is responsible for managing the write chunk sizes as
00253 *    _WriteBlocking() will block until all data has been posted successfully.
00254 *
00255 *  Parameters
00256 *    pRing        Ring buffer to post to.
00257 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00258 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00259 *
00260 *  Return value
00261 *    >= 0 - Number of bytes written into buffer.
00262 */
00263 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
00264   unsigned NumBytesToWrite;
00265   unsigned NumBytesWritten;
00266   unsigned RdOff;
00267   unsigned WrOff;
00268   //
00269   // Write data to buffer and handle wrap-around if necessary
00270   //
00271   NumBytesWritten = 0u;
00272   WrOff = pRing->WrOff;
00273   do {
00274     RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
00275     if (RdOff > WrOff) {
00276       NumBytesToWrite = RdOff - WrOff - 1u;
00277     } else {
00278       NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
00279     }
00280     NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
00281     NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
00282     memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
00283     NumBytesWritten += NumBytesToWrite;
00284     pBuffer         += NumBytesToWrite;
00285     NumBytes        -= NumBytesToWrite;
00286     WrOff           += NumBytesToWrite;
00287     if (WrOff == pRing->SizeOfBuffer) {
00288       WrOff = 0u;
00289     }
00290     pRing->WrOff = WrOff;
00291   } while (NumBytes);
00292   //
00293   return NumBytesWritten;
00294 }
00295 
00296 /*********************************************************************
00297 *
00298 *       _WriteNoCheck()
00299 *
00300 *  Function description
00301 *    Stores a specified number of characters in SEGGER RTT ring buffer
00302 *    and updates the associated write pointer which is periodically
00303 *    read by the host.
00304 *    It is callers responsibility to make sure data actually fits in buffer.
00305 *
00306 *  Parameters
00307 *    pRing        Ring buffer to post to.
00308 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00309 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00310 *
00311 *  Notes
00312 *    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
00313 */
00314 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
00315   unsigned NumBytesAtOnce;
00316   unsigned WrOff;
00317   unsigned Rem;
00318 
00319   WrOff = pRing->WrOff;
00320   Rem = pRing->SizeOfBuffer - WrOff;
00321   if (Rem > NumBytes) {
00322     //
00323     // All data fits before wrap around
00324     //
00325     memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00326     pRing->WrOff = WrOff + NumBytes;
00327   } else {
00328     //
00329     // We reach the end of the buffer, so need to wrap around
00330     //
00331     NumBytesAtOnce = Rem;
00332     memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
00333     NumBytesAtOnce = NumBytes - Rem;
00334     memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
00335     pRing->WrOff = NumBytesAtOnce;
00336   }
00337 }
00338 
00339 /*********************************************************************
00340 *
00341 *       _PostTerminalSwitch()
00342 *
00343 *  Function description
00344 *    Switch terminal to the given terminal ID.  It is the caller's
00345 *    responsibility to ensure the terminal ID is correct and there is
00346 *    enough space in the buffer for this to complete successfully.
00347 *
00348 *  Parameters
00349 *    pRing        Ring buffer to post to.
00350 *    TerminalId   Terminal ID to switch to.
00351 */
00352 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
00353   char ac[2];
00354 
00355   ac[0] = 0xFFu;
00356   ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
00357   _WriteBlocking(pRing, ac, 2u);
00358 }
00359 
00360 /*********************************************************************
00361 *
00362 *       _GetAvailWriteSpace()
00363 *
00364 *  Function description
00365 *    Returns the number of bytes that can be written to the ring
00366 *    buffer without blocking.
00367 *
00368 *  Parameters
00369 *    pRing        Ring buffer to check.
00370 *
00371 *  Return value
00372 *    Number of bytes that are free in the buffer.
00373 */
00374 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
00375   unsigned RdOff;
00376   unsigned WrOff;
00377   unsigned r;
00378   //
00379   // Avoid warnings regarding volatile access order.  It's not a problem
00380   // in this case, but dampen compiler enthusiasm.
00381   //
00382   RdOff = pRing->RdOff;
00383   WrOff = pRing->WrOff;
00384   if (RdOff <= WrOff) {
00385     r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
00386   } else {
00387     r = RdOff - WrOff - 1u;
00388   }
00389   return r;
00390 }
00391 
00392 /*********************************************************************
00393 *
00394 *       Public code
00395 *
00396 **********************************************************************
00397 */
00398 /*********************************************************************
00399 *
00400 *       SEGGER_RTT_ReadNoLock()
00401 *
00402 *  Function description
00403 *    Reads characters from SEGGER real-time-terminal control block
00404 *    which have been previously stored by the host.
00405 *    Do not lock against interrupts and multiple access.
00406 *
00407 *  Parameters
00408 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
00409 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
00410 *    BufferSize   Size of the target application buffer.
00411 *
00412 *  Return value
00413 *    Number of bytes that have been read.
00414 */
00415 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
00416   unsigned                NumBytesRem;
00417   unsigned                NumBytesRead;
00418   unsigned                RdOff;
00419   unsigned                WrOff;
00420   unsigned char*          pBuffer;
00421   SEGGER_RTT_BUFFER_DOWN* pRing;
00422   //
00423   INIT();
00424   pRing = &_SEGGER_RTT.aDown[BufferIndex];
00425   pBuffer = (unsigned char*)pData;
00426   RdOff = pRing->RdOff;
00427   WrOff = pRing->WrOff;
00428   NumBytesRead = 0u;
00429   //
00430   // Read from current read position to wrap-around of buffer, first
00431   //
00432   if (RdOff > WrOff) {
00433     NumBytesRem = pRing->SizeOfBuffer - RdOff;
00434     NumBytesRem = MIN(NumBytesRem, BufferSize);
00435     memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
00436     NumBytesRead += NumBytesRem;
00437     pBuffer      += NumBytesRem;
00438     BufferSize   -= NumBytesRem;
00439     RdOff        += NumBytesRem;
00440     //
00441     // Handle wrap-around of buffer
00442     //
00443     if (RdOff == pRing->SizeOfBuffer) {
00444       RdOff = 0u;
00445     }
00446   }
00447   //
00448   // Read remaining items of buffer
00449   //
00450   NumBytesRem = WrOff - RdOff;
00451   NumBytesRem = MIN(NumBytesRem, BufferSize);
00452   if (NumBytesRem > 0u) {
00453     memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
00454     NumBytesRead += NumBytesRem;
00455     pBuffer      += NumBytesRem;
00456     BufferSize   -= NumBytesRem;
00457     RdOff        += NumBytesRem;
00458   }
00459   if (NumBytesRead) {
00460     pRing->RdOff = RdOff;
00461   }
00462   //
00463   return NumBytesRead;
00464 }
00465 
00466 /*********************************************************************
00467 *
00468 *       SEGGER_RTT_Read
00469 *
00470 *  Function description
00471 *    Reads characters from SEGGER real-time-terminal control block
00472 *    which have been previously stored by the host.
00473 *
00474 *  Parameters
00475 *    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
00476 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
00477 *    BufferSize   Size of the target application buffer.
00478 *
00479 *  Return value
00480 *    Number of bytes that have been read.
00481 */
00482 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
00483   unsigned NumBytesRead;
00484   //
00485   SEGGER_RTT_LOCK();
00486   //
00487   // Call the non-locking read function
00488   //
00489   NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
00490   //
00491   // Finish up.
00492   //
00493   SEGGER_RTT_UNLOCK();
00494   //
00495   return NumBytesRead;
00496 }
00497 
00498 /*********************************************************************
00499 *
00500 *       SEGGER_RTT_WriteWithOverwriteNoLock
00501 *
00502 *  Function description
00503 *    Stores a specified number of characters in SEGGER RTT
00504 *    control block.
00505 *    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 
00506 *    and overwrites data if the data does not fit into the buffer.
00507 *
00508 *  Parameters
00509 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00510 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00511 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00512 *
00513 *  Notes
00514 *    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
00515 *    (2) For performance reasons this function does not call Init()
00516 *        and may only be called after RTT has been initialized.
00517 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00518 *    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 
00519 *        connection reads RTT data.
00520 */
00521 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00522   const char*           pData;
00523   SEGGER_RTT_BUFFER_UP* pRing;
00524   unsigned              Avail;
00525 
00526   pData = (const char *)pBuffer;
00527   //
00528   // Get "to-host" ring buffer and copy some elements into local variables.
00529   //
00530   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00531   //
00532   // Check if we will overwrite data and need to adjust the RdOff.
00533   //
00534   if (pRing->WrOff == pRing->RdOff) {
00535     Avail = pRing->SizeOfBuffer - 1u;
00536   } else if ( pRing->WrOff < pRing->RdOff) {
00537     Avail = pRing->RdOff - pRing->WrOff - 1u;
00538   } else {
00539     Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
00540   }
00541   if (NumBytes > Avail) {
00542     pRing->RdOff += (NumBytes - Avail);
00543     while (pRing->RdOff >= pRing->SizeOfBuffer) {
00544       pRing->RdOff -= pRing->SizeOfBuffer;
00545     }
00546   }
00547   //
00548   // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
00549   //
00550   Avail = pRing->SizeOfBuffer - pRing->WrOff;
00551   do {
00552     if (Avail > NumBytes) {
00553       //
00554       // Last round
00555       //
00556 #if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
00557       char* pDst;
00558       pDst = pRing->pBuffer + pRing->WrOff;
00559       pRing->WrOff += NumBytes;
00560       do {
00561         *pDst++ = *pData++;
00562       } while (--NumBytes);
00563 #else
00564       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00565       pRing->WrOff += NumBytes;
00566 #endif
00567       break;  //Alternatively: NumBytes = 0;
00568     } else {
00569       //
00570       //  Wrap-around necessary, write until wrap-around and reset WrOff
00571       //
00572       memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
00573       pData += Avail;
00574       pRing->WrOff = 0;
00575       NumBytes -= Avail;
00576       Avail = (pRing->SizeOfBuffer - 1);
00577     }
00578   } while (NumBytes);
00579 }
00580 
00581 /*********************************************************************
00582 *
00583 *       SEGGER_RTT_WriteSkipNoLock
00584 *
00585 *  Function description
00586 *    Stores a specified number of characters in SEGGER RTT
00587 *    control block which is then read by the host.
00588 *    SEGGER_RTT_WriteSkipNoLock does not lock the application and
00589 *    skips all data, if the data does not fit into the buffer.
00590 *
00591 *  Parameters
00592 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00593 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00594 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00595 *
00596 *  Return value
00597 *    Number of bytes which have been stored in the "Up"-buffer.
00598 *
00599 *  Notes
00600 *    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
00601 *    (2) For performance reasons this function does not call Init()
00602 *        and may only be called after RTT has been initialized.
00603 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00604 */
00605 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00606   const char*           pData;
00607   SEGGER_RTT_BUFFER_UP* pRing;
00608   unsigned              Avail;
00609   unsigned              RdOff;
00610   unsigned              WrOff;
00611   unsigned              Rem;
00612 
00613   pData = (const char *)pBuffer;
00614   //
00615   // Get "to-host" ring buffer and copy some elements into local variables.
00616   //
00617   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00618   RdOff = pRing->RdOff;
00619   WrOff = pRing->WrOff;
00620   //
00621   // Handle the most common cases fastest.
00622   // Which is:
00623   //    RdOff <= WrOff -> Space until wrap around is free.
00624   //  AND
00625   //    WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary.
00626   //
00627   //  OR
00628   //
00629   //    RdOff > WrOff -> Space until RdOff - 1 is free.
00630   //  AND
00631   //    WrOff + NumBytes < RdOff -> Data fits into buffer
00632   //
00633   if (RdOff <= WrOff) {
00634     //
00635     // Get space until WrOff will be at wrap around.
00636     //
00637     Avail = pRing->SizeOfBuffer - 1u - WrOff ;
00638     if (Avail >= NumBytes) {
00639 #if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
00640       char* pDst;
00641       pDst = pRing->pBuffer + WrOff;
00642       WrOff += NumBytes;
00643       do {
00644         *pDst++ = *pData++;
00645       } while (--NumBytes);
00646       pRing->WrOff = WrOff + NumBytes;
00647 #else
00648       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00649       pRing->WrOff = WrOff + NumBytes;
00650 #endif
00651       return 1;
00652     }
00653     //
00654     // If data did not fit into space until wrap around calculate complete space in buffer.
00655     //
00656     Avail += RdOff;
00657     //
00658     // If there is still no space for the whole of this output, don't bother.
00659     //
00660     if (Avail >= NumBytes) {
00661       //
00662       //  OK, we have enough space in buffer. Copy in one or 2 chunks
00663       //
00664       Rem = pRing->SizeOfBuffer - WrOff;      // Space until end of buffer
00665       if (Rem > NumBytes) {
00666         memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00667         pRing->WrOff = WrOff + NumBytes;
00668       } else {
00669         //
00670         // We reach the end of the buffer, so need to wrap around
00671         //
00672         memcpy(pRing->pBuffer + WrOff, pData, Rem);
00673         memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
00674         pRing->WrOff = NumBytes - Rem;
00675       }
00676       return 1;
00677     }
00678   } else {
00679     Avail = RdOff - WrOff - 1u;
00680     if (Avail >= NumBytes) {
00681       memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
00682       pRing->WrOff = WrOff + NumBytes;
00683       return 1;
00684     }
00685   }
00686   //
00687   // If we reach this point no data has been written
00688   //
00689   return 0;
00690 }
00691 
00692 /*********************************************************************
00693 *
00694 *       SEGGER_RTT_WriteNoLock
00695 *
00696 *  Function description
00697 *    Stores a specified number of characters in SEGGER RTT
00698 *    control block which is then read by the host.
00699 *    SEGGER_RTT_WriteNoLock does not lock the application.
00700 *
00701 *  Parameters
00702 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00703 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00704 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00705 *
00706 *  Return value
00707 *    Number of bytes which have been stored in the "Up"-buffer.
00708 *
00709 *  Notes
00710 *    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
00711 *    (2) For performance reasons this function does not call Init()
00712 *        and may only be called after RTT has been initialized.
00713 *        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
00714 */
00715 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00716   unsigned              Status;
00717   unsigned              Avail;
00718   const char*           pData;
00719   SEGGER_RTT_BUFFER_UP* pRing;
00720 
00721   pData = (const char *)pBuffer;
00722   //
00723   // Get "to-host" ring buffer.
00724   //
00725   pRing = &_SEGGER_RTT.aUp[BufferIndex];
00726   //
00727   // How we output depends upon the mode...
00728   //
00729   switch (pRing->Flags) {
00730   case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
00731     //
00732     // If we are in skip mode and there is no space for the whole
00733     // of this output, don't bother.
00734     //
00735     Avail = _GetAvailWriteSpace(pRing);
00736     if (Avail < NumBytes) {
00737       Status = 0u;
00738     } else {
00739       Status = NumBytes;
00740       _WriteNoCheck(pRing, pData, NumBytes);
00741     }
00742     break;
00743   case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
00744     //
00745     // If we are in trim mode, trim to what we can output without blocking.
00746     //
00747     Avail = _GetAvailWriteSpace(pRing);
00748     Status = Avail < NumBytes ? Avail : NumBytes;
00749     _WriteNoCheck(pRing, pData, Status);
00750     break;
00751   case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
00752     //
00753     // If we are in blocking mode, output everything.
00754     //
00755     Status = _WriteBlocking(pRing, pData, NumBytes);
00756     break;
00757   default:
00758     Status = 0u;
00759     break;
00760   }
00761   //
00762   // Finish up.
00763   //
00764   return Status;
00765 }
00766 
00767 /*********************************************************************
00768 *
00769 *       SEGGER_RTT_Write
00770 *
00771 *  Function description
00772 *    Stores a specified number of characters in SEGGER RTT
00773 *    control block which is then read by the host.
00774 *
00775 *  Parameters
00776 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00777 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00778 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00779 *
00780 *  Return value
00781 *    Number of bytes which have been stored in the "Up"-buffer.
00782 *
00783 *  Notes
00784 *    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
00785 */
00786 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
00787   unsigned Status;
00788   //
00789   INIT();
00790   SEGGER_RTT_LOCK();
00791   //
00792   // Call the non-locking write function
00793   //
00794   Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
00795   //
00796   // Finish up.
00797   //
00798   SEGGER_RTT_UNLOCK();
00799   //
00800   return Status;
00801 }
00802 
00803 /*********************************************************************
00804 *
00805 *       SEGGER_RTT_WriteString
00806 *
00807 *  Function description
00808 *    Stores string in SEGGER RTT control block.
00809 *    This data is read by the host.
00810 *
00811 *  Parameters
00812 *    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
00813 *    s            Pointer to string.
00814 *
00815 *  Return value
00816 *    Number of bytes which have been stored in the "Up"-buffer.
00817 *
00818 *  Notes
00819 *    (1) If there is not enough space in the "Up"-buffer, depending on configuration,
00820 *        remaining characters may be dropped or RTT module waits until there is more space in the buffer.
00821 *    (2) String passed to this function has to be \0 terminated
00822 *    (3) \0 termination character is *not* stored in RTT buffer
00823 */
00824 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
00825   unsigned Len;
00826 
00827   Len = STRLEN(s);
00828   return SEGGER_RTT_Write(BufferIndex, s, Len);
00829 }
00830 
00831 /*********************************************************************
00832 *
00833 *       SEGGER_RTT_GetKey
00834 *
00835 *  Function description
00836 *    Reads one character from the SEGGER RTT buffer.
00837 *    Host has previously stored data there.
00838 *
00839 *  Return value
00840 *    <  0 -   No character available (buffer empty).
00841 *    >= 0 -   Character which has been read. (Possible values: 0 - 255)
00842 *
00843 *  Notes
00844 *    (1) This function is only specified for accesses to RTT buffer 0.
00845 */
00846 int SEGGER_RTT_GetKey(void) {
00847   char c;
00848   int r;
00849 
00850   r = (int)SEGGER_RTT_Read(0u, &c, 1u);
00851   if (r == 1) {
00852     r = (int)(unsigned char)c;
00853   } else {
00854     r = -1;
00855   }
00856   return r;
00857 }
00858 
00859 /*********************************************************************
00860 *
00861 *       SEGGER_RTT_WaitKey
00862 *
00863 *  Function description
00864 *    Waits until at least one character is avaible in the SEGGER RTT buffer.
00865 *    Once a character is available, it is read and this function returns.
00866 *
00867 *  Return value
00868 *    >=0 -   Character which has been read.
00869 *
00870 *  Notes
00871 *    (1) This function is only specified for accesses to RTT buffer 0
00872 *    (2) This function is blocking if no character is present in RTT buffer
00873 */
00874 int SEGGER_RTT_WaitKey(void) {
00875   int r;
00876 
00877   do {
00878     r = SEGGER_RTT_GetKey();
00879   } while (r < 0);
00880   return r;
00881 }
00882 
00883 /*********************************************************************
00884 *
00885 *       SEGGER_RTT_HasKey
00886 *
00887 *  Function description
00888 *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
00889 *
00890 *  Return value
00891 *    == 0 -     No characters are available to read.
00892 *    == 1 -     At least one character is available.
00893 *
00894 *  Notes
00895 *    (1) This function is only specified for accesses to RTT buffer 0
00896 */
00897 int SEGGER_RTT_HasKey(void) {
00898   unsigned RdOff;
00899   int r;
00900 
00901   INIT();
00902   RdOff = _SEGGER_RTT.aDown[0].RdOff;
00903   if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
00904     r = 1;
00905   } else {
00906     r = 0;
00907   }
00908   return r;
00909 }
00910 
00911 /*********************************************************************
00912 *
00913 *       SEGGER_RTT_HasData
00914 *
00915 *  Function description
00916 *    Check if there is data from the host in the given buffer.
00917 *
00918 *  Return value:
00919 *  ==0:  No data
00920 *  !=0:  Data in buffer
00921 *
00922 */
00923 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
00924   SEGGER_RTT_BUFFER_DOWN* pRing;
00925   unsigned                v;
00926 
00927   pRing = &_SEGGER_RTT.aDown[BufferIndex];
00928   v = pRing->WrOff;
00929   return v - pRing->RdOff;
00930 }
00931 
00932 /*********************************************************************
00933 *
00934 *       SEGGER_RTT_AllocDownBuffer
00935 *
00936 *  Function description
00937 *    Run-time configuration of the next down-buffer (H->T).
00938 *    The next buffer, which is not used yet is configured.
00939 *    This includes: Buffer address, size, name, flags, ...
00940 *
00941 *  Parameters
00942 *    sName        Pointer to a constant name string.
00943 *    pBuffer      Pointer to a buffer to be used.
00944 *    BufferSize   Size of the buffer.
00945 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
00946 *
00947 *  Return value
00948 *    >= 0 - O.K. Buffer Index
00949 *     < 0 - Error
00950 */
00951 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
00952   int BufferIndex;
00953 
00954   INIT();
00955   SEGGER_RTT_LOCK();
00956   BufferIndex = 0;
00957   do {
00958     if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
00959       break;
00960     }
00961     BufferIndex++;
00962   } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
00963   if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
00964     _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
00965     _SEGGER_RTT.aDown[BufferIndex].pBuffer      = pBuffer;
00966     _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
00967     _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
00968     _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
00969     _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
00970   } else {
00971     BufferIndex = -1;
00972   }
00973   SEGGER_RTT_UNLOCK();
00974   return BufferIndex;
00975 }
00976 
00977 /*********************************************************************
00978 *
00979 *       SEGGER_RTT_AllocUpBuffer
00980 *
00981 *  Function description
00982 *    Run-time configuration of the next up-buffer (T->H).
00983 *    The next buffer, which is not used yet is configured.
00984 *    This includes: Buffer address, size, name, flags, ...
00985 *
00986 *  Parameters
00987 *    sName        Pointer to a constant name string.
00988 *    pBuffer      Pointer to a buffer to be used.
00989 *    BufferSize   Size of the buffer.
00990 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
00991 *
00992 *  Return value
00993 *    >= 0 - O.K. Buffer Index
00994 *     < 0 - Error
00995 */
00996 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
00997   int BufferIndex;
00998 
00999   INIT();
01000   SEGGER_RTT_LOCK();
01001   BufferIndex = 0;
01002   do {
01003     if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
01004       break;
01005     }
01006     BufferIndex++;
01007   } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
01008   if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
01009     _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
01010     _SEGGER_RTT.aUp[BufferIndex].pBuffer      = pBuffer;
01011     _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
01012     _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
01013     _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
01014     _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
01015   } else {
01016     BufferIndex = -1;
01017   }
01018   SEGGER_RTT_UNLOCK();
01019   return BufferIndex;
01020 }
01021 
01022 /*********************************************************************
01023 *
01024 *       SEGGER_RTT_ConfigUpBuffer
01025 *
01026 *  Function description
01027 *    Run-time configuration of a specific up-buffer (T->H).
01028 *    Buffer to be configured is specified by index.
01029 *    This includes: Buffer address, size, name, flags, ...
01030 *
01031 *  Parameters
01032 *    BufferIndex  Index of the buffer to configure.
01033 *    sName        Pointer to a constant name string.
01034 *    pBuffer      Pointer to a buffer to be used.
01035 *    BufferSize   Size of the buffer.
01036 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01037 *
01038 *  Return value
01039 *    >= 0 - O.K.
01040 *     < 0 - Error
01041 */
01042 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01043   int r;
01044 
01045   INIT();
01046   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
01047     SEGGER_RTT_LOCK();
01048     if (BufferIndex > 0u) {
01049       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
01050       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = pBuffer;
01051       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
01052       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
01053       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
01054     }
01055     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
01056     SEGGER_RTT_UNLOCK();
01057     r =  0;
01058   } else {
01059     r = -1;
01060   }
01061   return r;
01062 }
01063 
01064 /*********************************************************************
01065 *
01066 *       SEGGER_RTT_ConfigDownBuffer
01067 *
01068 *  Function description
01069 *    Run-time configuration of a specific down-buffer (H->T).
01070 *    Buffer to be configured is specified by index.
01071 *    This includes: Buffer address, size, name, flags, ...
01072 *
01073 *  Parameters
01074 *    BufferIndex  Index of the buffer to configure.
01075 *    sName        Pointer to a constant name string.
01076 *    pBuffer      Pointer to a buffer to be used.
01077 *    BufferSize   Size of the buffer.
01078 *    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
01079 *
01080 *  Return value
01081 *    >= 0  O.K.
01082 *     < 0  Error
01083 */
01084 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
01085   int r;
01086 
01087   INIT();
01088   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
01089     SEGGER_RTT_LOCK();
01090     if (BufferIndex > 0u) {
01091       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
01092       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = pBuffer;
01093       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
01094       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
01095       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
01096     }
01097     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
01098     SEGGER_RTT_UNLOCK();
01099     r =  0;
01100   } else {
01101     r = -1;
01102   }
01103   return r;
01104 }
01105 
01106 /*********************************************************************
01107 *
01108 *       SEGGER_RTT_SetNameUpBuffer
01109 *
01110 *  Function description
01111 *    Run-time configuration of a specific up-buffer name (T->H).
01112 *    Buffer to be configured is specified by index.
01113 *
01114 *  Parameters
01115 *    BufferIndex  Index of the buffer to renamed.
01116 *    sName        Pointer to a constant name string.
01117 *
01118 *  Return value
01119 *    >= 0  O.K.
01120 *     < 0  Error
01121 */
01122 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
01123   int r;
01124 
01125   INIT();
01126   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
01127     SEGGER_RTT_LOCK();
01128     _SEGGER_RTT.aUp[BufferIndex].sName = sName;
01129     SEGGER_RTT_UNLOCK();
01130     r =  0;
01131   } else {
01132     r = -1;
01133   }
01134   return r;
01135 }
01136 
01137 /*********************************************************************
01138 *
01139 *       SEGGER_RTT_SetNameDownBuffer
01140 *
01141 *  Function description
01142 *    Run-time configuration of a specific Down-buffer name (T->H).
01143 *    Buffer to be configured is specified by index.
01144 *
01145 *  Parameters
01146 *    BufferIndex  Index of the buffer to renamed.
01147 *    sName        Pointer to a constant name string.
01148 *
01149 *  Return value
01150 *    >= 0  O.K.
01151 *     < 0  Error
01152 */
01153 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
01154   int r;
01155 
01156   INIT();
01157   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
01158     SEGGER_RTT_LOCK();
01159     _SEGGER_RTT.aDown[BufferIndex].sName = sName;
01160     SEGGER_RTT_UNLOCK();
01161     r =  0;
01162   } else {
01163     r = -1;
01164   }
01165   return r;
01166 }
01167 
01168 /*********************************************************************
01169 *
01170 *       SEGGER_RTT_Init
01171 *
01172 *  Function description
01173 *    Initializes the RTT Control Block.
01174 *    Should be used in RAM targets, at start of the application.
01175 *
01176 */
01177 void SEGGER_RTT_Init (void) {
01178   _DoInit();
01179 }
01180 
01181 /*********************************************************************
01182 *
01183 *       SEGGER_RTT_SetTerminal
01184 *
01185 *  Function description
01186 *    Sets the terminal to be used for output on channel 0.
01187 *
01188 *  Parameters
01189 *    TerminalId  Index of the terminal.
01190 *
01191 *  Return value
01192 *    >= 0  O.K.
01193 *     < 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)
01194 */
01195 int SEGGER_RTT_SetTerminal (char TerminalId) {
01196   char                  ac[2];
01197   SEGGER_RTT_BUFFER_UP* pRing;
01198   unsigned Avail;
01199   int r;
01200   //
01201   INIT();
01202   //
01203   r = 0;
01204   ac[0] = 0xFFU;
01205   if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
01206     ac[1] = _aTerminalId[(unsigned char)TerminalId];
01207     pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
01208     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
01209     if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
01210       _ActiveTerminal = TerminalId;
01211       _WriteBlocking(pRing, ac, 2u);
01212     } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
01213       Avail = _GetAvailWriteSpace(pRing);
01214       if (Avail >= 2) {
01215         _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
01216         _WriteNoCheck(pRing, ac, 2u);
01217       } else {
01218         r = -1;
01219       }
01220     }
01221     SEGGER_RTT_UNLOCK();
01222   } else {
01223     r = -1;
01224   }
01225   return r;
01226 }
01227 
01228 /*********************************************************************
01229 *
01230 *       SEGGER_RTT_TerminalOut
01231 *
01232 *  Function description
01233 *    Writes a string to the given terminal
01234 *     without changing the terminal for channel 0.
01235 *
01236 *  Parameters
01237 *    TerminalId   Index of the terminal.
01238 *    s            String to be printed on the terminal.
01239 *
01240 *  Return value
01241 *    >= 0 - Number of bytes written.
01242 *     < 0 - Error.
01243 *
01244 */
01245 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
01246   int                   Status;
01247   unsigned              FragLen;
01248   unsigned              Avail;
01249   SEGGER_RTT_BUFFER_UP* pRing;
01250   //
01251   INIT();
01252   //
01253   // Validate terminal ID.
01254   //
01255   if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
01256     //
01257     // Get "to-host" ring buffer.
01258     //
01259     pRing = &_SEGGER_RTT.aUp[0];
01260     //
01261     // Need to be able to change terminal, write data, change back.
01262     // Compute the fixed and variable sizes.
01263     //
01264     FragLen = strlen(s);
01265     //
01266     // How we output depends upon the mode...
01267     //
01268     SEGGER_RTT_LOCK();
01269     Avail = _GetAvailWriteSpace(pRing);
01270     switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
01271     case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
01272       //
01273       // If we are in skip mode and there is no space for the whole
01274       // of this output, don't bother switching terminals at all.
01275       //
01276       if (Avail < (FragLen + 4u)) {
01277         Status = 0;
01278       } else {
01279         _PostTerminalSwitch(pRing, TerminalId);
01280         Status = (int)_WriteBlocking(pRing, s, FragLen);
01281         _PostTerminalSwitch(pRing, _ActiveTerminal);
01282       }
01283       break;
01284     case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
01285       //
01286       // If we are in trim mode and there is not enough space for everything,
01287       // trim the output but always include the terminal switch.  If no room
01288       // for terminal switch, skip that totally.
01289       //
01290       if (Avail < 4u) {
01291         Status = -1;
01292       } else {
01293         _PostTerminalSwitch(pRing, TerminalId);
01294         Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
01295         _PostTerminalSwitch(pRing, _ActiveTerminal);
01296       }
01297       break;
01298     case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
01299       //
01300       // If we are in blocking mode, output everything.
01301       //
01302       _PostTerminalSwitch(pRing, TerminalId);
01303       Status = (int)_WriteBlocking(pRing, s, FragLen);
01304       _PostTerminalSwitch(pRing, _ActiveTerminal);
01305       break;
01306     default:
01307       Status = -1;
01308       break;
01309     }
01310     //
01311     // Finish up.
01312     //
01313     SEGGER_RTT_UNLOCK();
01314   } else {
01315     Status = -1;
01316   }
01317   return Status;
01318 }
01319 
01320 
01321 /*************************** End of file ****************************/
01322