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