RTT Debugger Library

Dependents:   BREAK_SENSOR_LED MPU9250_simple MPU9250_tap_better Sensor_tap_BLE ... 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-2014 SEGGER Microcontroller GmbH & Co. KG          *
00007 *                                                                    *
00008 *       Internet: www.segger.com Support: support@segger.com         *
00009 *                                                                    *
00010 **********************************************************************
00011 ----------------------------------------------------------------------
00012 File    : SEGGER_RTT.c
00013 Date    : 17 Dec 2014
00014 Purpose : Implementation of SEGGER real-time terminal (RTT) which allows
00015           real-time terminal communication on targets which support
00016           debugger memory accesses while the CPU is running.
00017 
00018           Type "int" is assumed to be 32-bits in size
00019           H->T    Host to target communication
00020           T->H    Target to host communication
00021 
00022           RTT channel 0 is always present and reserved for Terminal usage.
00023           Name is fixed to "Terminal"
00024 
00025 ---------------------------END-OF-HEADER------------------------------
00026 */
00027 
00028 #include "SEGGER_RTT_Conf.h"
00029 #include "SEGGER_RTT.h"
00030 
00031 #include <string.h>                 // for memcpy
00032 
00033 /*********************************************************************
00034 *
00035 *       Defines, configurable
00036 *
00037 **********************************************************************
00038 */
00039 
00040 #ifndef   BUFFER_SIZE_UP
00041   #define BUFFER_SIZE_UP                                  (1024)  // Size of the buffer for terminal output of target, up to host
00042 #endif
00043 
00044 #ifndef   BUFFER_SIZE_DOWN
00045   #define BUFFER_SIZE_DOWN                                (16)    // Size of the buffer for terminal input to target from host (Usually keyboard input)
00046 #endif
00047 
00048 #ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
00049   #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                   (1)     // Number of up-buffers (T->H) available on this target
00050 #endif
00051 
00052 #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
00053   #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                 (1)     // Number of down-buffers (H->T) available on this target
00054 #endif
00055 
00056 #ifndef   SEGGER_RTT_LOCK
00057   #define SEGGER_RTT_LOCK()
00058 #endif
00059 
00060 #ifndef   SEGGER_RTT_UNLOCK
00061   #define SEGGER_RTT_UNLOCK()
00062 #endif
00063 
00064 #ifndef   SEGGER_RTT_IN_RAM
00065   #define SEGGER_RTT_IN_RAM                               (0)
00066 #endif
00067 
00068 /*********************************************************************
00069 *
00070 *       Defines, fixed
00071 *
00072 **********************************************************************
00073 */
00074 
00075 #define MIN(a, b)        (((a) < (b)) ? (a) : (b))
00076 #define MAX(a, b)        (((a) > (b)) ? (a) : (b))
00077 
00078 #define MEMCPY(a, b, c)  memcpy((a),(b),(c))
00079 
00080 //
00081 // For some environments, NULL may not be defined until certain headers are included
00082 //
00083 #ifndef NULL
00084   #define NULL 0
00085 #endif
00086 
00087 /*********************************************************************
00088 *
00089 *       Types
00090 *
00091 **********************************************************************
00092 */
00093 
00094 //
00095 // Description for a circular buffer (also called "ring buffer")
00096 // which is used as up- (T->H) or down-buffer (H->T)
00097 //
00098 typedef struct {
00099   const char* sName;                     // Optional name. Standard names so far are: "Terminal", "VCom"
00100   char*  pBuffer;                        // Pointer to start of buffer
00101   int    SizeOfBuffer;                   // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
00102   volatile int WrOff;                    // Position of next item to be written by either host (down-buffer) or target (up-buffer). Must be volatile since it may be modified by host (down-buffer)
00103   volatile int RdOff;                    // Position of next item to be read by target (down-buffer) or host (up-buffer). Must be volatile since it may be modified by host (up-buffer)
00104   int    Flags;                          // Contains configuration flags
00105 } RING_BUFFER;
00106 
00107 //
00108 // RTT control block which describes the number of buffers available
00109 // as well as the configuration for each buffer
00110 //
00111 //
00112 typedef struct {
00113   char        acID[16];                                 // Initialized to "SEGGER RTT"
00114   int         MaxNumUpBuffers;                          // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
00115   int         MaxNumDownBuffers;                        // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
00116   RING_BUFFER aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS];       // Up buffers, transferring information up from target via debug probe to host
00117   RING_BUFFER aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS];   // Down buffers, transferring information down from host via debug probe to target
00118 } SEGGER_RTT_CB;
00119 
00120 /*********************************************************************
00121 *
00122 *       Static data
00123 *
00124 **********************************************************************
00125 */
00126 //
00127 // Allocate buffers for channel 0
00128 //
00129 static char _acUpBuffer  [BUFFER_SIZE_UP];
00130 static char _acDownBuffer[BUFFER_SIZE_DOWN];
00131 //
00132 // Initialize SEGGER Real-time-Terminal control block (CB)
00133 //
00134 static SEGGER_RTT_CB _SEGGER_RTT = {
00135 #if SEGGER_RTT_IN_RAM
00136   "SEGGER RTTI",
00137 #else
00138   "SEGGER RTT",
00139 #endif
00140   SEGGER_RTT_MAX_NUM_UP_BUFFERS,
00141   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS,
00142   {{ "Terminal", &_acUpBuffer[0],   sizeof(_acUpBuffer),   0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
00143   {{ "Terminal", &_acDownBuffer[0], sizeof(_acDownBuffer), 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
00144 };
00145 
00146 static char _ActiveTerminal;
00147 
00148 /*********************************************************************
00149 *
00150 *       Static code
00151 *
00152 **********************************************************************
00153 */
00154 
00155 /*********************************************************************
00156 *
00157 *       _strlen
00158 *
00159 *  Function description
00160 *    ANSI compatible function to determine the length of a string
00161 *
00162 *  Return value
00163 *    Length of string in bytes.
00164 *
00165 *  Parameters
00166 *    s         Pointer to \0 terminated string.
00167 *
00168 *  Notes
00169 *    (1) s needs to point to an \0 terminated string. Otherwise proper functionality of this function is not guaranteed.
00170 */
00171 static int _strlen(const char* s) {
00172   int Len;
00173 
00174   Len = 0;
00175   if (s == NULL) {
00176     return 0;
00177   }
00178   do {
00179     if (*s == 0) {
00180       break;
00181     }
00182     Len++;
00183     s++;
00184   } while (1);
00185   return Len;
00186 }
00187 
00188 /*********************************************************************
00189 *
00190 *       _Init
00191 *
00192 *  Function description
00193 *    In case SEGGER_RTT_IN_RAM is defined,
00194 *    _Init() modifies the ID of the RTT CB to allow identifying the
00195 *    RTT Control Block Structure in the data segment.
00196 */
00197 static void _Init(void) {
00198 #if SEGGER_RTT_IN_RAM
00199   if (_SEGGER_RTT.acID[10] == 'I') {
00200     _SEGGER_RTT.acID[10] = '\0';
00201   }
00202 #endif
00203 }
00204 
00205 /*********************************************************************
00206 *
00207 *       Public code
00208 *
00209 **********************************************************************
00210 */
00211 /*********************************************************************
00212 *
00213 *       SEGGER_RTT_Read
00214 *
00215 *  Function description
00216 *    Reads characters from SEGGER real-time-terminal control block
00217 *    which have been previously stored by the host.
00218 *
00219 *  Parameters
00220 *    BufferIndex  Index of Down-buffer to be used. (e.g. 0 for "Terminal")
00221 *    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
00222 *    BufferSize   Size of the target application buffer
00223 *
00224 *  Return values
00225 *    Number of bytes that have been read
00226 */
00227 int SEGGER_RTT_Read(unsigned BufferIndex, char* pBuffer, unsigned BufferSize) {
00228   int NumBytesRem;
00229   unsigned NumBytesRead;
00230   int RdOff;
00231   int WrOff;
00232 
00233   SEGGER_RTT_LOCK();
00234   _Init();
00235   RdOff = _SEGGER_RTT.aDown[BufferIndex].RdOff;
00236   WrOff = _SEGGER_RTT.aDown[BufferIndex].WrOff;
00237   NumBytesRead = 0;
00238   //
00239   // Read from current read position to wrap-around of buffer, first
00240   //
00241   if (RdOff > WrOff) {
00242     NumBytesRem = _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer - RdOff;
00243     NumBytesRem = MIN(NumBytesRem, (int)BufferSize);
00244     MEMCPY(pBuffer, _SEGGER_RTT.aDown[BufferIndex].pBuffer + RdOff, NumBytesRem);
00245     NumBytesRead += NumBytesRem;
00246     pBuffer      += NumBytesRem;
00247     BufferSize   -= NumBytesRem;
00248     RdOff        += NumBytesRem;
00249     //
00250     // Handle wrap-around of buffer
00251     //
00252     if (RdOff == _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer) {
00253       RdOff = 0;
00254     }
00255   }
00256   //
00257   // Read remaining items of buffer
00258   //
00259   NumBytesRem = WrOff - RdOff;
00260   NumBytesRem = MIN(NumBytesRem, (int)BufferSize);
00261   if (NumBytesRem > 0) {
00262     MEMCPY(pBuffer, _SEGGER_RTT.aDown[BufferIndex].pBuffer + RdOff, NumBytesRem);
00263     NumBytesRead += NumBytesRem;
00264     pBuffer      += NumBytesRem;
00265     BufferSize   -= NumBytesRem;
00266     RdOff        += NumBytesRem;
00267   }
00268   if (NumBytesRead) {
00269     _SEGGER_RTT.aDown[BufferIndex].RdOff = RdOff;
00270   }
00271   SEGGER_RTT_UNLOCK();
00272   return NumBytesRead;
00273 }
00274 
00275 /*********************************************************************
00276 *
00277 *       SEGGER_RTT_Write
00278 *
00279 *  Function description
00280 *    Stores a specified number of characters in SEGGER RTT
00281 *    control block which is then read by the host.
00282 *
00283 *  Parameters
00284 *    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
00285 *    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
00286 *    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
00287 *
00288 *  Return values
00289 *    Number of bytes which have been stored in the "Up"-buffer.
00290 *
00291 *  Notes
00292 *    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
00293 */
00294 int SEGGER_RTT_Write(unsigned BufferIndex, const char* pBuffer, unsigned NumBytes) {
00295   int NumBytesToWrite;
00296   unsigned NumBytesWritten;
00297   int RdOff;
00298   //
00299   // Target is not allowed to perform other RTT operations while string still has not been stored completely.
00300   // Otherwise we would probably end up with a mixed string in the buffer.
00301   //
00302   SEGGER_RTT_LOCK();
00303   _Init();
00304   //
00305   // In case we are not in blocking mode,
00306   // we need to calculate, how many bytes we can put into the buffer at all.
00307   //
00308   if ((_SEGGER_RTT.aUp[BufferIndex].Flags & SEGGER_RTT_MODE_MASK) != SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
00309     RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff;
00310     NumBytesToWrite =  RdOff - _SEGGER_RTT.aUp[BufferIndex].WrOff - 1;
00311     if (NumBytesToWrite < 0) {
00312       NumBytesToWrite += _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer;
00313     }
00314     //
00315     // If the complete data does not fit in the buffer, check if we have to skip it completely or trim the data
00316     //
00317     if ((int)NumBytes > NumBytesToWrite) {
00318       if ((_SEGGER_RTT.aUp[BufferIndex].Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_NO_BLOCK_SKIP) {
00319         SEGGER_RTT_UNLOCK();
00320         return 0;
00321       } else {
00322         NumBytes = NumBytesToWrite;
00323       }
00324     }
00325   }
00326   //
00327   // Early out if nothing is to do
00328   //
00329   if (NumBytes == 0) {
00330     SEGGER_RTT_UNLOCK();
00331     return 0;
00332   }
00333   //
00334   // Write data to buffer and handle wrap-around if necessary
00335   //
00336   NumBytesWritten = 0;
00337   do {
00338     RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff;                          // May be changed by host (debug probe) in the meantime
00339     NumBytesToWrite = RdOff - _SEGGER_RTT.aUp[BufferIndex].WrOff - 1;
00340     if (NumBytesToWrite < 0) {
00341       NumBytesToWrite += _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer;
00342     }
00343     NumBytesToWrite = MIN(NumBytesToWrite, (_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - _SEGGER_RTT.aUp[BufferIndex].WrOff));    // Number of bytes that can be written until buffer wrap-around
00344     NumBytesToWrite = MIN(NumBytesToWrite, (int)NumBytes);
00345     MEMCPY(_SEGGER_RTT.aUp[BufferIndex].pBuffer + _SEGGER_RTT.aUp[BufferIndex].WrOff, pBuffer, NumBytesToWrite);
00346     NumBytesWritten     += NumBytesToWrite;
00347     pBuffer             += NumBytesToWrite;
00348     NumBytes            -= NumBytesToWrite;
00349     _SEGGER_RTT.aUp[BufferIndex].WrOff += NumBytesToWrite;
00350     if (_SEGGER_RTT.aUp[BufferIndex].WrOff == _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer) {
00351       _SEGGER_RTT.aUp[BufferIndex].WrOff = 0;
00352     }
00353   } while (NumBytes);
00354   SEGGER_RTT_UNLOCK();
00355   return NumBytesWritten;
00356 }
00357 
00358 /*********************************************************************
00359 *
00360 *       SEGGER_RTT_WriteString
00361 *
00362 *  Function description
00363 *    Stores string in SEGGER RTT control block.
00364 *    This data is read by the host.
00365 *
00366 *  Parameters
00367 *    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
00368 *    s            Pointer to string.
00369 *
00370 *  Return values
00371 *    Number of bytes which have been stored in the "Up"-buffer.
00372 *
00373 *  Notes
00374 *    (1) If there is not enough space in the "Up"-buffer, depending on configuration,
00375 *        remaining characters may be dropped or RTT module waits until there is more space in the buffer.
00376 *    (2) String passed to this function has to be \0 terminated
00377 *    (3) \0 termination character is *not* stored in RTT buffer
00378 */
00379 int SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
00380   int Len;
00381 
00382   Len = _strlen(s);
00383   return SEGGER_RTT_Write(BufferIndex, s, Len);
00384 }
00385 
00386 /*********************************************************************
00387 *
00388 *       SEGGER_RTT_GetKey
00389 *
00390 *  Function description
00391 *    Reads one character from the SEGGER RTT buffer.
00392 *    Host has previously stored data there.
00393 *
00394 *  Return values
00395 *    <  0    No character available (buffer empty).
00396 *    >= 0    Character which has been read. (Possible values: 0 - 255)
00397 *
00398 *  Notes
00399 *    (1) This function is only specified for accesses to RTT buffer 0.
00400 */
00401 int SEGGER_RTT_GetKey(void) {
00402   char c;
00403   int r;
00404 
00405   r = SEGGER_RTT_Read(0, &c, 1);
00406   if (r == 1) {
00407     return (int)(unsigned char)c;
00408   }
00409   return -1;
00410 }
00411 
00412 /*********************************************************************
00413 *
00414 *       SEGGER_RTT_WaitKey
00415 *
00416 *  Function description
00417 *    Waits until at least one character is avaible in the SEGGER RTT buffer.
00418 *    Once a character is available, it is read and this function returns.
00419 *
00420 *  Return values
00421 *    >=0    Character which has been read.
00422 *
00423 *  Notes
00424 *    (1) This function is only specified for accesses to RTT buffer 0
00425 *    (2) This function is blocking if no character is present in RTT buffer
00426 */
00427 int SEGGER_RTT_WaitKey(void) {
00428   int r;
00429 
00430   do {
00431     r = SEGGER_RTT_GetKey();
00432   } while (r < 0);
00433   return r;
00434 }
00435 
00436 /*********************************************************************
00437 *
00438 *       SEGGER_RTT_HasKey
00439 *
00440 *  Function description
00441 *    Checks if at least one character for reading is available in the SEGGER RTT buffer.
00442 *
00443 *  Return values
00444 *    0      No characters are available to read.
00445 *    1      At least one character is available.
00446 *
00447 *  Notes
00448 *    (1) This function is only specified for accesses to RTT buffer 0
00449 */
00450 int SEGGER_RTT_HasKey(void) {
00451   int RdOff;
00452 
00453   _Init();
00454   RdOff = _SEGGER_RTT.aDown[0].RdOff;
00455   if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
00456     return 1;
00457   }
00458   return 0;
00459 }
00460 
00461 /*********************************************************************
00462 *
00463 *       SEGGER_RTT_ConfigUpBuffer
00464 *
00465 *  Function description
00466 *    Run-time configuration of a specific up-buffer (T->H).
00467 *    Buffer to be configured is specified by index.
00468 *    This includes: Buffer address, size, name, flags, ...
00469 *
00470 *  Return value
00471 *    >= 0  O.K.
00472 *     < 0  Error
00473 */
00474 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, char* pBuffer, int BufferSize, int Flags) {
00475   _Init();
00476   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
00477     SEGGER_RTT_LOCK();
00478     if (BufferIndex > 0) {
00479       _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
00480       _SEGGER_RTT.aUp[BufferIndex].pBuffer      = pBuffer;
00481       _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
00482       _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0;
00483       _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0;
00484     }
00485     _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
00486     SEGGER_RTT_UNLOCK();
00487     return 0;
00488   }
00489   return -1;
00490 }
00491 
00492 /*********************************************************************
00493 *
00494 *       SEGGER_RTT_ConfigDownBuffer
00495 *
00496 *  Function description
00497 *    Run-time configuration of a specific down-buffer (H->T).
00498 *    Buffer to be configured is specified by index.
00499 *    This includes: Buffer address, size, name, flags, ...
00500 *
00501 *  Return value
00502 *    >= 0  O.K.
00503 *     < 0  Error
00504 */
00505 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, char* pBuffer, int BufferSize, int Flags) {
00506   _Init();
00507   if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
00508     SEGGER_RTT_LOCK();
00509     if (BufferIndex > 0) {
00510       _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
00511       _SEGGER_RTT.aDown[BufferIndex].pBuffer      = pBuffer;
00512       _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
00513       _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0;
00514       _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0;
00515     }
00516     _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
00517     SEGGER_RTT_UNLOCK();
00518     return 0;
00519   }
00520   return -1;
00521 }
00522 
00523 /*********************************************************************
00524 *
00525 *       SEGGER_RTT_Init
00526 *
00527 *  Function description
00528 *    Initializes the RTT Control Block.
00529 *    Should be used in RAM targets, at start of the application.
00530 *
00531 */
00532 void SEGGER_RTT_Init (void) {
00533   _Init();
00534 }
00535 
00536 /*********************************************************************
00537 *
00538 *       SEGGER_RTT_SetTerminal
00539 *
00540 *  Function description
00541 *    Sets the terminal to be used for output on channel 0.
00542 *
00543 */
00544 void SEGGER_RTT_SetTerminal (char TerminalId) {
00545   char ac[2];
00546 
00547   ac[0] = 0xFF;
00548   if (TerminalId < 10) {
00549     ac[1] = '0' + TerminalId;
00550   } else if (TerminalId < 16) {
00551     ac[1] = 'A' + (TerminalId - 0x0A);
00552   } else {
00553     return; // RTT only supports up to 16 virtual terminals.
00554   }
00555   _ActiveTerminal = TerminalId;
00556   SEGGER_RTT_Write(0, ac, 2);
00557 }
00558 
00559 /*********************************************************************
00560 *
00561 *       SEGGER_RTT_TerminalOut
00562 *
00563 *  Function description
00564 *    Writes a string to the given terminal
00565 *     without changing the terminal for channel 0.
00566 *
00567 */
00568 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
00569   char ac[2];
00570   int  r;
00571 
00572   ac[0] = 0xFF;
00573   if (TerminalId < 10) {
00574     ac[1] = '0' + TerminalId;
00575   } else if (TerminalId < 16) {
00576     ac[1] = 'A' + (TerminalId - 0x0A);
00577   } else {
00578     return -1; // RTT only supports up to 16 virtual terminals.
00579   }
00580   SEGGER_RTT_Write(0, ac, 2);
00581   r = SEGGER_RTT_WriteString(0, s);
00582   if (TerminalId < 10) {
00583     ac[1] = '0' + _ActiveTerminal;
00584   } else if (TerminalId < 16) {
00585     ac[1] = 'A' + (_ActiveTerminal - 0x0A);
00586   }
00587   SEGGER_RTT_Write(0, ac, 2);
00588   return r;
00589 }
00590 
00591 /*************************** End of file ****************************/