1 /********************************************************************* 2 * SEGGER Microcontroller GmbH * 3 * The Embedded Experts * 4 ********************************************************************** 5 * * 6 * (c) 1995 - 2019 SEGGER Microcontroller GmbH * 7 * * 8 * www.segger.com Support: [email protected] * 9 * * 10 ********************************************************************** 11 * * 12 * SEGGER RTT * Real Time Transfer for embedded targets * 13 * * 14 ********************************************************************** 15 * * 16 * All rights reserved. * 17 * * 18 * SEGGER strongly recommends to not make any changes * 19 * to or modify the source code of this software in order to stay * 20 * compatible with the RTT protocol and J-Link. * 21 * * 22 * Redistribution and use in source and binary forms, with or * 23 * without modification, are permitted provided that the following * 24 * condition is met: * 25 * * 26 * o Redistributions of source code must retain the above copyright * 27 * notice, this condition and the following disclaimer. * 28 * * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 * DAMAGE. * 42 * * 43 ********************************************************************** 44 ---------------------------END-OF-HEADER------------------------------ 45 File : SEGGER_RTT.c 46 Purpose : Implementation of SEGGER real-time transfer (RTT) which 47 allows real-time communication on targets which support 48 debugger memory accesses while the CPU is running. 49 Revision: $Rev: 28168 $ 50 51 Additional information: 52 Type "int" is assumed to be 32-bits in size 53 H->T Host to target communication 54 T->H Target to host communication 55 56 RTT channel 0 is always present and reserved for Terminal usage. 57 Name is fixed to "Terminal" 58 59 Effective buffer size: SizeOfBuffer - 1 60 61 WrOff == RdOff: Buffer is empty 62 WrOff == (RdOff - 1): Buffer is full 63 WrOff > RdOff: Free space includes wrap-around 64 WrOff < RdOff: Used space includes wrap-around 65 (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): 66 Buffer full and wrap-around after next byte 67 68 69 ---------------------------------------------------------------------- 70 */ 71 72 #include "SEGGER_RTT.h" 73 74 #include <string.h> // for memcpy 75 76 /********************************************************************* 77 * 78 * Configuration, default values 79 * 80 ********************************************************************** 81 */ 82 83 #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 84 #ifdef SEGGER_RTT_CB_ALIGN 85 #error "Custom SEGGER_RTT_CB_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 86 #endif 87 #ifdef SEGGER_RTT_BUFFER_ALIGN 88 #error "Custom SEGGER_RTT_BUFFER_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 89 #endif 90 #ifdef SEGGER_RTT_PUT_CB_SECTION 91 #error "Custom SEGGER_RTT_PUT_CB_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 92 #endif 93 #ifdef SEGGER_RTT_PUT_BUFFER_SECTION 94 #error "Custom SEGGER_RTT_PUT_BUFFER_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 95 #endif 96 #ifdef SEGGER_RTT_BUFFER_ALIGNMENT 97 #error "Custom SEGGER_RTT_BUFFER_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 98 #endif 99 #ifdef SEGGER_RTT_ALIGNMENT 100 #error "Custom SEGGER_RTT_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 101 #endif 102 #endif 103 104 #ifndef BUFFER_SIZE_UP 105 #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 106 #endif 107 108 #ifndef BUFFER_SIZE_DOWN 109 #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) 110 #endif 111 112 #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 113 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target 114 #endif 115 116 #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 117 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target 118 #endif 119 120 #ifndef SEGGER_RTT_BUFFER_SECTION 121 #if defined(SEGGER_RTT_SECTION) 122 #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION 123 #endif 124 #endif 125 126 #ifndef SEGGER_RTT_ALIGNMENT 127 #define SEGGER_RTT_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 128 #endif 129 130 #ifndef SEGGER_RTT_BUFFER_ALIGNMENT 131 #define SEGGER_RTT_BUFFER_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 132 #endif 133 134 #ifndef SEGGER_RTT_MODE_DEFAULT 135 #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 136 #endif 137 138 #ifndef SEGGER_RTT_LOCK 139 #define SEGGER_RTT_LOCK() 140 #endif 141 142 #ifndef SEGGER_RTT_UNLOCK 143 #define SEGGER_RTT_UNLOCK() 144 #endif 145 146 #ifndef STRLEN 147 #define STRLEN(a) strlen((a)) 148 #endif 149 150 #ifndef STRCPY 151 #define STRCPY(pDest, pSrc) strcpy((pDest), (pSrc)) 152 #endif 153 154 #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 155 #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 156 #endif 157 158 #ifndef SEGGER_RTT_MEMCPY 159 #ifdef MEMCPY 160 #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) 161 #else 162 #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 163 #endif 164 #endif 165 166 #ifndef MIN 167 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 168 #endif 169 170 #ifndef MAX 171 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 172 #endif 173 // 174 // For some environments, NULL may not be defined until certain headers are included 175 // 176 #ifndef NULL 177 #define NULL 0 178 #endif 179 180 /********************************************************************* 181 * 182 * Defines, fixed 183 * 184 ********************************************************************** 185 */ 186 #if (defined __ICCARM__) || (defined __ICCRX__) 187 #define RTT_PRAGMA(P) _Pragma(#P) 188 #endif 189 190 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 191 #if ((defined __GNUC__) || (defined __clang__)) 192 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 193 #elif (defined __ICCARM__) || (defined __ICCRX__) 194 #define PRAGMA(A) _Pragma(#A) 195 #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 196 Var 197 #elif (defined __CC_ARM) 198 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 199 #else 200 #error "Alignment not supported for this compiler." 201 #endif 202 #else 203 #define SEGGER_RTT_ALIGN(Var, Alignment) Var 204 #endif 205 206 #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 207 #if ((defined __GNUC__) || (defined __clang__)) 208 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 209 #elif (defined __ICCARM__) || (defined __ICCRX__) 210 #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 211 Var 212 #elif (defined __CC_ARM) 213 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 214 #else 215 #error "Section placement not supported for this compiler." 216 #endif 217 #else 218 #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 219 #endif 220 221 #if SEGGER_RTT_ALIGNMENT 222 #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 223 #else 224 #define SEGGER_RTT_CB_ALIGN(Var) Var 225 #endif 226 227 #if SEGGER_RTT_BUFFER_ALIGNMENT 228 #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 229 #else 230 #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 231 #endif 232 233 234 #if defined(SEGGER_RTT_SECTION) 235 #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 236 #else 237 #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 238 #endif 239 240 #if defined(SEGGER_RTT_BUFFER_SECTION) 241 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 242 #else 243 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 244 #endif 245 246 /********************************************************************* 247 * 248 * Static const data 249 * 250 ********************************************************************** 251 */ 252 253 static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 254 255 /********************************************************************* 256 * 257 * Static data 258 * 259 ********************************************************************** 260 */ 261 262 // 263 // RTT Control Block and allocate buffers for channel 0 264 // 265 #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 266 #if ((defined __GNUC__) || (defined __clang__)) 267 SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 268 static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 269 static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 270 #elif (defined __ICCARM__) 271 #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 272 SEGGER_RTT_CB _SEGGER_RTT; 273 #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 274 static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)]; 275 #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 276 static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)]; 277 #else 278 #error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned" 279 #endif 280 #else 281 SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); 282 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); 283 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); 284 #endif 285 286 static unsigned char _ActiveTerminal; 287 288 /********************************************************************* 289 * 290 * Static functions 291 * 292 ********************************************************************** 293 */ 294 295 /********************************************************************* 296 * 297 * _DoInit() 298 * 299 * Function description 300 * Initializes the control block an buffers. 301 * May only be called via INIT() to avoid overriding settings. 302 * 303 */ 304 #define INIT() { \ 305 volatile SEGGER_RTT_CB* pRTTCBInit; \ 306 pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \ 307 do { \ 308 if (pRTTCBInit->acID[0] == '\0') { \ 309 _DoInit(); \ 310 } \ 311 } while (0); \ 312 } 313 314 static void _DoInit(void) { 315 volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block 316 static const char _aInitStr[] = "\0\0\0\0\0\0TTR REGGES"; // Init complete ID string to make sure that things also work if RTT is linked to a no-init memory area 317 unsigned i; 318 // 319 // Initialize control block 320 // 321 p = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access control block uncached so that nothing in the cache ever becomes dirty and all changes are visible in HW directly 322 memset((SEGGER_RTT_CB*)p, 0, sizeof(_SEGGER_RTT)); // Make sure that the RTT CB is always zero initialized. 323 p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; 324 p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; 325 // 326 // Initialize up buffer 0 327 // 328 p->aUp[0].sName = "Terminal"; 329 p->aUp[0].pBuffer = _acUpBuffer; 330 p->aUp[0].SizeOfBuffer = BUFFER_SIZE_UP; 331 p->aUp[0].RdOff = 0u; 332 p->aUp[0].WrOff = 0u; 333 p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; 334 // 335 // Initialize down buffer 0 336 // 337 p->aDown[0].sName = "Terminal"; 338 p->aDown[0].pBuffer = _acDownBuffer; 339 p->aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN; 340 p->aDown[0].RdOff = 0u; 341 p->aDown[0].WrOff = 0u; 342 p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; 343 // 344 // Finish initialization of the control block. 345 // Copy Id string backwards to make sure that "SEGGER RTT" is not found in initializer memory (usually flash), 346 // as this would cause J-Link to "find" the control block at a wrong address. 347 // 348 RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 349 for (i = 0; i < sizeof(_aInitStr) - 1; ++i) { 350 p->acID[i] = _aInitStr[sizeof(_aInitStr) - 2 - i]; // Skip terminating \0 at the end of the array 351 } 352 RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 353 } 354 355 /********************************************************************* 356 * 357 * _WriteBlocking() 358 * 359 * Function description 360 * Stores a specified number of characters in SEGGER RTT ring buffer 361 * and updates the associated write pointer which is periodically 362 * read by the host. 363 * The caller is responsible for managing the write chunk sizes as 364 * _WriteBlocking() will block until all data has been posted successfully. 365 * 366 * Parameters 367 * pRing Ring buffer to post to. 368 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 369 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 370 * 371 * Return value 372 * >= 0 - Number of bytes written into buffer. 373 */ 374 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { 375 unsigned NumBytesToWrite; 376 unsigned NumBytesWritten; 377 unsigned RdOff; 378 unsigned WrOff; 379 volatile char* pDst; 380 // 381 // Write data to buffer and handle wrap-around if necessary 382 // 383 NumBytesWritten = 0u; 384 WrOff = pRing->WrOff; 385 do { 386 RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime 387 if (RdOff > WrOff) { 388 NumBytesToWrite = RdOff - WrOff - 1u; 389 } else { 390 NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); 391 } 392 NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around 393 NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); 394 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 395 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 396 NumBytesWritten += NumBytesToWrite; 397 NumBytes -= NumBytesToWrite; 398 WrOff += NumBytesToWrite; 399 while (NumBytesToWrite--) { 400 *pDst++ = *pBuffer++; 401 }; 402 #else 403 SEGGER_RTT_MEMCPY((void*)pDst, pBuffer, NumBytesToWrite); 404 NumBytesWritten += NumBytesToWrite; 405 pBuffer += NumBytesToWrite; 406 NumBytes -= NumBytesToWrite; 407 WrOff += NumBytesToWrite; 408 #endif 409 if (WrOff == pRing->SizeOfBuffer) { 410 WrOff = 0u; 411 } 412 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 413 pRing->WrOff = WrOff; 414 } while (NumBytes); 415 return NumBytesWritten; 416 } 417 418 /********************************************************************* 419 * 420 * _WriteNoCheck() 421 * 422 * Function description 423 * Stores a specified number of characters in SEGGER RTT ring buffer 424 * and updates the associated write pointer which is periodically 425 * read by the host. 426 * It is callers responsibility to make sure data actually fits in buffer. 427 * 428 * Parameters 429 * pRing Ring buffer to post to. 430 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 431 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 432 * 433 * Notes 434 * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking 435 */ 436 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { 437 unsigned NumBytesAtOnce; 438 unsigned WrOff; 439 unsigned Rem; 440 volatile char* pDst; 441 442 WrOff = pRing->WrOff; 443 Rem = pRing->SizeOfBuffer - WrOff; 444 if (Rem > NumBytes) { 445 // 446 // All data fits before wrap around 447 // 448 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 449 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 450 WrOff += NumBytes; 451 while (NumBytes--) { 452 *pDst++ = *pData++; 453 }; 454 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 455 pRing->WrOff = WrOff; 456 #else 457 SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 458 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 459 pRing->WrOff = WrOff + NumBytes; 460 #endif 461 } else { 462 // 463 // We reach the end of the buffer, so need to wrap around 464 // 465 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 466 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 467 NumBytesAtOnce = Rem; 468 while (NumBytesAtOnce--) { 469 *pDst++ = *pData++; 470 }; 471 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 472 NumBytesAtOnce = NumBytes - Rem; 473 while (NumBytesAtOnce--) { 474 *pDst++ = *pData++; 475 }; 476 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 477 pRing->WrOff = NumBytes - Rem; 478 #else 479 NumBytesAtOnce = Rem; 480 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 481 SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytesAtOnce); 482 NumBytesAtOnce = NumBytes - Rem; 483 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 484 SEGGER_RTT_MEMCPY((void*)pDst, pData + Rem, NumBytesAtOnce); 485 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 486 pRing->WrOff = NumBytesAtOnce; 487 #endif 488 } 489 } 490 491 /********************************************************************* 492 * 493 * _PostTerminalSwitch() 494 * 495 * Function description 496 * Switch terminal to the given terminal ID. It is the caller's 497 * responsibility to ensure the terminal ID is correct and there is 498 * enough space in the buffer for this to complete successfully. 499 * 500 * Parameters 501 * pRing Ring buffer to post to. 502 * TerminalId Terminal ID to switch to. 503 */ 504 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { 505 unsigned char ac[2]; 506 507 ac[0] = 0xFFu; 508 ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit 509 _WriteBlocking(pRing, (const char*)ac, 2u); 510 } 511 512 /********************************************************************* 513 * 514 * _GetAvailWriteSpace() 515 * 516 * Function description 517 * Returns the number of bytes that can be written to the ring 518 * buffer without blocking. 519 * 520 * Parameters 521 * pRing Ring buffer to check. 522 * 523 * Return value 524 * Number of bytes that are free in the buffer. 525 */ 526 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { 527 unsigned RdOff; 528 unsigned WrOff; 529 unsigned r; 530 // 531 // Avoid warnings regarding volatile access order. It's not a problem 532 // in this case, but dampen compiler enthusiasm. 533 // 534 RdOff = pRing->RdOff; 535 WrOff = pRing->WrOff; 536 if (RdOff <= WrOff) { 537 r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; 538 } else { 539 r = RdOff - WrOff - 1u; 540 } 541 return r; 542 } 543 544 /********************************************************************* 545 * 546 * Public code 547 * 548 ********************************************************************** 549 */ 550 551 /********************************************************************* 552 * 553 * SEGGER_RTT_ReadUpBufferNoLock() 554 * 555 * Function description 556 * Reads characters from SEGGER real-time-terminal control block 557 * which have been previously stored by the application. 558 * Do not lock against interrupts and multiple access. 559 * Used to do the same operation that J-Link does, to transfer 560 * RTT data via other channels, such as TCP/IP or UART. 561 * 562 * Parameters 563 * BufferIndex Index of Up-buffer to be used. 564 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 565 * BufferSize Size of the target application buffer. 566 * 567 * Return value 568 * Number of bytes that have been read. 569 * 570 * Additional information 571 * This function must not be called when J-Link might also do RTT. 572 */ 573 unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 574 unsigned NumBytesRem; 575 unsigned NumBytesRead; 576 unsigned RdOff; 577 unsigned WrOff; 578 unsigned char* pBuffer; 579 SEGGER_RTT_BUFFER_UP* pRing; 580 volatile char* pSrc; 581 582 INIT(); 583 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 584 pBuffer = (unsigned char*)pData; 585 RdOff = pRing->RdOff; 586 WrOff = pRing->WrOff; 587 NumBytesRead = 0u; 588 // 589 // Read from current read position to wrap-around of buffer, first 590 // 591 if (RdOff > WrOff) { 592 NumBytesRem = pRing->SizeOfBuffer - RdOff; 593 NumBytesRem = MIN(NumBytesRem, BufferSize); 594 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 595 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 596 NumBytesRead += NumBytesRem; 597 BufferSize -= NumBytesRem; 598 RdOff += NumBytesRem; 599 while (NumBytesRem--) { 600 *pBuffer++ = *pSrc++; 601 }; 602 #else 603 SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 604 NumBytesRead += NumBytesRem; 605 pBuffer += NumBytesRem; 606 BufferSize -= NumBytesRem; 607 RdOff += NumBytesRem; 608 #endif 609 // 610 // Handle wrap-around of buffer 611 // 612 if (RdOff == pRing->SizeOfBuffer) { 613 RdOff = 0u; 614 } 615 } 616 // 617 // Read remaining items of buffer 618 // 619 NumBytesRem = WrOff - RdOff; 620 NumBytesRem = MIN(NumBytesRem, BufferSize); 621 if (NumBytesRem > 0u) { 622 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 623 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 624 NumBytesRead += NumBytesRem; 625 BufferSize -= NumBytesRem; 626 RdOff += NumBytesRem; 627 while (NumBytesRem--) { 628 *pBuffer++ = *pSrc++; 629 }; 630 #else 631 SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 632 NumBytesRead += NumBytesRem; 633 pBuffer += NumBytesRem; 634 BufferSize -= NumBytesRem; 635 RdOff += NumBytesRem; 636 #endif 637 } 638 // 639 // Update read offset of buffer 640 // 641 if (NumBytesRead) { 642 pRing->RdOff = RdOff; 643 } 644 // 645 return NumBytesRead; 646 } 647 648 /********************************************************************* 649 * 650 * SEGGER_RTT_ReadNoLock() 651 * 652 * Function description 653 * Reads characters from SEGGER real-time-terminal control block 654 * which have been previously stored by the host. 655 * Do not lock against interrupts and multiple access. 656 * 657 * Parameters 658 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 659 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 660 * BufferSize Size of the target application buffer. 661 * 662 * Return value 663 * Number of bytes that have been read. 664 */ 665 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 666 unsigned NumBytesRem; 667 unsigned NumBytesRead; 668 unsigned RdOff; 669 unsigned WrOff; 670 unsigned char* pBuffer; 671 SEGGER_RTT_BUFFER_DOWN* pRing; 672 volatile char* pSrc; 673 // 674 INIT(); 675 pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 676 pBuffer = (unsigned char*)pData; 677 RdOff = pRing->RdOff; 678 WrOff = pRing->WrOff; 679 NumBytesRead = 0u; 680 // 681 // Read from current read position to wrap-around of buffer, first 682 // 683 if (RdOff > WrOff) { 684 NumBytesRem = pRing->SizeOfBuffer - RdOff; 685 NumBytesRem = MIN(NumBytesRem, BufferSize); 686 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 687 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 688 NumBytesRead += NumBytesRem; 689 BufferSize -= NumBytesRem; 690 RdOff += NumBytesRem; 691 while (NumBytesRem--) { 692 *pBuffer++ = *pSrc++; 693 }; 694 #else 695 SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 696 NumBytesRead += NumBytesRem; 697 pBuffer += NumBytesRem; 698 BufferSize -= NumBytesRem; 699 RdOff += NumBytesRem; 700 #endif 701 // 702 // Handle wrap-around of buffer 703 // 704 if (RdOff == pRing->SizeOfBuffer) { 705 RdOff = 0u; 706 } 707 } 708 // 709 // Read remaining items of buffer 710 // 711 NumBytesRem = WrOff - RdOff; 712 NumBytesRem = MIN(NumBytesRem, BufferSize); 713 if (NumBytesRem > 0u) { 714 pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 715 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 716 NumBytesRead += NumBytesRem; 717 BufferSize -= NumBytesRem; 718 RdOff += NumBytesRem; 719 while (NumBytesRem--) { 720 *pBuffer++ = *pSrc++; 721 }; 722 #else 723 SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 724 NumBytesRead += NumBytesRem; 725 pBuffer += NumBytesRem; 726 BufferSize -= NumBytesRem; 727 RdOff += NumBytesRem; 728 #endif 729 } 730 if (NumBytesRead) { 731 pRing->RdOff = RdOff; 732 } 733 // 734 return NumBytesRead; 735 } 736 737 /********************************************************************* 738 * 739 * SEGGER_RTT_ReadUpBuffer 740 * 741 * Function description 742 * Reads characters from SEGGER real-time-terminal control block 743 * which have been previously stored by the application. 744 * Used to do the same operation that J-Link does, to transfer 745 * RTT data via other channels, such as TCP/IP or UART. 746 * 747 * Parameters 748 * BufferIndex Index of Up-buffer to be used. 749 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 750 * BufferSize Size of the target application buffer. 751 * 752 * Return value 753 * Number of bytes that have been read. 754 * 755 * Additional information 756 * This function must not be called when J-Link might also do RTT. 757 * This function locks against all other RTT operations. I.e. during 758 * the read operation, writing is also locked. 759 * If only one consumer reads from the up buffer, 760 * call sEGGER_RTT_ReadUpBufferNoLock() instead. 761 */ 762 unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 763 unsigned NumBytesRead; 764 765 SEGGER_RTT_LOCK(); 766 // 767 // Call the non-locking read function 768 // 769 NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); 770 // 771 // Finish up. 772 // 773 SEGGER_RTT_UNLOCK(); 774 // 775 return NumBytesRead; 776 } 777 778 /********************************************************************* 779 * 780 * SEGGER_RTT_Read 781 * 782 * Function description 783 * Reads characters from SEGGER real-time-terminal control block 784 * which have been previously stored by the host. 785 * 786 * Parameters 787 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 788 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 789 * BufferSize Size of the target application buffer. 790 * 791 * Return value 792 * Number of bytes that have been read. 793 */ 794 unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 795 unsigned NumBytesRead; 796 797 SEGGER_RTT_LOCK(); 798 // 799 // Call the non-locking read function 800 // 801 NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); 802 // 803 // Finish up. 804 // 805 SEGGER_RTT_UNLOCK(); 806 // 807 return NumBytesRead; 808 } 809 810 /********************************************************************* 811 * 812 * SEGGER_RTT_WriteWithOverwriteNoLock 813 * 814 * Function description 815 * Stores a specified number of characters in SEGGER RTT 816 * control block. 817 * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 818 * and overwrites data if the data does not fit into the buffer. 819 * 820 * Parameters 821 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 822 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 823 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 824 * 825 * Notes 826 * (1) If there is not enough space in the "Up"-buffer, data is overwritten. 827 * (2) For performance reasons this function does not call Init() 828 * and may only be called after RTT has been initialized. 829 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 830 * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 831 * connection reads RTT data. 832 */ 833 void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 834 const char* pData; 835 SEGGER_RTT_BUFFER_UP* pRing; 836 unsigned Avail; 837 volatile char* pDst; 838 // 839 // Get "to-host" ring buffer and copy some elements into local variables. 840 // 841 pData = (const char *)pBuffer; 842 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 843 // 844 // Check if we will overwrite data and need to adjust the RdOff. 845 // 846 if (pRing->WrOff == pRing->RdOff) { 847 Avail = pRing->SizeOfBuffer - 1u; 848 } else if ( pRing->WrOff < pRing->RdOff) { 849 Avail = pRing->RdOff - pRing->WrOff - 1u; 850 } else { 851 Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; 852 } 853 if (NumBytes > Avail) { 854 pRing->RdOff += (NumBytes - Avail); 855 while (pRing->RdOff >= pRing->SizeOfBuffer) { 856 pRing->RdOff -= pRing->SizeOfBuffer; 857 } 858 } 859 // 860 // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds 861 // 862 Avail = pRing->SizeOfBuffer - pRing->WrOff; 863 do { 864 if (Avail > NumBytes) { 865 // 866 // Last round 867 // 868 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 869 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 870 Avail = NumBytes; 871 while (NumBytes--) { 872 *pDst++ = *pData++; 873 }; 874 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 875 pRing->WrOff += Avail; 876 #else 877 SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 878 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 879 pRing->WrOff += NumBytes; 880 #endif 881 break; 882 } else { 883 // 884 // Wrap-around necessary, write until wrap-around and reset WrOff 885 // 886 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 887 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 888 NumBytes -= Avail; 889 while (Avail--) { 890 *pDst++ = *pData++; 891 }; 892 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 893 pRing->WrOff = 0; 894 #else 895 SEGGER_RTT_MEMCPY((void*)pDst, pData, Avail); 896 pData += Avail; 897 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 898 pRing->WrOff = 0; 899 NumBytes -= Avail; 900 #endif 901 Avail = (pRing->SizeOfBuffer - 1); 902 } 903 } while (NumBytes); 904 } 905 906 /********************************************************************* 907 * 908 * SEGGER_RTT_WriteSkipNoLock 909 * 910 * Function description 911 * Stores a specified number of characters in SEGGER RTT 912 * control block which is then read by the host. 913 * SEGGER_RTT_WriteSkipNoLock does not lock the application and 914 * skips all data, if the data does not fit into the buffer. 915 * 916 * Parameters 917 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 918 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 919 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 920 * MUST be > 0!!! 921 * This is done for performance reasons, so no initial check has do be done. 922 * 923 * Return value 924 * 1: Data has been copied 925 * 0: No space, data has not been copied 926 * 927 * Notes 928 * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 929 * (2) For performance reasons this function does not call Init() 930 * and may only be called after RTT has been initialized. 931 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 932 */ 933 #if (RTT_USE_ASM == 0) 934 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 935 const char* pData; 936 SEGGER_RTT_BUFFER_UP* pRing; 937 unsigned Avail; 938 unsigned RdOff; 939 unsigned WrOff; 940 unsigned Rem; 941 volatile char* pDst; 942 // 943 // Cases: 944 // 1) RdOff <= WrOff => Space until wrap-around is sufficient 945 // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 946 // 3) RdOff < WrOff => No space in buf 947 // 4) RdOff > WrOff => Space is sufficient 948 // 5) RdOff > WrOff => No space in buf 949 // 950 // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 951 // 952 pData = (const char *)pBuffer; 953 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 954 RdOff = pRing->RdOff; 955 WrOff = pRing->WrOff; 956 pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 957 if (RdOff <= WrOff) { // Case 1), 2) or 3) 958 Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 959 if (Avail >= NumBytes) { // Case 1)? 960 memcpy((void*)pDst, pData, NumBytes); 961 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 962 pRing->WrOff = WrOff + NumBytes; 963 return 1; 964 } 965 Avail += RdOff; // Space incl. wrap-around 966 if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) 967 Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 968 memcpy((void*)pDst, pData, Rem); // Copy 1st chunk 969 NumBytes -= Rem; 970 // 971 // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used 972 // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element 973 // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks 974 // Therefore, check if 2nd memcpy is necessary at all 975 // 976 if (NumBytes) { 977 pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 978 memcpy((void*)pDst, pData + Rem, NumBytes); 979 } 980 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 981 pRing->WrOff = NumBytes; 982 return 1; 983 } 984 } else { // Potential case 4) 985 Avail = RdOff - WrOff - 1u; 986 if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) 987 memcpy((void*)pDst, pData, NumBytes); 988 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 989 pRing->WrOff = WrOff + NumBytes; 990 return 1; 991 } 992 } 993 return 0; // No space in buffer 994 } 995 #endif 996 997 /********************************************************************* 998 * 999 * SEGGER_RTT_WriteDownBufferNoLock 1000 * 1001 * Function description 1002 * Stores a specified number of characters in SEGGER RTT 1003 * control block inside a <Down> buffer. 1004 * SEGGER_RTT_WriteDownBufferNoLock does not lock the application. 1005 * Used to do the same operation that J-Link does, to transfer 1006 * RTT data from other channels, such as TCP/IP or UART. 1007 * 1008 * Parameters 1009 * BufferIndex Index of "Down"-buffer to be used. 1010 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1011 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1012 * 1013 * Return value 1014 * Number of bytes which have been stored in the "Down"-buffer. 1015 * 1016 * Notes 1017 * (1) Data is stored according to buffer flags. 1018 * (2) For performance reasons this function does not call Init() 1019 * and may only be called after RTT has been initialized. 1020 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1021 * 1022 * Additional information 1023 * This function must not be called when J-Link might also do RTT. 1024 */ 1025 unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1026 unsigned Status; 1027 unsigned Avail; 1028 const char* pData; 1029 SEGGER_RTT_BUFFER_UP* pRing; 1030 // 1031 // Get "to-target" ring buffer. 1032 // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. 1033 // 1034 pData = (const char *)pBuffer; 1035 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1036 // 1037 // How we output depends upon the mode... 1038 // 1039 switch (pRing->Flags) { 1040 case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1041 // 1042 // If we are in skip mode and there is no space for the whole 1043 // of this output, don't bother. 1044 // 1045 Avail = _GetAvailWriteSpace(pRing); 1046 if (Avail < NumBytes) { 1047 Status = 0u; 1048 } else { 1049 Status = NumBytes; 1050 _WriteNoCheck(pRing, pData, NumBytes); 1051 } 1052 break; 1053 case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1054 // 1055 // If we are in trim mode, trim to what we can output without blocking. 1056 // 1057 Avail = _GetAvailWriteSpace(pRing); 1058 Status = Avail < NumBytes ? Avail : NumBytes; 1059 _WriteNoCheck(pRing, pData, Status); 1060 break; 1061 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1062 // 1063 // If we are in blocking mode, output everything. 1064 // 1065 Status = _WriteBlocking(pRing, pData, NumBytes); 1066 break; 1067 default: 1068 Status = 0u; 1069 break; 1070 } 1071 // 1072 // Finish up. 1073 // 1074 return Status; 1075 } 1076 1077 /********************************************************************* 1078 * 1079 * SEGGER_RTT_WriteNoLock 1080 * 1081 * Function description 1082 * Stores a specified number of characters in SEGGER RTT 1083 * control block which is then read by the host. 1084 * SEGGER_RTT_WriteNoLock does not lock the application. 1085 * 1086 * Parameters 1087 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1088 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1089 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1090 * 1091 * Return value 1092 * Number of bytes which have been stored in the "Up"-buffer. 1093 * 1094 * Notes 1095 * (1) Data is stored according to buffer flags. 1096 * (2) For performance reasons this function does not call Init() 1097 * and may only be called after RTT has been initialized. 1098 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1099 */ 1100 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1101 unsigned Status; 1102 unsigned Avail; 1103 const char* pData; 1104 SEGGER_RTT_BUFFER_UP* pRing; 1105 // 1106 // Get "to-host" ring buffer. 1107 // 1108 pData = (const char *)pBuffer; 1109 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1110 // 1111 // How we output depends upon the mode... 1112 // 1113 switch (pRing->Flags) { 1114 case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1115 // 1116 // If we are in skip mode and there is no space for the whole 1117 // of this output, don't bother. 1118 // 1119 Avail = _GetAvailWriteSpace(pRing); 1120 if (Avail < NumBytes) { 1121 Status = 0u; 1122 } else { 1123 Status = NumBytes; 1124 _WriteNoCheck(pRing, pData, NumBytes); 1125 } 1126 break; 1127 case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1128 // 1129 // If we are in trim mode, trim to what we can output without blocking. 1130 // 1131 Avail = _GetAvailWriteSpace(pRing); 1132 Status = Avail < NumBytes ? Avail : NumBytes; 1133 _WriteNoCheck(pRing, pData, Status); 1134 break; 1135 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1136 // 1137 // If we are in blocking mode, output everything. 1138 // 1139 Status = _WriteBlocking(pRing, pData, NumBytes); 1140 break; 1141 default: 1142 Status = 0u; 1143 break; 1144 } 1145 // 1146 // Finish up. 1147 // 1148 return Status; 1149 } 1150 1151 /********************************************************************* 1152 * 1153 * SEGGER_RTT_WriteDownBuffer 1154 * 1155 * Function description 1156 * Stores a specified number of characters in SEGGER RTT control block in a <Down> buffer. 1157 * 1158 * Parameters 1159 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1160 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1161 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1162 * 1163 * Return value 1164 * Number of bytes which have been stored in the "Down"-buffer. 1165 * 1166 * Notes 1167 * (1) Data is stored according to buffer flags. 1168 * 1169 * Additional information 1170 * This function must not be called when J-Link might also do RTT. 1171 * This function locks against all other RTT operations. I.e. during 1172 * the write operation, writing from the application is also locked. 1173 * If only one consumer writes to the down buffer, 1174 * call SEGGER_RTT_WriteDownBufferNoLock() instead. 1175 */ 1176 unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1177 unsigned Status; 1178 1179 INIT(); 1180 SEGGER_RTT_LOCK(); 1181 Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1182 SEGGER_RTT_UNLOCK(); 1183 return Status; 1184 } 1185 1186 /********************************************************************* 1187 * 1188 * SEGGER_RTT_Write 1189 * 1190 * Function description 1191 * Stores a specified number of characters in SEGGER RTT 1192 * control block which is then read by the host. 1193 * 1194 * Parameters 1195 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1196 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1197 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1198 * 1199 * Return value 1200 * Number of bytes which have been stored in the "Up"-buffer. 1201 * 1202 * Notes 1203 * (1) Data is stored according to buffer flags. 1204 */ 1205 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1206 unsigned Status; 1207 1208 INIT(); 1209 SEGGER_RTT_LOCK(); 1210 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1211 SEGGER_RTT_UNLOCK(); 1212 return Status; 1213 } 1214 1215 /********************************************************************* 1216 * 1217 * SEGGER_RTT_WriteString 1218 * 1219 * Function description 1220 * Stores string in SEGGER RTT control block. 1221 * This data is read by the host. 1222 * 1223 * Parameters 1224 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1225 * s Pointer to string. 1226 * 1227 * Return value 1228 * Number of bytes which have been stored in the "Up"-buffer. 1229 * 1230 * Notes 1231 * (1) Data is stored according to buffer flags. 1232 * (2) String passed to this function has to be \0 terminated 1233 * (3) \0 termination character is *not* stored in RTT buffer 1234 */ 1235 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1236 unsigned Len; 1237 1238 Len = STRLEN(s); 1239 return SEGGER_RTT_Write(BufferIndex, s, Len); 1240 } 1241 1242 /********************************************************************* 1243 * 1244 * SEGGER_RTT_PutCharSkipNoLock 1245 * 1246 * Function description 1247 * Stores a single character/byte in SEGGER RTT buffer. 1248 * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1249 * skips the byte, if it does not fit into the buffer. 1250 * 1251 * Parameters 1252 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1253 * c Byte to be stored. 1254 * 1255 * Return value 1256 * Number of bytes which have been stored in the "Up"-buffer. 1257 * 1258 * Notes 1259 * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1260 * (2) For performance reasons this function does not call Init() 1261 * and may only be called after RTT has been initialized. 1262 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1263 */ 1264 1265 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1266 SEGGER_RTT_BUFFER_UP* pRing; 1267 unsigned WrOff; 1268 unsigned Status; 1269 volatile char* pDst; 1270 // 1271 // Get "to-host" ring buffer. 1272 // 1273 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1274 // 1275 // Get write position and handle wrap-around if necessary 1276 // 1277 WrOff = pRing->WrOff + 1; 1278 if (WrOff == pRing->SizeOfBuffer) { 1279 WrOff = 0; 1280 } 1281 // 1282 // Output byte if free space is available 1283 // 1284 if (WrOff != pRing->RdOff) { 1285 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1286 *pDst = c; 1287 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1288 pRing->WrOff = WrOff; 1289 Status = 1; 1290 } else { 1291 Status = 0; 1292 } 1293 // 1294 return Status; 1295 } 1296 1297 /********************************************************************* 1298 * 1299 * SEGGER_RTT_PutCharSkip 1300 * 1301 * Function description 1302 * Stores a single character/byte in SEGGER RTT buffer. 1303 * 1304 * Parameters 1305 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1306 * c Byte to be stored. 1307 * 1308 * Return value 1309 * Number of bytes which have been stored in the "Up"-buffer. 1310 * 1311 * Notes 1312 * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1313 */ 1314 1315 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1316 SEGGER_RTT_BUFFER_UP* pRing; 1317 unsigned WrOff; 1318 unsigned Status; 1319 volatile char* pDst; 1320 // 1321 // Prepare 1322 // 1323 INIT(); 1324 SEGGER_RTT_LOCK(); 1325 // 1326 // Get "to-host" ring buffer. 1327 // 1328 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1329 // 1330 // Get write position and handle wrap-around if necessary 1331 // 1332 WrOff = pRing->WrOff + 1; 1333 if (WrOff == pRing->SizeOfBuffer) { 1334 WrOff = 0; 1335 } 1336 // 1337 // Output byte if free space is available 1338 // 1339 if (WrOff != pRing->RdOff) { 1340 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1341 *pDst = c; 1342 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1343 pRing->WrOff = WrOff; 1344 Status = 1; 1345 } else { 1346 Status = 0; 1347 } 1348 // 1349 // Finish up. 1350 // 1351 SEGGER_RTT_UNLOCK(); 1352 // 1353 return Status; 1354 } 1355 1356 /********************************************************************* 1357 * 1358 * SEGGER_RTT_PutChar 1359 * 1360 * Function description 1361 * Stores a single character/byte in SEGGER RTT buffer. 1362 * 1363 * Parameters 1364 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1365 * c Byte to be stored. 1366 * 1367 * Return value 1368 * Number of bytes which have been stored in the "Up"-buffer. 1369 * 1370 * Notes 1371 * (1) Data is stored according to buffer flags. 1372 */ 1373 1374 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1375 SEGGER_RTT_BUFFER_UP* pRing; 1376 unsigned WrOff; 1377 unsigned Status; 1378 volatile char* pDst; 1379 // 1380 // Prepare 1381 // 1382 INIT(); 1383 SEGGER_RTT_LOCK(); 1384 // 1385 // Get "to-host" ring buffer. 1386 // 1387 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1388 // 1389 // Get write position and handle wrap-around if necessary 1390 // 1391 WrOff = pRing->WrOff + 1; 1392 if (WrOff == pRing->SizeOfBuffer) { 1393 WrOff = 0; 1394 } 1395 // 1396 // Wait for free space if mode is set to blocking 1397 // 1398 if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1399 while (WrOff == pRing->RdOff) { 1400 ; 1401 } 1402 } 1403 // 1404 // Output byte if free space is available 1405 // 1406 if (WrOff != pRing->RdOff) { 1407 pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1408 *pDst = c; 1409 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1410 pRing->WrOff = WrOff; 1411 Status = 1; 1412 } else { 1413 Status = 0; 1414 } 1415 // 1416 // Finish up. 1417 // 1418 SEGGER_RTT_UNLOCK(); 1419 return Status; 1420 } 1421 1422 /********************************************************************* 1423 * 1424 * SEGGER_RTT_GetKey 1425 * 1426 * Function description 1427 * Reads one character from the SEGGER RTT buffer. 1428 * Host has previously stored data there. 1429 * 1430 * Return value 1431 * < 0 - No character available (buffer empty). 1432 * >= 0 - Character which has been read. (Possible values: 0 - 255) 1433 * 1434 * Notes 1435 * (1) This function is only specified for accesses to RTT buffer 0. 1436 */ 1437 int SEGGER_RTT_GetKey(void) { 1438 char c; 1439 int r; 1440 1441 r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1442 if (r == 1) { 1443 r = (int)(unsigned char)c; 1444 } else { 1445 r = -1; 1446 } 1447 return r; 1448 } 1449 1450 /********************************************************************* 1451 * 1452 * SEGGER_RTT_WaitKey 1453 * 1454 * Function description 1455 * Waits until at least one character is avaible in the SEGGER RTT buffer. 1456 * Once a character is available, it is read and this function returns. 1457 * 1458 * Return value 1459 * >=0 - Character which has been read. 1460 * 1461 * Notes 1462 * (1) This function is only specified for accesses to RTT buffer 0 1463 * (2) This function is blocking if no character is present in RTT buffer 1464 */ 1465 int SEGGER_RTT_WaitKey(void) { 1466 int r; 1467 1468 do { 1469 r = SEGGER_RTT_GetKey(); 1470 } while (r < 0); 1471 return r; 1472 } 1473 1474 /********************************************************************* 1475 * 1476 * SEGGER_RTT_HasKey 1477 * 1478 * Function description 1479 * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1480 * 1481 * Return value 1482 * == 0 - No characters are available to read. 1483 * == 1 - At least one character is available. 1484 * 1485 * Notes 1486 * (1) This function is only specified for accesses to RTT buffer 0 1487 */ 1488 int SEGGER_RTT_HasKey(void) { 1489 SEGGER_RTT_BUFFER_DOWN* pRing; 1490 unsigned RdOff; 1491 int r; 1492 1493 INIT(); 1494 pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1495 RdOff = pRing->RdOff; 1496 if (RdOff != pRing->WrOff) { 1497 r = 1; 1498 } else { 1499 r = 0; 1500 } 1501 return r; 1502 } 1503 1504 /********************************************************************* 1505 * 1506 * SEGGER_RTT_HasData 1507 * 1508 * Function description 1509 * Check if there is data from the host in the given buffer. 1510 * 1511 * Return value: 1512 * ==0: No data 1513 * !=0: Data in buffer 1514 * 1515 */ 1516 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1517 SEGGER_RTT_BUFFER_DOWN* pRing; 1518 unsigned v; 1519 1520 pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1521 v = pRing->WrOff; 1522 return v - pRing->RdOff; 1523 } 1524 1525 /********************************************************************* 1526 * 1527 * SEGGER_RTT_HasDataUp 1528 * 1529 * Function description 1530 * Check if there is data remaining to be sent in the given buffer. 1531 * 1532 * Return value: 1533 * ==0: No data 1534 * !=0: Data in buffer 1535 * 1536 */ 1537 unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { 1538 SEGGER_RTT_BUFFER_UP* pRing; 1539 unsigned v; 1540 1541 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1542 v = pRing->RdOff; 1543 return pRing->WrOff - v; 1544 } 1545 1546 /********************************************************************* 1547 * 1548 * SEGGER_RTT_AllocDownBuffer 1549 * 1550 * Function description 1551 * Run-time configuration of the next down-buffer (H->T). 1552 * The next buffer, which is not used yet is configured. 1553 * This includes: Buffer address, size, name, flags, ... 1554 * 1555 * Parameters 1556 * sName Pointer to a constant name string. 1557 * pBuffer Pointer to a buffer to be used. 1558 * BufferSize Size of the buffer. 1559 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1560 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1561 * 1562 * Return value 1563 * >= 0 - O.K. Buffer Index 1564 * < 0 - Error 1565 */ 1566 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1567 int BufferIndex; 1568 volatile SEGGER_RTT_CB* pRTTCB; 1569 1570 INIT(); 1571 SEGGER_RTT_LOCK(); 1572 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1573 BufferIndex = 0; 1574 do { 1575 if (pRTTCB->aDown[BufferIndex].pBuffer == NULL) { 1576 break; 1577 } 1578 BufferIndex++; 1579 } while (BufferIndex < pRTTCB->MaxNumDownBuffers); 1580 if (BufferIndex < pRTTCB->MaxNumDownBuffers) { 1581 pRTTCB->aDown[BufferIndex].sName = sName; 1582 pRTTCB->aDown[BufferIndex].pBuffer = (char*)pBuffer; 1583 pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize; 1584 pRTTCB->aDown[BufferIndex].RdOff = 0u; 1585 pRTTCB->aDown[BufferIndex].WrOff = 0u; 1586 pRTTCB->aDown[BufferIndex].Flags = Flags; 1587 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1588 } else { 1589 BufferIndex = -1; 1590 } 1591 SEGGER_RTT_UNLOCK(); 1592 return BufferIndex; 1593 } 1594 1595 /********************************************************************* 1596 * 1597 * SEGGER_RTT_AllocUpBuffer 1598 * 1599 * Function description 1600 * Run-time configuration of the next up-buffer (T->H). 1601 * The next buffer, which is not used yet is configured. 1602 * This includes: Buffer address, size, name, flags, ... 1603 * 1604 * Parameters 1605 * sName Pointer to a constant name string. 1606 * pBuffer Pointer to a buffer to be used. 1607 * BufferSize Size of the buffer. 1608 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1609 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1610 * 1611 * Return value 1612 * >= 0 - O.K. Buffer Index 1613 * < 0 - Error 1614 */ 1615 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1616 int BufferIndex; 1617 volatile SEGGER_RTT_CB* pRTTCB; 1618 1619 INIT(); 1620 SEGGER_RTT_LOCK(); 1621 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1622 BufferIndex = 0; 1623 do { 1624 if (pRTTCB->aUp[BufferIndex].pBuffer == NULL) { 1625 break; 1626 } 1627 BufferIndex++; 1628 } while (BufferIndex < pRTTCB->MaxNumUpBuffers); 1629 if (BufferIndex < pRTTCB->MaxNumUpBuffers) { 1630 pRTTCB->aUp[BufferIndex].sName = sName; 1631 pRTTCB->aUp[BufferIndex].pBuffer = (char*)pBuffer; 1632 pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize; 1633 pRTTCB->aUp[BufferIndex].RdOff = 0u; 1634 pRTTCB->aUp[BufferIndex].WrOff = 0u; 1635 pRTTCB->aUp[BufferIndex].Flags = Flags; 1636 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1637 } else { 1638 BufferIndex = -1; 1639 } 1640 SEGGER_RTT_UNLOCK(); 1641 return BufferIndex; 1642 } 1643 1644 /********************************************************************* 1645 * 1646 * SEGGER_RTT_ConfigUpBuffer 1647 * 1648 * Function description 1649 * Run-time configuration of a specific up-buffer (T->H). 1650 * Buffer to be configured is specified by index. 1651 * This includes: Buffer address, size, name, flags, ... 1652 * 1653 * Parameters 1654 * BufferIndex Index of the buffer to configure. 1655 * sName Pointer to a constant name string. 1656 * pBuffer Pointer to a buffer to be used. 1657 * BufferSize Size of the buffer. 1658 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1659 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1660 * 1661 * Return value 1662 * >= 0 - O.K. 1663 * < 0 - Error 1664 * 1665 * Additional information 1666 * Buffer 0 is configured on compile-time. 1667 * May only be called once per buffer. 1668 * Buffer name and flags can be reconfigured using the appropriate functions. 1669 */ 1670 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1671 int r; 1672 volatile SEGGER_RTT_CB* pRTTCB; 1673 volatile SEGGER_RTT_BUFFER_UP* pUp; 1674 1675 INIT(); 1676 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1677 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1678 SEGGER_RTT_LOCK(); 1679 pUp = &pRTTCB->aUp[BufferIndex]; 1680 if (BufferIndex) { 1681 pUp->sName = sName; 1682 pUp->pBuffer = (char*)pBuffer; 1683 pUp->SizeOfBuffer = BufferSize; 1684 pUp->RdOff = 0u; 1685 pUp->WrOff = 0u; 1686 } 1687 pUp->Flags = Flags; 1688 SEGGER_RTT_UNLOCK(); 1689 r = 0; 1690 } else { 1691 r = -1; 1692 } 1693 return r; 1694 } 1695 1696 /********************************************************************* 1697 * 1698 * SEGGER_RTT_ConfigDownBuffer 1699 * 1700 * Function description 1701 * Run-time configuration of a specific down-buffer (H->T). 1702 * Buffer to be configured is specified by index. 1703 * This includes: Buffer address, size, name, flags, ... 1704 * 1705 * Parameters 1706 * BufferIndex Index of the buffer to configure. 1707 * sName Pointer to a constant name string. 1708 * pBuffer Pointer to a buffer to be used. 1709 * BufferSize Size of the buffer. 1710 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1711 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1712 * 1713 * Return value 1714 * >= 0 O.K. 1715 * < 0 Error 1716 * 1717 * Additional information 1718 * Buffer 0 is configured on compile-time. 1719 * May only be called once per buffer. 1720 * Buffer name and flags can be reconfigured using the appropriate functions. 1721 */ 1722 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1723 int r; 1724 volatile SEGGER_RTT_CB* pRTTCB; 1725 volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1726 1727 INIT(); 1728 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1729 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1730 SEGGER_RTT_LOCK(); 1731 pDown = &pRTTCB->aDown[BufferIndex]; 1732 if (BufferIndex) { 1733 pDown->sName = sName; 1734 pDown->pBuffer = (char*)pBuffer; 1735 pDown->SizeOfBuffer = BufferSize; 1736 pDown->RdOff = 0u; 1737 pDown->WrOff = 0u; 1738 } 1739 pDown->Flags = Flags; 1740 RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses 1741 SEGGER_RTT_UNLOCK(); 1742 r = 0; 1743 } else { 1744 r = -1; 1745 } 1746 return r; 1747 } 1748 1749 /********************************************************************* 1750 * 1751 * SEGGER_RTT_SetNameUpBuffer 1752 * 1753 * Function description 1754 * Run-time configuration of a specific up-buffer name (T->H). 1755 * Buffer to be configured is specified by index. 1756 * 1757 * Parameters 1758 * BufferIndex Index of the buffer to renamed. 1759 * sName Pointer to a constant name string. 1760 * 1761 * Return value 1762 * >= 0 O.K. 1763 * < 0 Error 1764 */ 1765 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1766 int r; 1767 volatile SEGGER_RTT_CB* pRTTCB; 1768 volatile SEGGER_RTT_BUFFER_UP* pUp; 1769 1770 INIT(); 1771 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1772 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1773 SEGGER_RTT_LOCK(); 1774 pUp = &pRTTCB->aUp[BufferIndex]; 1775 pUp->sName = sName; 1776 SEGGER_RTT_UNLOCK(); 1777 r = 0; 1778 } else { 1779 r = -1; 1780 } 1781 return r; 1782 } 1783 1784 /********************************************************************* 1785 * 1786 * SEGGER_RTT_SetNameDownBuffer 1787 * 1788 * Function description 1789 * Run-time configuration of a specific Down-buffer name (T->H). 1790 * Buffer to be configured is specified by index. 1791 * 1792 * Parameters 1793 * BufferIndex Index of the buffer to renamed. 1794 * sName Pointer to a constant name string. 1795 * 1796 * Return value 1797 * >= 0 O.K. 1798 * < 0 Error 1799 */ 1800 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1801 int r; 1802 volatile SEGGER_RTT_CB* pRTTCB; 1803 volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1804 1805 INIT(); 1806 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1807 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1808 SEGGER_RTT_LOCK(); 1809 pDown = &pRTTCB->aDown[BufferIndex]; 1810 pDown->sName = sName; 1811 SEGGER_RTT_UNLOCK(); 1812 r = 0; 1813 } else { 1814 r = -1; 1815 } 1816 return r; 1817 } 1818 1819 /********************************************************************* 1820 * 1821 * SEGGER_RTT_SetFlagsUpBuffer 1822 * 1823 * Function description 1824 * Run-time configuration of specific up-buffer flags (T->H). 1825 * Buffer to be configured is specified by index. 1826 * 1827 * Parameters 1828 * BufferIndex Index of the buffer. 1829 * Flags Flags to set for the buffer. 1830 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1831 * 1832 * Return value 1833 * >= 0 O.K. 1834 * < 0 Error 1835 */ 1836 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1837 int r; 1838 volatile SEGGER_RTT_CB* pRTTCB; 1839 volatile SEGGER_RTT_BUFFER_UP* pUp; 1840 1841 INIT(); 1842 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1843 if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1844 SEGGER_RTT_LOCK(); 1845 pUp = &pRTTCB->aUp[BufferIndex]; 1846 pUp->Flags = Flags; 1847 SEGGER_RTT_UNLOCK(); 1848 r = 0; 1849 } else { 1850 r = -1; 1851 } 1852 return r; 1853 } 1854 1855 /********************************************************************* 1856 * 1857 * SEGGER_RTT_SetFlagsDownBuffer 1858 * 1859 * Function description 1860 * Run-time configuration of specific Down-buffer flags (T->H). 1861 * Buffer to be configured is specified by index. 1862 * 1863 * Parameters 1864 * BufferIndex Index of the buffer to renamed. 1865 * Flags Flags to set for the buffer. 1866 * Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. 1867 * 1868 * Return value 1869 * >= 0 O.K. 1870 * < 0 Error 1871 */ 1872 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1873 int r; 1874 volatile SEGGER_RTT_CB* pRTTCB; 1875 volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1876 1877 INIT(); 1878 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1879 if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1880 SEGGER_RTT_LOCK(); 1881 pDown = &pRTTCB->aDown[BufferIndex]; 1882 pDown->Flags = Flags; 1883 SEGGER_RTT_UNLOCK(); 1884 r = 0; 1885 } else { 1886 r = -1; 1887 } 1888 return r; 1889 } 1890 1891 /********************************************************************* 1892 * 1893 * SEGGER_RTT_Init 1894 * 1895 * Function description 1896 * Initializes the RTT Control Block. 1897 * Should be used in RAM targets, at start of the application. 1898 * 1899 */ 1900 void SEGGER_RTT_Init (void) { 1901 _DoInit(); 1902 } 1903 1904 /********************************************************************* 1905 * 1906 * SEGGER_RTT_SetTerminal 1907 * 1908 * Function description 1909 * Sets the terminal to be used for output on channel 0. 1910 * 1911 * Parameters 1912 * TerminalId Index of the terminal. 1913 * 1914 * Return value 1915 * >= 0 O.K. 1916 * < 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) 1917 * 1918 * Notes 1919 * (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1920 */ 1921 int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { 1922 unsigned char ac[2]; 1923 SEGGER_RTT_BUFFER_UP* pRing; 1924 unsigned Avail; 1925 int r; 1926 1927 INIT(); 1928 r = 0; 1929 ac[0] = 0xFFu; 1930 if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels 1931 ac[1] = _aTerminalId[TerminalId]; 1932 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1933 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 1934 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1935 _ActiveTerminal = TerminalId; 1936 _WriteBlocking(pRing, (const char*)ac, 2u); 1937 } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1938 Avail = _GetAvailWriteSpace(pRing); 1939 if (Avail >= 2) { 1940 _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1941 _WriteNoCheck(pRing, (const char*)ac, 2u); 1942 } else { 1943 r = -1; 1944 } 1945 } 1946 SEGGER_RTT_UNLOCK(); 1947 } else { 1948 r = -1; 1949 } 1950 return r; 1951 } 1952 1953 /********************************************************************* 1954 * 1955 * SEGGER_RTT_TerminalOut 1956 * 1957 * Function description 1958 * Writes a string to the given terminal 1959 * without changing the terminal for channel 0. 1960 * 1961 * Parameters 1962 * TerminalId Index of the terminal. 1963 * s String to be printed on the terminal. 1964 * 1965 * Return value 1966 * >= 0 - Number of bytes written. 1967 * < 0 - Error. 1968 * 1969 */ 1970 int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { 1971 int Status; 1972 unsigned FragLen; 1973 unsigned Avail; 1974 SEGGER_RTT_BUFFER_UP* pRing; 1975 // 1976 INIT(); 1977 // 1978 // Validate terminal ID. 1979 // 1980 if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1981 // 1982 // Get "to-host" ring buffer. 1983 // 1984 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1985 // 1986 // Need to be able to change terminal, write data, change back. 1987 // Compute the fixed and variable sizes. 1988 // 1989 FragLen = STRLEN(s); 1990 // 1991 // How we output depends upon the mode... 1992 // 1993 SEGGER_RTT_LOCK(); 1994 Avail = _GetAvailWriteSpace(pRing); 1995 switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1996 case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1997 // 1998 // If we are in skip mode and there is no space for the whole 1999 // of this output, don't bother switching terminals at all. 2000 // 2001 if (Avail < (FragLen + 4u)) { 2002 Status = 0; 2003 } else { 2004 _PostTerminalSwitch(pRing, TerminalId); 2005 Status = (int)_WriteBlocking(pRing, s, FragLen); 2006 _PostTerminalSwitch(pRing, _ActiveTerminal); 2007 } 2008 break; 2009 case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 2010 // 2011 // If we are in trim mode and there is not enough space for everything, 2012 // trim the output but always include the terminal switch. If no room 2013 // for terminal switch, skip that totally. 2014 // 2015 if (Avail < 4u) { 2016 Status = -1; 2017 } else { 2018 _PostTerminalSwitch(pRing, TerminalId); 2019 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 2020 _PostTerminalSwitch(pRing, _ActiveTerminal); 2021 } 2022 break; 2023 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 2024 // 2025 // If we are in blocking mode, output everything. 2026 // 2027 _PostTerminalSwitch(pRing, TerminalId); 2028 Status = (int)_WriteBlocking(pRing, s, FragLen); 2029 _PostTerminalSwitch(pRing, _ActiveTerminal); 2030 break; 2031 default: 2032 Status = -1; 2033 break; 2034 } 2035 // 2036 // Finish up. 2037 // 2038 SEGGER_RTT_UNLOCK(); 2039 } else { 2040 Status = -1; 2041 } 2042 return Status; 2043 } 2044 2045 /********************************************************************* 2046 * 2047 * SEGGER_RTT_GetAvailWriteSpace 2048 * 2049 * Function description 2050 * Returns the number of bytes available in the ring buffer. 2051 * 2052 * Parameters 2053 * BufferIndex Index of the up buffer. 2054 * 2055 * Return value 2056 * Number of bytes that are free in the selected up buffer. 2057 */ 2058 unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex) { 2059 SEGGER_RTT_BUFFER_UP* pRing; 2060 2061 pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 2062 return _GetAvailWriteSpace(pRing); 2063 } 2064 2065 2066 /********************************************************************* 2067 * 2068 * SEGGER_RTT_GetBytesInBuffer() 2069 * 2070 * Function description 2071 * Returns the number of bytes currently used in the up buffer. 2072 * 2073 * Parameters 2074 * BufferIndex Index of the up buffer. 2075 * 2076 * Return value 2077 * Number of bytes that are used in the buffer. 2078 */ 2079 unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { 2080 unsigned RdOff; 2081 unsigned WrOff; 2082 unsigned r; 2083 volatile SEGGER_RTT_CB* pRTTCB; 2084 // 2085 // Avoid warnings regarding volatile access order. It's not a problem 2086 // in this case, but dampen compiler enthusiasm. 2087 // 2088 pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 2089 RdOff = pRTTCB->aUp[BufferIndex].RdOff; 2090 WrOff = pRTTCB->aUp[BufferIndex].WrOff; 2091 if (RdOff <= WrOff) { 2092 r = WrOff - RdOff; 2093 } else { 2094 r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 2095 } 2096 return r; 2097 } 2098 2099 /*************************** End of file ****************************/ 2100