1 /********************************************************************* 2 * SEGGER MICROCONTROLLER GmbH & Co. KG * 3 * Solutions for real time microcontroller applications * 4 ********************************************************************** 5 * * 6 * (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * 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 & Co. KG * 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: 6852 $ 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 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 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, 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 * 738 * Return value 739 * Number of bytes which have been stored in the "Up"-buffer. 740 * 741 * Notes 742 * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 743 * (2) For performance reasons this function does not call Init() 744 * and may only be called after RTT has been initialized. 745 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 746 */ 747 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 748 const char* pData; 749 SEGGER_RTT_BUFFER_UP* pRing; 750 unsigned Avail; 751 unsigned RdOff; 752 unsigned WrOff; 753 unsigned Rem; 754 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 755 char* pDst; 756 #endif 757 758 pData = (const char *)pBuffer; 759 // 760 // Get "to-host" ring buffer and copy some elements into local variables. 761 // 762 pRing = &_SEGGER_RTT.aUp[BufferIndex]; 763 RdOff = pRing->RdOff; 764 WrOff = pRing->WrOff; 765 // 766 // Handle the most common cases fastest. 767 // Which is: 768 // RdOff <= WrOff -> Space until wrap around is free. 769 // AND 770 // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. 771 // 772 // OR 773 // 774 // RdOff > WrOff -> Space until RdOff - 1 is free. 775 // AND 776 // WrOff + NumBytes < RdOff -> Data fits into buffer 777 // 778 if (RdOff <= WrOff) { 779 // 780 // Get space until WrOff will be at wrap around. 781 // 782 Avail = pRing->SizeOfBuffer - 1u - WrOff ; 783 if (Avail >= NumBytes) { 784 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 785 pDst = pRing->pBuffer + WrOff; 786 WrOff += NumBytes; 787 while (NumBytes--) { 788 *pDst++ = *pData++; 789 }; 790 pRing->WrOff = WrOff; 791 #else 792 SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); 793 pRing->WrOff = WrOff + NumBytes; 794 #endif 795 return 1; 796 } 797 // 798 // If data did not fit into space until wrap around calculate complete space in buffer. 799 // 800 Avail += RdOff; 801 // 802 // If there is still no space for the whole of this output, don't bother. 803 // 804 if (Avail >= NumBytes) { 805 // 806 // OK, we have enough space in buffer. Copy in one or 2 chunks 807 // 808 Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 809 if (Rem > NumBytes) { 810 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 811 pDst = pRing->pBuffer + WrOff; 812 WrOff += NumBytes; 813 while (NumBytes--) { 814 *pDst++ = *pData++; 815 }; 816 pRing->WrOff = WrOff; 817 #else 818 SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); 819 pRing->WrOff = WrOff + NumBytes; 820 #endif 821 } else { 822 // 823 // We reach the end of the buffer, so need to wrap around 824 // 825 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 826 pDst = pRing->pBuffer + WrOff; 827 NumBytes -= Rem; 828 WrOff = NumBytes; 829 do { 830 *pDst++ = *pData++; 831 } while (--Rem); 832 pDst = pRing->pBuffer; 833 do { 834 *pDst++ = *pData++; 835 } while (--NumBytes); 836 pRing->WrOff = WrOff; 837 #else 838 SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, Rem); 839 SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytes - Rem); 840 pRing->WrOff = NumBytes - Rem; 841 #endif 842 } 843 return 1; 844 } 845 } else { 846 Avail = RdOff - WrOff - 1u; 847 if (Avail >= NumBytes) { 848 #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 849 pDst = pRing->pBuffer + WrOff; 850 WrOff += NumBytes; 851 while (NumBytes--) { 852 *pDst++ = *pData++; 853 }; 854 pRing->WrOff = WrOff; 855 #else 856 SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); 857 pRing->WrOff = WrOff + NumBytes; 858 #endif 859 return 1; 860 } 861 } 862 // 863 // If we reach this point no data has been written 864 // 865 return 0; 866 } 867 868 /********************************************************************* 869 * 870 * SEGGER_RTT_WriteNoLock 871 * 872 * Function description 873 * Stores a specified number of characters in SEGGER RTT 874 * control block which is then read by the host. 875 * SEGGER_RTT_WriteNoLock does not lock the application. 876 * 877 * Parameters 878 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 879 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 880 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 881 * 882 * Return value 883 * Number of bytes which have been stored in the "Up"-buffer. 884 * 885 * Notes 886 * (1) Data is stored according to buffer flags. 887 * (2) For performance reasons this function does not call Init() 888 * and may only be called after RTT has been initialized. 889 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 890 */ 891 unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 892 unsigned Status; 893 unsigned Avail; 894 const char* pData; 895 SEGGER_RTT_BUFFER_UP* pRing; 896 897 pData = (const char *)pBuffer; 898 // 899 // Get "to-host" ring buffer. 900 // 901 pRing = &_SEGGER_RTT.aUp[BufferIndex]; 902 // 903 // How we output depends upon the mode... 904 // 905 switch (pRing->Flags) { 906 case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 907 // 908 // If we are in skip mode and there is no space for the whole 909 // of this output, don't bother. 910 // 911 Avail = _GetAvailWriteSpace(pRing); 912 if (Avail < NumBytes) { 913 Status = 0u; 914 } else { 915 Status = NumBytes; 916 _WriteNoCheck(pRing, pData, NumBytes); 917 } 918 break; 919 case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 920 // 921 // If we are in trim mode, trim to what we can output without blocking. 922 // 923 Avail = _GetAvailWriteSpace(pRing); 924 Status = Avail < NumBytes ? Avail : NumBytes; 925 _WriteNoCheck(pRing, pData, Status); 926 break; 927 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 928 // 929 // If we are in blocking mode, output everything. 930 // 931 Status = _WriteBlocking(pRing, pData, NumBytes); 932 break; 933 default: 934 Status = 0u; 935 break; 936 } 937 // 938 // Finish up. 939 // 940 return Status; 941 } 942 943 /********************************************************************* 944 * 945 * SEGGER_RTT_Write 946 * 947 * Function description 948 * Stores a specified number of characters in SEGGER RTT 949 * control block which is then read by the host. 950 * 951 * Parameters 952 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 953 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 954 * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 955 * 956 * Return value 957 * Number of bytes which have been stored in the "Up"-buffer. 958 * 959 * Notes 960 * (1) Data is stored according to buffer flags. 961 */ 962 unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 963 unsigned Status; 964 // 965 INIT(); 966 SEGGER_RTT_LOCK(); 967 // 968 // Call the non-locking write function 969 // 970 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); 971 // 972 // Finish up. 973 // 974 SEGGER_RTT_UNLOCK(); 975 // 976 return Status; 977 } 978 979 /********************************************************************* 980 * 981 * SEGGER_RTT_WriteString 982 * 983 * Function description 984 * Stores string in SEGGER RTT control block. 985 * This data is read by the host. 986 * 987 * Parameters 988 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 989 * s Pointer to string. 990 * 991 * Return value 992 * Number of bytes which have been stored in the "Up"-buffer. 993 * 994 * Notes 995 * (1) Data is stored according to buffer flags. 996 * (2) String passed to this function has to be \0 terminated 997 * (3) \0 termination character is *not* stored in RTT buffer 998 */ 999 unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1000 unsigned Len; 1001 1002 Len = STRLEN(s); 1003 return SEGGER_RTT_Write(BufferIndex, s, Len); 1004 } 1005 1006 /********************************************************************* 1007 * 1008 * SEGGER_RTT_PutCharSkipNoLock 1009 * 1010 * Function description 1011 * Stores a single character/byte in SEGGER RTT buffer. 1012 * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1013 * skips the byte, if it does not fit into the buffer. 1014 * 1015 * Parameters 1016 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1017 * c Byte to be stored. 1018 * 1019 * Return value 1020 * Number of bytes which have been stored in the "Up"-buffer. 1021 * 1022 * Notes 1023 * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1024 * (2) For performance reasons this function does not call Init() 1025 * and may only be called after RTT has been initialized. 1026 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1027 */ 1028 1029 unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1030 SEGGER_RTT_BUFFER_UP* pRing; 1031 unsigned WrOff; 1032 unsigned Status; 1033 // 1034 // Get "to-host" ring buffer. 1035 // 1036 pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1037 // 1038 // Get write position and handle wrap-around if necessary 1039 // 1040 WrOff = pRing->WrOff + 1; 1041 if (WrOff == pRing->SizeOfBuffer) { 1042 WrOff = 0; 1043 } 1044 // 1045 // Output byte if free space is available 1046 // 1047 if (WrOff != pRing->RdOff) { 1048 pRing->pBuffer[pRing->WrOff] = c; 1049 pRing->WrOff = WrOff; 1050 Status = 1; 1051 } else { 1052 Status = 0; 1053 } 1054 // 1055 return Status; 1056 } 1057 1058 /********************************************************************* 1059 * 1060 * SEGGER_RTT_PutCharSkip 1061 * 1062 * Function description 1063 * Stores a single character/byte in SEGGER RTT buffer. 1064 * 1065 * Parameters 1066 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1067 * c Byte to be stored. 1068 * 1069 * Return value 1070 * Number of bytes which have been stored in the "Up"-buffer. 1071 * 1072 * Notes 1073 * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1074 */ 1075 1076 unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1077 SEGGER_RTT_BUFFER_UP* pRing; 1078 unsigned WrOff; 1079 unsigned Status; 1080 // 1081 // Prepare 1082 // 1083 INIT(); 1084 SEGGER_RTT_LOCK(); 1085 // 1086 // Get "to-host" ring buffer. 1087 // 1088 pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1089 // 1090 // Get write position and handle wrap-around if necessary 1091 // 1092 WrOff = pRing->WrOff + 1; 1093 if (WrOff == pRing->SizeOfBuffer) { 1094 WrOff = 0; 1095 } 1096 // 1097 // Output byte if free space is available 1098 // 1099 if (WrOff != pRing->RdOff) { 1100 pRing->pBuffer[pRing->WrOff] = c; 1101 pRing->WrOff = WrOff; 1102 Status = 1; 1103 } else { 1104 Status = 0; 1105 } 1106 // 1107 // Finish up. 1108 // 1109 SEGGER_RTT_UNLOCK(); 1110 // 1111 return Status; 1112 } 1113 1114 /********************************************************************* 1115 * 1116 * SEGGER_RTT_PutChar 1117 * 1118 * Function description 1119 * Stores a single character/byte in SEGGER RTT buffer. 1120 * 1121 * Parameters 1122 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1123 * c Byte to be stored. 1124 * 1125 * Return value 1126 * Number of bytes which have been stored in the "Up"-buffer. 1127 * 1128 * Notes 1129 * (1) Data is stored according to buffer flags. 1130 */ 1131 1132 unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1133 SEGGER_RTT_BUFFER_UP* pRing; 1134 unsigned WrOff; 1135 unsigned Status; 1136 // 1137 // Prepare 1138 // 1139 INIT(); 1140 SEGGER_RTT_LOCK(); 1141 // 1142 // Get "to-host" ring buffer. 1143 // 1144 pRing = &_SEGGER_RTT.aUp[BufferIndex]; 1145 // 1146 // Get write position and handle wrap-around if necessary 1147 // 1148 WrOff = pRing->WrOff + 1; 1149 if (WrOff == pRing->SizeOfBuffer) { 1150 WrOff = 0; 1151 } 1152 // 1153 // Wait for free space if mode is set to blocking 1154 // 1155 if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1156 while (WrOff == pRing->RdOff) { 1157 ; 1158 } 1159 } 1160 // 1161 // Output byte if free space is available 1162 // 1163 if (WrOff != pRing->RdOff) { 1164 pRing->pBuffer[pRing->WrOff] = c; 1165 pRing->WrOff = WrOff; 1166 Status = 1; 1167 } else { 1168 Status = 0; 1169 } 1170 // 1171 // Finish up. 1172 // 1173 SEGGER_RTT_UNLOCK(); 1174 // 1175 return Status; 1176 } 1177 1178 /********************************************************************* 1179 * 1180 * SEGGER_RTT_GetKey 1181 * 1182 * Function description 1183 * Reads one character from the SEGGER RTT buffer. 1184 * Host has previously stored data there. 1185 * 1186 * Return value 1187 * < 0 - No character available (buffer empty). 1188 * >= 0 - Character which has been read. (Possible values: 0 - 255) 1189 * 1190 * Notes 1191 * (1) This function is only specified for accesses to RTT buffer 0. 1192 */ 1193 int SEGGER_RTT_GetKey(void) { 1194 char c; 1195 int r; 1196 1197 r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1198 if (r == 1) { 1199 r = (int)(unsigned char)c; 1200 } else { 1201 r = -1; 1202 } 1203 return r; 1204 } 1205 1206 /********************************************************************* 1207 * 1208 * SEGGER_RTT_WaitKey 1209 * 1210 * Function description 1211 * Waits until at least one character is avaible in the SEGGER RTT buffer. 1212 * Once a character is available, it is read and this function returns. 1213 * 1214 * Return value 1215 * >=0 - Character which has been read. 1216 * 1217 * Notes 1218 * (1) This function is only specified for accesses to RTT buffer 0 1219 * (2) This function is blocking if no character is present in RTT buffer 1220 */ 1221 int SEGGER_RTT_WaitKey(void) { 1222 int r; 1223 1224 do { 1225 r = SEGGER_RTT_GetKey(); 1226 } while (r < 0); 1227 return r; 1228 } 1229 1230 /********************************************************************* 1231 * 1232 * SEGGER_RTT_HasKey 1233 * 1234 * Function description 1235 * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1236 * 1237 * Return value 1238 * == 0 - No characters are available to read. 1239 * == 1 - At least one character is available. 1240 * 1241 * Notes 1242 * (1) This function is only specified for accesses to RTT buffer 0 1243 */ 1244 int SEGGER_RTT_HasKey(void) { 1245 unsigned RdOff; 1246 int r; 1247 1248 INIT(); 1249 RdOff = _SEGGER_RTT.aDown[0].RdOff; 1250 if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { 1251 r = 1; 1252 } else { 1253 r = 0; 1254 } 1255 return r; 1256 } 1257 1258 /********************************************************************* 1259 * 1260 * SEGGER_RTT_HasData 1261 * 1262 * Function description 1263 * Check if there is data from the host in the given buffer. 1264 * 1265 * Return value: 1266 * ==0: No data 1267 * !=0: Data in buffer 1268 * 1269 */ 1270 unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1271 SEGGER_RTT_BUFFER_DOWN* pRing; 1272 unsigned v; 1273 1274 pRing = &_SEGGER_RTT.aDown[BufferIndex]; 1275 v = pRing->WrOff; 1276 return v - pRing->RdOff; 1277 } 1278 1279 /********************************************************************* 1280 * 1281 * SEGGER_RTT_AllocDownBuffer 1282 * 1283 * Function description 1284 * Run-time configuration of the next down-buffer (H->T). 1285 * The next buffer, which is not used yet is configured. 1286 * This includes: Buffer address, size, name, flags, ... 1287 * 1288 * Parameters 1289 * sName Pointer to a constant name string. 1290 * pBuffer Pointer to a buffer to be used. 1291 * BufferSize Size of the buffer. 1292 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1293 * 1294 * Return value 1295 * >= 0 - O.K. Buffer Index 1296 * < 0 - Error 1297 */ 1298 int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1299 int BufferIndex; 1300 1301 INIT(); 1302 SEGGER_RTT_LOCK(); 1303 BufferIndex = 0; 1304 do { 1305 if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { 1306 break; 1307 } 1308 BufferIndex++; 1309 } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); 1310 if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { 1311 _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1312 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; 1313 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; 1314 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; 1315 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; 1316 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1317 } else { 1318 BufferIndex = -1; 1319 } 1320 SEGGER_RTT_UNLOCK(); 1321 return BufferIndex; 1322 } 1323 1324 /********************************************************************* 1325 * 1326 * SEGGER_RTT_AllocUpBuffer 1327 * 1328 * Function description 1329 * Run-time configuration of the next up-buffer (T->H). 1330 * The next buffer, which is not used yet is configured. 1331 * This includes: Buffer address, size, name, flags, ... 1332 * 1333 * Parameters 1334 * sName Pointer to a constant name string. 1335 * pBuffer Pointer to a buffer to be used. 1336 * BufferSize Size of the buffer. 1337 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1338 * 1339 * Return value 1340 * >= 0 - O.K. Buffer Index 1341 * < 0 - Error 1342 */ 1343 int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1344 int BufferIndex; 1345 1346 INIT(); 1347 SEGGER_RTT_LOCK(); 1348 BufferIndex = 0; 1349 do { 1350 if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { 1351 break; 1352 } 1353 BufferIndex++; 1354 } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); 1355 if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { 1356 _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1357 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; 1358 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; 1359 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; 1360 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; 1361 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1362 } else { 1363 BufferIndex = -1; 1364 } 1365 SEGGER_RTT_UNLOCK(); 1366 return BufferIndex; 1367 } 1368 1369 /********************************************************************* 1370 * 1371 * SEGGER_RTT_ConfigUpBuffer 1372 * 1373 * Function description 1374 * Run-time configuration of a specific up-buffer (T->H). 1375 * Buffer to be configured is specified by index. 1376 * This includes: Buffer address, size, name, flags, ... 1377 * 1378 * Parameters 1379 * BufferIndex Index of the buffer to configure. 1380 * sName Pointer to a constant name string. 1381 * pBuffer Pointer to a buffer to be used. 1382 * BufferSize Size of the buffer. 1383 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1384 * 1385 * Return value 1386 * >= 0 - O.K. 1387 * < 0 - Error 1388 * 1389 * Additional information 1390 * Buffer 0 is configured on compile-time. 1391 * May only be called once per buffer. 1392 * Buffer name and flags can be reconfigured using the appropriate functions. 1393 */ 1394 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1395 int r; 1396 1397 INIT(); 1398 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1399 SEGGER_RTT_LOCK(); 1400 if (BufferIndex > 0u) { 1401 _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1402 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; 1403 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; 1404 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; 1405 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; 1406 } 1407 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1408 SEGGER_RTT_UNLOCK(); 1409 r = 0; 1410 } else { 1411 r = -1; 1412 } 1413 return r; 1414 } 1415 1416 /********************************************************************* 1417 * 1418 * SEGGER_RTT_ConfigDownBuffer 1419 * 1420 * Function description 1421 * Run-time configuration of a specific down-buffer (H->T). 1422 * Buffer to be configured is specified by index. 1423 * This includes: Buffer address, size, name, flags, ... 1424 * 1425 * Parameters 1426 * BufferIndex Index of the buffer to configure. 1427 * sName Pointer to a constant name string. 1428 * pBuffer Pointer to a buffer to be used. 1429 * BufferSize Size of the buffer. 1430 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1431 * 1432 * Return value 1433 * >= 0 O.K. 1434 * < 0 Error 1435 * 1436 * Additional information 1437 * Buffer 0 is configured on compile-time. 1438 * May only be called once per buffer. 1439 * Buffer name and flags can be reconfigured using the appropriate functions. 1440 */ 1441 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1442 int r; 1443 1444 INIT(); 1445 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1446 SEGGER_RTT_LOCK(); 1447 if (BufferIndex > 0u) { 1448 _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1449 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; 1450 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; 1451 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; 1452 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; 1453 } 1454 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1455 SEGGER_RTT_UNLOCK(); 1456 r = 0; 1457 } else { 1458 r = -1; 1459 } 1460 return r; 1461 } 1462 1463 /********************************************************************* 1464 * 1465 * SEGGER_RTT_SetNameUpBuffer 1466 * 1467 * Function description 1468 * Run-time configuration of a specific up-buffer name (T->H). 1469 * Buffer to be configured is specified by index. 1470 * 1471 * Parameters 1472 * BufferIndex Index of the buffer to renamed. 1473 * sName Pointer to a constant name string. 1474 * 1475 * Return value 1476 * >= 0 O.K. 1477 * < 0 Error 1478 */ 1479 int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1480 int r; 1481 1482 INIT(); 1483 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1484 SEGGER_RTT_LOCK(); 1485 _SEGGER_RTT.aUp[BufferIndex].sName = sName; 1486 SEGGER_RTT_UNLOCK(); 1487 r = 0; 1488 } else { 1489 r = -1; 1490 } 1491 return r; 1492 } 1493 1494 /********************************************************************* 1495 * 1496 * SEGGER_RTT_SetNameDownBuffer 1497 * 1498 * Function description 1499 * Run-time configuration of a specific Down-buffer name (T->H). 1500 * Buffer to be configured is specified by index. 1501 * 1502 * Parameters 1503 * BufferIndex Index of the buffer to renamed. 1504 * sName Pointer to a constant name string. 1505 * 1506 * Return value 1507 * >= 0 O.K. 1508 * < 0 Error 1509 */ 1510 int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1511 int r; 1512 1513 INIT(); 1514 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1515 SEGGER_RTT_LOCK(); 1516 _SEGGER_RTT.aDown[BufferIndex].sName = sName; 1517 SEGGER_RTT_UNLOCK(); 1518 r = 0; 1519 } else { 1520 r = -1; 1521 } 1522 return r; 1523 } 1524 1525 /********************************************************************* 1526 * 1527 * SEGGER_RTT_SetFlagsUpBuffer 1528 * 1529 * Function description 1530 * Run-time configuration of specific up-buffer flags (T->H). 1531 * Buffer to be configured is specified by index. 1532 * 1533 * Parameters 1534 * BufferIndex Index of the buffer. 1535 * Flags Flags to set for the buffer. 1536 * 1537 * Return value 1538 * >= 0 O.K. 1539 * < 0 Error 1540 */ 1541 int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1542 int r; 1543 1544 INIT(); 1545 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { 1546 SEGGER_RTT_LOCK(); 1547 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; 1548 SEGGER_RTT_UNLOCK(); 1549 r = 0; 1550 } else { 1551 r = -1; 1552 } 1553 return r; 1554 } 1555 1556 /********************************************************************* 1557 * 1558 * SEGGER_RTT_SetFlagsDownBuffer 1559 * 1560 * Function description 1561 * Run-time configuration of specific Down-buffer flags (T->H). 1562 * Buffer to be configured is specified by index. 1563 * 1564 * Parameters 1565 * BufferIndex Index of the buffer to renamed. 1566 * Flags Flags to set for the buffer. 1567 * 1568 * Return value 1569 * >= 0 O.K. 1570 * < 0 Error 1571 */ 1572 int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1573 int r; 1574 1575 INIT(); 1576 if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { 1577 SEGGER_RTT_LOCK(); 1578 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; 1579 SEGGER_RTT_UNLOCK(); 1580 r = 0; 1581 } else { 1582 r = -1; 1583 } 1584 return r; 1585 } 1586 1587 /********************************************************************* 1588 * 1589 * SEGGER_RTT_Init 1590 * 1591 * Function description 1592 * Initializes the RTT Control Block. 1593 * Should be used in RAM targets, at start of the application. 1594 * 1595 */ 1596 void SEGGER_RTT_Init (void) { 1597 _DoInit(); 1598 } 1599 1600 /********************************************************************* 1601 * 1602 * SEGGER_RTT_SetTerminal 1603 * 1604 * Function description 1605 * Sets the terminal to be used for output on channel 0. 1606 * 1607 * Parameters 1608 * TerminalId Index of the terminal. 1609 * 1610 * Return value 1611 * >= 0 O.K. 1612 * < 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) 1613 */ 1614 int SEGGER_RTT_SetTerminal (char TerminalId) { 1615 char ac[2]; 1616 SEGGER_RTT_BUFFER_UP* pRing; 1617 unsigned Avail; 1618 int r; 1619 // 1620 INIT(); 1621 // 1622 r = 0; 1623 ac[0] = 0xFFU; 1624 if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1625 ac[1] = _aTerminalId[(unsigned char)TerminalId]; 1626 pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1627 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 1628 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1629 _ActiveTerminal = TerminalId; 1630 _WriteBlocking(pRing, ac, 2u); 1631 } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1632 Avail = _GetAvailWriteSpace(pRing); 1633 if (Avail >= 2) { 1634 _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1635 _WriteNoCheck(pRing, ac, 2u); 1636 } else { 1637 r = -1; 1638 } 1639 } 1640 SEGGER_RTT_UNLOCK(); 1641 } else { 1642 r = -1; 1643 } 1644 return r; 1645 } 1646 1647 /********************************************************************* 1648 * 1649 * SEGGER_RTT_TerminalOut 1650 * 1651 * Function description 1652 * Writes a string to the given terminal 1653 * without changing the terminal for channel 0. 1654 * 1655 * Parameters 1656 * TerminalId Index of the terminal. 1657 * s String to be printed on the terminal. 1658 * 1659 * Return value 1660 * >= 0 - Number of bytes written. 1661 * < 0 - Error. 1662 * 1663 */ 1664 int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { 1665 int Status; 1666 unsigned FragLen; 1667 unsigned Avail; 1668 SEGGER_RTT_BUFFER_UP* pRing; 1669 // 1670 INIT(); 1671 // 1672 // Validate terminal ID. 1673 // 1674 if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1675 // 1676 // Get "to-host" ring buffer. 1677 // 1678 pRing = &_SEGGER_RTT.aUp[0]; 1679 // 1680 // Need to be able to change terminal, write data, change back. 1681 // Compute the fixed and variable sizes. 1682 // 1683 FragLen = STRLEN(s); 1684 // 1685 // How we output depends upon the mode... 1686 // 1687 SEGGER_RTT_LOCK(); 1688 Avail = _GetAvailWriteSpace(pRing); 1689 switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1690 case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1691 // 1692 // If we are in skip mode and there is no space for the whole 1693 // of this output, don't bother switching terminals at all. 1694 // 1695 if (Avail < (FragLen + 4u)) { 1696 Status = 0; 1697 } else { 1698 _PostTerminalSwitch(pRing, TerminalId); 1699 Status = (int)_WriteBlocking(pRing, s, FragLen); 1700 _PostTerminalSwitch(pRing, _ActiveTerminal); 1701 } 1702 break; 1703 case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1704 // 1705 // If we are in trim mode and there is not enough space for everything, 1706 // trim the output but always include the terminal switch. If no room 1707 // for terminal switch, skip that totally. 1708 // 1709 if (Avail < 4u) { 1710 Status = -1; 1711 } else { 1712 _PostTerminalSwitch(pRing, TerminalId); 1713 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 1714 _PostTerminalSwitch(pRing, _ActiveTerminal); 1715 } 1716 break; 1717 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1718 // 1719 // If we are in blocking mode, output everything. 1720 // 1721 _PostTerminalSwitch(pRing, TerminalId); 1722 Status = (int)_WriteBlocking(pRing, s, FragLen); 1723 _PostTerminalSwitch(pRing, _ActiveTerminal); 1724 break; 1725 default: 1726 Status = -1; 1727 break; 1728 } 1729 // 1730 // Finish up. 1731 // 1732 SEGGER_RTT_UNLOCK(); 1733 } else { 1734 Status = -1; 1735 } 1736 return Status; 1737 } 1738 1739 1740 /*************************** End of file ****************************/ 1741