Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: acnSensa_LIS acd52832_Indoor_Posit_Peripheral acd52832_Indoor_Posit_Central iBeacon acnsensa ... more
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
Generated on Sat Jul 16 2022 10:25:54 by
1.7.2