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