RTT Debugger Library
Dependents: BREAK_SENSOR_LED MPU9250_simple MPU9250_tap_better Sensor_tap_BLE ... more
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 ****************************/
Generated on Wed Jul 13 2022 19:38:22 by 1.7.2