|
@@ -1,35 +1,34 @@
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
|
-* SEGGER MICROCONTROLLER GmbH & Co. KG *
|
|
|
|
|
-* Solutions for real time microcontroller applications *
|
|
|
|
|
|
|
+* SEGGER Microcontroller GmbH *
|
|
|
|
|
+* The Embedded Experts *
|
|
|
**********************************************************************
|
|
**********************************************************************
|
|
|
* *
|
|
* *
|
|
|
-* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG *
|
|
|
|
|
|
|
+* (c) 2014 - 2018 SEGGER Microcontroller GmbH *
|
|
|
* *
|
|
* *
|
|
|
-* www.segger.com Support: support@segger.com *
|
|
|
|
|
|
|
+* www.segger.com Support: support@segger.com *
|
|
|
* *
|
|
* *
|
|
|
**********************************************************************
|
|
**********************************************************************
|
|
|
* *
|
|
* *
|
|
|
-* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
|
|
|
|
|
+* All rights reserved. *
|
|
|
* *
|
|
* *
|
|
|
-**********************************************************************
|
|
|
|
|
|
|
+* Redistribution and use in source and binary forms, with or *
|
|
|
|
|
+* without modification, are permitted provided that the following *
|
|
|
|
|
+* conditions are met: *
|
|
|
* *
|
|
* *
|
|
|
-* All rights reserved. *
|
|
|
|
|
|
|
+* - Redistributions of source code must retain the above copyright *
|
|
|
|
|
+* notice, this list of conditions and the following disclaimer. *
|
|
|
* *
|
|
* *
|
|
|
-* * This software may in its unmodified form be freely redistributed *
|
|
|
|
|
-* in source form. *
|
|
|
|
|
-* * The source code may be modified, provided the source code *
|
|
|
|
|
-* retains the above copyright notice, this list of conditions and *
|
|
|
|
|
-* the following disclaimer. *
|
|
|
|
|
-* * Modified versions of this software in source or linkable form *
|
|
|
|
|
-* may not be distributed without prior consent of SEGGER. *
|
|
|
|
|
-* * This software may only be used for communication with SEGGER *
|
|
|
|
|
-* J-Link debug probes. *
|
|
|
|
|
|
|
+* - Neither the name of SEGGER Microcontroller GmbH *
|
|
|
|
|
+* nor the names of its contributors may be used to endorse or *
|
|
|
|
|
+* promote products derived from this software without specific *
|
|
|
|
|
+* prior written permission. *
|
|
|
* *
|
|
* *
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
|
-* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
|
|
|
|
|
+* DISCLAIMED. *
|
|
|
|
|
+* IN NO EVENT SHALL SEGGER Microcontroller GmbH BE LIABLE FOR *
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
@@ -40,15 +39,12 @@
|
|
|
* DAMAGE. *
|
|
* DAMAGE. *
|
|
|
* *
|
|
* *
|
|
|
**********************************************************************
|
|
**********************************************************************
|
|
|
-* *
|
|
|
|
|
-* RTT version: 5.12e *
|
|
|
|
|
-* *
|
|
|
|
|
-**********************************************************************
|
|
|
|
|
---------------------------END-OF-HEADER------------------------------
|
|
---------------------------END-OF-HEADER------------------------------
|
|
|
File : SEGGER_RTT.c
|
|
File : SEGGER_RTT.c
|
|
|
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
|
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
|
|
allows real-time communication on targets which support
|
|
allows real-time communication on targets which support
|
|
|
debugger memory accesses while the CPU is running.
|
|
debugger memory accesses while the CPU is running.
|
|
|
|
|
+Revision: $Rev: 12804 $
|
|
|
|
|
|
|
|
Additional information:
|
|
Additional information:
|
|
|
Type "int" is assumed to be 32-bits in size
|
|
Type "int" is assumed to be 32-bits in size
|
|
@@ -99,11 +95,19 @@ Additional information:
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SEGGER_RTT_BUFFER_SECTION
|
|
#ifndef SEGGER_RTT_BUFFER_SECTION
|
|
|
- #if defined SEGGER_RTT_SECTION
|
|
|
|
|
|
|
+ #if defined(SEGGER_RTT_SECTION)
|
|
|
#define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
|
|
#define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
|
|
|
#endif
|
|
#endif
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifndef SEGGER_RTT_ALIGNMENT
|
|
|
|
|
+ #define SEGGER_RTT_ALIGNMENT 0
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifndef SEGGER_RTT_BUFFER_ALIGNMENT
|
|
|
|
|
+ #define SEGGER_RTT_BUFFER_ALIGNMENT 0
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
#ifndef SEGGER_RTT_MODE_DEFAULT
|
|
#ifndef SEGGER_RTT_MODE_DEFAULT
|
|
|
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
|
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
|
|
#endif
|
|
#endif
|
|
@@ -120,8 +124,16 @@ Additional information:
|
|
|
#define STRLEN(a) strlen((a))
|
|
#define STRLEN(a) strlen((a))
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-#ifndef MEMCPY
|
|
|
|
|
- #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
|
|
|
|
|
|
|
+#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifndef SEGGER_RTT_MEMCPY
|
|
|
|
|
+ #ifdef MEMCPY
|
|
|
|
|
+ #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes))
|
|
|
|
|
+ #else
|
|
|
|
|
+ #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
|
|
|
|
|
+ #endif
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MIN
|
|
#ifndef MIN
|
|
@@ -140,58 +152,94 @@ Additional information:
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
|
*
|
|
*
|
|
|
-* Static const data
|
|
|
|
|
|
|
+* Defines, fixed
|
|
|
*
|
|
*
|
|
|
**********************************************************************
|
|
**********************************************************************
|
|
|
*/
|
|
*/
|
|
|
|
|
+#if (defined __ICCARM__) || (defined __ICCRX__)
|
|
|
|
|
+ #define RTT_PRAGMA(P) _Pragma(#P)
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
-static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
|
|
|
-
|
|
|
|
|
-/*********************************************************************
|
|
|
|
|
-*
|
|
|
|
|
-* Static data
|
|
|
|
|
-*
|
|
|
|
|
-**********************************************************************
|
|
|
|
|
-*/
|
|
|
|
|
-//
|
|
|
|
|
-// RTT Control Block and allocate buffers for channel 0
|
|
|
|
|
-//
|
|
|
|
|
-#ifdef SEGGER_RTT_SECTION
|
|
|
|
|
|
|
+#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
|
|
|
#if (defined __GNUC__)
|
|
#if (defined __GNUC__)
|
|
|
- __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT;
|
|
|
|
|
|
|
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
|
|
|
#elif (defined __ICCARM__) || (defined __ICCRX__)
|
|
#elif (defined __ICCARM__) || (defined __ICCRX__)
|
|
|
- #pragma location=SEGGER_RTT_SECTION
|
|
|
|
|
- SEGGER_RTT_CB _SEGGER_RTT;
|
|
|
|
|
- #elif (defined __CC_ARM__)
|
|
|
|
|
- __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT;
|
|
|
|
|
|
|
+ #define PRAGMA(A) _Pragma(#A)
|
|
|
|
|
+#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
|
|
|
|
|
+ Var
|
|
|
|
|
+ #elif (defined __CC_ARM)
|
|
|
|
|
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
|
|
|
#else
|
|
#else
|
|
|
- SEGGER_RTT_CB _SEGGER_RTT;
|
|
|
|
|
|
|
+ #error "Alignment not supported for this compiler."
|
|
|
#endif
|
|
#endif
|
|
|
#else
|
|
#else
|
|
|
- SEGGER_RTT_CB _SEGGER_RTT;
|
|
|
|
|
|
|
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-#ifdef SEGGER_RTT_BUFFER_SECTION
|
|
|
|
|
|
|
+#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
|
|
|
#if (defined __GNUC__)
|
|
#if (defined __GNUC__)
|
|
|
- __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP];
|
|
|
|
|
- __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN];
|
|
|
|
|
|
|
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
|
|
|
#elif (defined __ICCARM__) || (defined __ICCRX__)
|
|
#elif (defined __ICCARM__) || (defined __ICCRX__)
|
|
|
- #pragma location=SEGGER_RTT_BUFFER_SECTION
|
|
|
|
|
- static char _acUpBuffer [BUFFER_SIZE_UP];
|
|
|
|
|
- #pragma location=SEGGER_RTT_BUFFER_SECTION
|
|
|
|
|
- static char _acDownBuffer[BUFFER_SIZE_DOWN];
|
|
|
|
|
- #elif (defined __CC_ARM__)
|
|
|
|
|
- __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP];
|
|
|
|
|
- __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN];
|
|
|
|
|
|
|
+#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
|
|
|
|
|
+ Var
|
|
|
|
|
+ #elif (defined __CC_ARM)
|
|
|
|
|
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var
|
|
|
#else
|
|
#else
|
|
|
- static char _acUpBuffer [BUFFER_SIZE_UP];
|
|
|
|
|
- static char _acDownBuffer[BUFFER_SIZE_DOWN];
|
|
|
|
|
|
|
+ #error "Section placement not supported for this compiler."
|
|
|
#endif
|
|
#endif
|
|
|
#else
|
|
#else
|
|
|
- static char _acUpBuffer [BUFFER_SIZE_UP];
|
|
|
|
|
- static char _acDownBuffer[BUFFER_SIZE_DOWN];
|
|
|
|
|
|
|
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#if SEGGER_RTT_ALIGNMENT
|
|
|
|
|
+ #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
|
|
|
|
|
+#else
|
|
|
|
|
+ #define SEGGER_RTT_CB_ALIGN(Var) Var
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if SEGGER_RTT_BUFFER_ALIGNMENT
|
|
|
|
|
+ #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
|
|
|
|
|
+#else
|
|
|
|
|
+ #define SEGGER_RTT_BUFFER_ALIGN(Var) Var
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#if defined(SEGGER_RTT_SECTION)
|
|
|
|
|
+ #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
|
|
|
|
|
+#else
|
|
|
|
|
+ #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#if defined(SEGGER_RTT_BUFFER_SECTION)
|
|
|
|
|
+ #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
|
|
|
|
|
+#else
|
|
|
|
|
+ #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* Static const data
|
|
|
|
|
+*
|
|
|
|
|
+**********************************************************************
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
|
|
|
+
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* Static data
|
|
|
|
|
+*
|
|
|
|
|
+**********************************************************************
|
|
|
|
|
+*/
|
|
|
|
|
+//
|
|
|
|
|
+// RTT Control Block and allocate buffers for channel 0
|
|
|
|
|
+//
|
|
|
|
|
+SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
|
|
|
|
|
+
|
|
|
|
|
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP]));
|
|
|
|
|
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
|
|
|
|
|
+
|
|
|
static char _ActiveTerminal;
|
|
static char _ActiveTerminal;
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
@@ -273,6 +321,9 @@ static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer,
|
|
|
unsigned NumBytesWritten;
|
|
unsigned NumBytesWritten;
|
|
|
unsigned RdOff;
|
|
unsigned RdOff;
|
|
|
unsigned WrOff;
|
|
unsigned WrOff;
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ char* pDst;
|
|
|
|
|
+#endif
|
|
|
//
|
|
//
|
|
|
// Write data to buffer and handle wrap-around if necessary
|
|
// Write data to buffer and handle wrap-around if necessary
|
|
|
//
|
|
//
|
|
@@ -287,11 +338,21 @@ static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer,
|
|
|
}
|
|
}
|
|
|
NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around
|
|
NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around
|
|
|
NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
|
|
NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
|
|
|
- memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
|
|
+ NumBytesWritten += NumBytesToWrite;
|
|
|
|
|
+ NumBytes -= NumBytesToWrite;
|
|
|
|
|
+ WrOff += NumBytesToWrite;
|
|
|
|
|
+ while (NumBytesToWrite--) {
|
|
|
|
|
+ *pDst++ = *pBuffer++;
|
|
|
|
|
+ };
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
|
|
|
NumBytesWritten += NumBytesToWrite;
|
|
NumBytesWritten += NumBytesToWrite;
|
|
|
pBuffer += NumBytesToWrite;
|
|
pBuffer += NumBytesToWrite;
|
|
|
NumBytes -= NumBytesToWrite;
|
|
NumBytes -= NumBytesToWrite;
|
|
|
WrOff += NumBytesToWrite;
|
|
WrOff += NumBytesToWrite;
|
|
|
|
|
+#endif
|
|
|
if (WrOff == pRing->SizeOfBuffer) {
|
|
if (WrOff == pRing->SizeOfBuffer) {
|
|
|
WrOff = 0u;
|
|
WrOff = 0u;
|
|
|
}
|
|
}
|
|
@@ -323,6 +384,9 @@ static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsign
|
|
|
unsigned NumBytesAtOnce;
|
|
unsigned NumBytesAtOnce;
|
|
|
unsigned WrOff;
|
|
unsigned WrOff;
|
|
|
unsigned Rem;
|
|
unsigned Rem;
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ char* pDst;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
WrOff = pRing->WrOff;
|
|
WrOff = pRing->WrOff;
|
|
|
Rem = pRing->SizeOfBuffer - WrOff;
|
|
Rem = pRing->SizeOfBuffer - WrOff;
|
|
@@ -330,17 +394,40 @@ static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsign
|
|
|
//
|
|
//
|
|
|
// All data fits before wrap around
|
|
// All data fits before wrap around
|
|
|
//
|
|
//
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
|
|
+ WrOff += NumBytes;
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
|
|
|
+#endif
|
|
|
} else {
|
|
} else {
|
|
|
//
|
|
//
|
|
|
// We reach the end of the buffer, so need to wrap around
|
|
// We reach the end of the buffer, so need to wrap around
|
|
|
//
|
|
//
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
NumBytesAtOnce = Rem;
|
|
NumBytesAtOnce = Rem;
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
|
|
|
|
|
|
|
+ while (NumBytesAtOnce--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pDst = pRing->pBuffer;
|
|
|
NumBytesAtOnce = NumBytes - Rem;
|
|
NumBytesAtOnce = NumBytes - Rem;
|
|
|
- memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
|
|
|
|
|
|
|
+ while (NumBytesAtOnce--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = NumBytes - Rem;
|
|
|
|
|
+#else
|
|
|
|
|
+ NumBytesAtOnce = Rem;
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
|
|
|
|
|
+ NumBytesAtOnce = NumBytes - Rem;
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
|
|
|
pRing->WrOff = NumBytesAtOnce;
|
|
pRing->WrOff = NumBytesAtOnce;
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -358,11 +445,11 @@ static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsign
|
|
|
* TerminalId Terminal ID to switch to.
|
|
* TerminalId Terminal ID to switch to.
|
|
|
*/
|
|
*/
|
|
|
static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
|
|
static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
|
|
|
- char ac[2];
|
|
|
|
|
|
|
+ unsigned char ac[2];
|
|
|
|
|
|
|
|
ac[0] = 0xFFu;
|
|
ac[0] = 0xFFu;
|
|
|
ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
|
|
ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
|
|
|
- _WriteBlocking(pRing, ac, 2u);
|
|
|
|
|
|
|
+ _WriteBlocking(pRing, (const char*)ac, 2u);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
@@ -427,6 +514,9 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe
|
|
|
unsigned WrOff;
|
|
unsigned WrOff;
|
|
|
unsigned char* pBuffer;
|
|
unsigned char* pBuffer;
|
|
|
SEGGER_RTT_BUFFER_DOWN* pRing;
|
|
SEGGER_RTT_BUFFER_DOWN* pRing;
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ const char* pSrc;
|
|
|
|
|
+#endif
|
|
|
//
|
|
//
|
|
|
INIT();
|
|
INIT();
|
|
|
pRing = &_SEGGER_RTT.aDown[BufferIndex];
|
|
pRing = &_SEGGER_RTT.aDown[BufferIndex];
|
|
@@ -440,11 +530,21 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe
|
|
|
if (RdOff > WrOff) {
|
|
if (RdOff > WrOff) {
|
|
|
NumBytesRem = pRing->SizeOfBuffer - RdOff;
|
|
NumBytesRem = pRing->SizeOfBuffer - RdOff;
|
|
|
NumBytesRem = MIN(NumBytesRem, BufferSize);
|
|
NumBytesRem = MIN(NumBytesRem, BufferSize);
|
|
|
- memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pSrc = pRing->pBuffer + RdOff;
|
|
|
|
|
+ NumBytesRead += NumBytesRem;
|
|
|
|
|
+ BufferSize -= NumBytesRem;
|
|
|
|
|
+ RdOff += NumBytesRem;
|
|
|
|
|
+ while (NumBytesRem--) {
|
|
|
|
|
+ *pBuffer++ = *pSrc++;
|
|
|
|
|
+ };
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
|
|
|
NumBytesRead += NumBytesRem;
|
|
NumBytesRead += NumBytesRem;
|
|
|
pBuffer += NumBytesRem;
|
|
pBuffer += NumBytesRem;
|
|
|
BufferSize -= NumBytesRem;
|
|
BufferSize -= NumBytesRem;
|
|
|
RdOff += NumBytesRem;
|
|
RdOff += NumBytesRem;
|
|
|
|
|
+#endif
|
|
|
//
|
|
//
|
|
|
// Handle wrap-around of buffer
|
|
// Handle wrap-around of buffer
|
|
|
//
|
|
//
|
|
@@ -458,11 +558,21 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe
|
|
|
NumBytesRem = WrOff - RdOff;
|
|
NumBytesRem = WrOff - RdOff;
|
|
|
NumBytesRem = MIN(NumBytesRem, BufferSize);
|
|
NumBytesRem = MIN(NumBytesRem, BufferSize);
|
|
|
if (NumBytesRem > 0u) {
|
|
if (NumBytesRem > 0u) {
|
|
|
- memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pSrc = pRing->pBuffer + RdOff;
|
|
|
|
|
+ NumBytesRead += NumBytesRem;
|
|
|
|
|
+ BufferSize -= NumBytesRem;
|
|
|
|
|
+ RdOff += NumBytesRem;
|
|
|
|
|
+ while (NumBytesRem--) {
|
|
|
|
|
+ *pBuffer++ = *pSrc++;
|
|
|
|
|
+ };
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
|
|
|
NumBytesRead += NumBytesRem;
|
|
NumBytesRead += NumBytesRem;
|
|
|
pBuffer += NumBytesRem;
|
|
pBuffer += NumBytesRem;
|
|
|
BufferSize -= NumBytesRem;
|
|
BufferSize -= NumBytesRem;
|
|
|
RdOff += NumBytesRem;
|
|
RdOff += NumBytesRem;
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
if (NumBytesRead) {
|
|
if (NumBytesRead) {
|
|
|
pRing->RdOff = RdOff;
|
|
pRing->RdOff = RdOff;
|
|
@@ -530,6 +640,9 @@ void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuff
|
|
|
const char* pData;
|
|
const char* pData;
|
|
|
SEGGER_RTT_BUFFER_UP* pRing;
|
|
SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
unsigned Avail;
|
|
unsigned Avail;
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ char* pDst;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
pData = (const char *)pBuffer;
|
|
pData = (const char *)pBuffer;
|
|
|
//
|
|
//
|
|
@@ -561,26 +674,35 @@ void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuff
|
|
|
//
|
|
//
|
|
|
// Last round
|
|
// Last round
|
|
|
//
|
|
//
|
|
|
-#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
|
|
|
|
|
- char* pDst;
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
pDst = pRing->pBuffer + pRing->WrOff;
|
|
pDst = pRing->pBuffer + pRing->WrOff;
|
|
|
- pRing->WrOff += NumBytes;
|
|
|
|
|
- do {
|
|
|
|
|
|
|
+ Avail = NumBytes;
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
*pDst++ = *pData++;
|
|
*pDst++ = *pData++;
|
|
|
- } while (--NumBytes);
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff += Avail;
|
|
|
#else
|
|
#else
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes);
|
|
|
pRing->WrOff += NumBytes;
|
|
pRing->WrOff += NumBytes;
|
|
|
#endif
|
|
#endif
|
|
|
- break; //Alternatively: NumBytes = 0;
|
|
|
|
|
|
|
+ break;
|
|
|
} else {
|
|
} else {
|
|
|
//
|
|
//
|
|
|
// Wrap-around necessary, write until wrap-around and reset WrOff
|
|
// Wrap-around necessary, write until wrap-around and reset WrOff
|
|
|
//
|
|
//
|
|
|
- memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + pRing->WrOff;
|
|
|
|
|
+ NumBytes -= Avail;
|
|
|
|
|
+ while (Avail--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = 0;
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail);
|
|
|
pData += Avail;
|
|
pData += Avail;
|
|
|
pRing->WrOff = 0;
|
|
pRing->WrOff = 0;
|
|
|
NumBytes -= Avail;
|
|
NumBytes -= Avail;
|
|
|
|
|
+#endif
|
|
|
Avail = (pRing->SizeOfBuffer - 1);
|
|
Avail = (pRing->SizeOfBuffer - 1);
|
|
|
}
|
|
}
|
|
|
} while (NumBytes);
|
|
} while (NumBytes);
|
|
@@ -617,6 +739,9 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
|
|
|
unsigned RdOff;
|
|
unsigned RdOff;
|
|
|
unsigned WrOff;
|
|
unsigned WrOff;
|
|
|
unsigned Rem;
|
|
unsigned Rem;
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ char* pDst;
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
pData = (const char *)pBuffer;
|
|
pData = (const char *)pBuffer;
|
|
|
//
|
|
//
|
|
@@ -644,16 +769,15 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
|
|
|
//
|
|
//
|
|
|
Avail = pRing->SizeOfBuffer - 1u - WrOff ;
|
|
Avail = pRing->SizeOfBuffer - 1u - WrOff ;
|
|
|
if (Avail >= NumBytes) {
|
|
if (Avail >= NumBytes) {
|
|
|
-#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
|
|
|
|
|
- char* pDst;
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
pDst = pRing->pBuffer + WrOff;
|
|
pDst = pRing->pBuffer + WrOff;
|
|
|
WrOff += NumBytes;
|
|
WrOff += NumBytes;
|
|
|
- do {
|
|
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
*pDst++ = *pData++;
|
|
*pDst++ = *pData++;
|
|
|
- } while (--NumBytes);
|
|
|
|
|
- pRing->WrOff = WrOff + NumBytes;
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
#else
|
|
#else
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
|
#endif
|
|
#endif
|
|
|
return 1;
|
|
return 1;
|
|
@@ -671,23 +795,55 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
|
|
|
//
|
|
//
|
|
|
Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
|
|
Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
|
|
|
if (Rem > NumBytes) {
|
|
if (Rem > NumBytes) {
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
|
|
+ WrOff += NumBytes;
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
|
|
|
+#endif
|
|
|
} else {
|
|
} else {
|
|
|
//
|
|
//
|
|
|
// We reach the end of the buffer, so need to wrap around
|
|
// We reach the end of the buffer, so need to wrap around
|
|
|
//
|
|
//
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, Rem);
|
|
|
|
|
- memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
|
|
+ NumBytes -= Rem;
|
|
|
|
|
+ WrOff = NumBytes;
|
|
|
|
|
+ do {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ } while (--Rem);
|
|
|
|
|
+ pDst = pRing->pBuffer;
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, Rem);
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytes - Rem);
|
|
|
pRing->WrOff = NumBytes - Rem;
|
|
pRing->WrOff = NumBytes - Rem;
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
Avail = RdOff - WrOff - 1u;
|
|
Avail = RdOff - WrOff - 1u;
|
|
|
if (Avail >= NumBytes) {
|
|
if (Avail >= NumBytes) {
|
|
|
- memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
|
|
|
|
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
|
|
|
+ pDst = pRing->pBuffer + WrOff;
|
|
|
|
|
+ WrOff += NumBytes;
|
|
|
|
|
+ while (NumBytes--) {
|
|
|
|
|
+ *pDst++ = *pData++;
|
|
|
|
|
+ };
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+#else
|
|
|
|
|
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
pRing->WrOff = WrOff + NumBytes;
|
|
|
|
|
+#endif
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -715,7 +871,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
|
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
*
|
|
*
|
|
|
* Notes
|
|
* Notes
|
|
|
-* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
|
|
|
|
|
|
|
+* (1) Data is stored according to buffer flags.
|
|
|
* (2) For performance reasons this function does not call Init()
|
|
* (2) For performance reasons this function does not call Init()
|
|
|
* and may only be called after RTT has been initialized.
|
|
* and may only be called after RTT has been initialized.
|
|
|
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
|
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
|
@@ -789,7 +945,7 @@ unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsig
|
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
*
|
|
*
|
|
|
* Notes
|
|
* Notes
|
|
|
-* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
|
|
|
|
|
|
|
+* (1) Data is stored according to buffer flags.
|
|
|
*/
|
|
*/
|
|
|
unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
|
|
unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
|
|
|
unsigned Status;
|
|
unsigned Status;
|
|
@@ -824,8 +980,7 @@ unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned Nu
|
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
*
|
|
*
|
|
|
* Notes
|
|
* Notes
|
|
|
-* (1) If there is not enough space in the "Up"-buffer, depending on configuration,
|
|
|
|
|
-* remaining characters may be dropped or RTT module waits until there is more space in the buffer.
|
|
|
|
|
|
|
+* (1) Data is stored according to buffer flags.
|
|
|
* (2) String passed to this function has to be \0 terminated
|
|
* (2) String passed to this function has to be \0 terminated
|
|
|
* (3) \0 termination character is *not* stored in RTT buffer
|
|
* (3) \0 termination character is *not* stored in RTT buffer
|
|
|
*/
|
|
*/
|
|
@@ -836,6 +991,178 @@ unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
|
|
|
return SEGGER_RTT_Write(BufferIndex, s, Len);
|
|
return SEGGER_RTT_Write(BufferIndex, s, Len);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_PutCharSkipNoLock
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Stores a single character/byte in SEGGER RTT buffer.
|
|
|
|
|
+* SEGGER_RTT_PutCharSkipNoLock does not lock the application and
|
|
|
|
|
+* skips the byte, if it does not fit into the buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Parameters
|
|
|
|
|
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
|
|
|
|
+* c Byte to be stored.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value
|
|
|
|
|
+* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Notes
|
|
|
|
|
+* (1) If there is not enough space in the "Up"-buffer, the character is dropped.
|
|
|
|
|
+* (2) For performance reasons this function does not call Init()
|
|
|
|
|
+* and may only be called after RTT has been initialized.
|
|
|
|
|
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
|
|
|
|
|
+ SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
|
|
+ unsigned WrOff;
|
|
|
|
|
+ unsigned Status;
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get "to-host" ring buffer.
|
|
|
|
|
+ //
|
|
|
|
|
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get write position and handle wrap-around if necessary
|
|
|
|
|
+ //
|
|
|
|
|
+ WrOff = pRing->WrOff + 1;
|
|
|
|
|
+ if (WrOff == pRing->SizeOfBuffer) {
|
|
|
|
|
+ WrOff = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Output byte if free space is available
|
|
|
|
|
+ //
|
|
|
|
|
+ if (WrOff != pRing->RdOff) {
|
|
|
|
|
+ pRing->pBuffer[pRing->WrOff] = c;
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+ Status = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Status = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ return Status;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_PutCharSkip
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Stores a single character/byte in SEGGER RTT buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Parameters
|
|
|
|
|
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
|
|
|
|
+* c Byte to be stored.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value
|
|
|
|
|
+* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Notes
|
|
|
|
|
+* (1) If there is not enough space in the "Up"-buffer, the character is dropped.
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
|
|
|
|
|
+ SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
|
|
+ unsigned WrOff;
|
|
|
|
|
+ unsigned Status;
|
|
|
|
|
+ //
|
|
|
|
|
+ // Prepare
|
|
|
|
|
+ //
|
|
|
|
|
+ INIT();
|
|
|
|
|
+ SEGGER_RTT_LOCK();
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get "to-host" ring buffer.
|
|
|
|
|
+ //
|
|
|
|
|
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get write position and handle wrap-around if necessary
|
|
|
|
|
+ //
|
|
|
|
|
+ WrOff = pRing->WrOff + 1;
|
|
|
|
|
+ if (WrOff == pRing->SizeOfBuffer) {
|
|
|
|
|
+ WrOff = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Output byte if free space is available
|
|
|
|
|
+ //
|
|
|
|
|
+ if (WrOff != pRing->RdOff) {
|
|
|
|
|
+ pRing->pBuffer[pRing->WrOff] = c;
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+ Status = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Status = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Finish up.
|
|
|
|
|
+ //
|
|
|
|
|
+ SEGGER_RTT_UNLOCK();
|
|
|
|
|
+ //
|
|
|
|
|
+ return Status;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ /*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_PutChar
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Stores a single character/byte in SEGGER RTT buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Parameters
|
|
|
|
|
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
|
|
|
|
+* c Byte to be stored.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value
|
|
|
|
|
+* Number of bytes which have been stored in the "Up"-buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Notes
|
|
|
|
|
+* (1) Data is stored according to buffer flags.
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
|
|
|
|
|
+ SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
|
|
+ unsigned WrOff;
|
|
|
|
|
+ unsigned Status;
|
|
|
|
|
+ //
|
|
|
|
|
+ // Prepare
|
|
|
|
|
+ //
|
|
|
|
|
+ INIT();
|
|
|
|
|
+ SEGGER_RTT_LOCK();
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get "to-host" ring buffer.
|
|
|
|
|
+ //
|
|
|
|
|
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
|
|
|
|
+ //
|
|
|
|
|
+ // Get write position and handle wrap-around if necessary
|
|
|
|
|
+ //
|
|
|
|
|
+ WrOff = pRing->WrOff + 1;
|
|
|
|
|
+ if (WrOff == pRing->SizeOfBuffer) {
|
|
|
|
|
+ WrOff = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Wait for free space if mode is set to blocking
|
|
|
|
|
+ //
|
|
|
|
|
+ if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
|
|
|
|
|
+ while (WrOff == pRing->RdOff) {
|
|
|
|
|
+ ;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Output byte if free space is available
|
|
|
|
|
+ //
|
|
|
|
|
+ if (WrOff != pRing->RdOff) {
|
|
|
|
|
+ pRing->pBuffer[pRing->WrOff] = c;
|
|
|
|
|
+ pRing->WrOff = WrOff;
|
|
|
|
|
+ Status = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Status = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //
|
|
|
|
|
+ // Finish up.
|
|
|
|
|
+ //
|
|
|
|
|
+ SEGGER_RTT_UNLOCK();
|
|
|
|
|
+ //
|
|
|
|
|
+ return Status;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
|
*
|
|
*
|
|
|
* SEGGER_RTT_GetKey
|
|
* SEGGER_RTT_GetKey
|
|
@@ -937,6 +1264,27 @@ unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
|
|
|
return v - pRing->RdOff;
|
|
return v - pRing->RdOff;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_HasDataUp
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Check if there is data remaining to be sent in the given buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value:
|
|
|
|
|
+* ==0: No data
|
|
|
|
|
+* !=0: Data in buffer
|
|
|
|
|
+*
|
|
|
|
|
+*/
|
|
|
|
|
+unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
|
|
|
|
|
+ SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
|
|
+ unsigned v;
|
|
|
|
|
+
|
|
|
|
|
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
|
|
|
|
+ v = pRing->RdOff;
|
|
|
|
|
+ return pRing->WrOff - v;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
|
*
|
|
*
|
|
|
* SEGGER_RTT_AllocDownBuffer
|
|
* SEGGER_RTT_AllocDownBuffer
|
|
@@ -970,7 +1318,7 @@ int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned Buffer
|
|
|
} while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
|
|
} while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
|
|
|
if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
|
|
if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
|
|
|
_SEGGER_RTT.aDown[BufferIndex].sName = sName;
|
|
_SEGGER_RTT.aDown[BufferIndex].sName = sName;
|
|
|
- _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer;
|
|
|
|
|
|
|
+ _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
|
|
_SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
|
|
_SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
|
|
_SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
|
|
@@ -1015,7 +1363,7 @@ int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSi
|
|
|
} while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
|
|
} while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
|
|
|
if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
|
|
if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
|
|
|
_SEGGER_RTT.aUp[BufferIndex].sName = sName;
|
|
_SEGGER_RTT.aUp[BufferIndex].sName = sName;
|
|
|
- _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer;
|
|
|
|
|
|
|
+ _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
|
|
_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
|
|
_SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
|
|
_SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
|
|
@@ -1046,6 +1394,11 @@ int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSi
|
|
|
* Return value
|
|
* Return value
|
|
|
* >= 0 - O.K.
|
|
* >= 0 - O.K.
|
|
|
* < 0 - Error
|
|
* < 0 - Error
|
|
|
|
|
+*
|
|
|
|
|
+* Additional information
|
|
|
|
|
+* Buffer 0 is configured on compile-time.
|
|
|
|
|
+* May only be called once per buffer.
|
|
|
|
|
+* Buffer name and flags can be reconfigured using the appropriate functions.
|
|
|
*/
|
|
*/
|
|
|
int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
|
int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
|
|
int r;
|
|
int r;
|
|
@@ -1055,7 +1408,7 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
|
|
|
SEGGER_RTT_LOCK();
|
|
SEGGER_RTT_LOCK();
|
|
|
if (BufferIndex > 0u) {
|
|
if (BufferIndex > 0u) {
|
|
|
_SEGGER_RTT.aUp[BufferIndex].sName = sName;
|
|
_SEGGER_RTT.aUp[BufferIndex].sName = sName;
|
|
|
- _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer;
|
|
|
|
|
|
|
+ _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
|
|
_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
|
|
_SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
|
|
|
_SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
|
|
_SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
|
|
@@ -1088,6 +1441,11 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
|
|
|
* Return value
|
|
* Return value
|
|
|
* >= 0 O.K.
|
|
* >= 0 O.K.
|
|
|
* < 0 Error
|
|
* < 0 Error
|
|
|
|
|
+*
|
|
|
|
|
+* Additional information
|
|
|
|
|
+* Buffer 0 is configured on compile-time.
|
|
|
|
|
+* May only be called once per buffer.
|
|
|
|
|
+* Buffer name and flags can be reconfigured using the appropriate functions.
|
|
|
*/
|
|
*/
|
|
|
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
|
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
|
|
int r;
|
|
int r;
|
|
@@ -1097,7 +1455,7 @@ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* p
|
|
|
SEGGER_RTT_LOCK();
|
|
SEGGER_RTT_LOCK();
|
|
|
if (BufferIndex > 0u) {
|
|
if (BufferIndex > 0u) {
|
|
|
_SEGGER_RTT.aDown[BufferIndex].sName = sName;
|
|
_SEGGER_RTT.aDown[BufferIndex].sName = sName;
|
|
|
- _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer;
|
|
|
|
|
|
|
+ _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
|
|
_SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
|
|
_SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
|
|
|
_SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
|
|
_SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
|
|
@@ -1173,6 +1531,68 @@ int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
|
|
|
return r;
|
|
return r;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_SetFlagsUpBuffer
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Run-time configuration of specific up-buffer flags (T->H).
|
|
|
|
|
+* Buffer to be configured is specified by index.
|
|
|
|
|
+*
|
|
|
|
|
+* Parameters
|
|
|
|
|
+* BufferIndex Index of the buffer.
|
|
|
|
|
+* Flags Flags to set for the buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value
|
|
|
|
|
+* >= 0 O.K.
|
|
|
|
|
+* < 0 Error
|
|
|
|
|
+*/
|
|
|
|
|
+int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
|
|
|
|
|
+ int r;
|
|
|
|
|
+
|
|
|
|
|
+ INIT();
|
|
|
|
|
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
|
|
|
|
|
+ SEGGER_RTT_LOCK();
|
|
|
|
|
+ _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
|
|
|
|
|
+ SEGGER_RTT_UNLOCK();
|
|
|
|
|
+ r = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ r = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*********************************************************************
|
|
|
|
|
+*
|
|
|
|
|
+* SEGGER_RTT_SetFlagsDownBuffer
|
|
|
|
|
+*
|
|
|
|
|
+* Function description
|
|
|
|
|
+* Run-time configuration of specific Down-buffer flags (T->H).
|
|
|
|
|
+* Buffer to be configured is specified by index.
|
|
|
|
|
+*
|
|
|
|
|
+* Parameters
|
|
|
|
|
+* BufferIndex Index of the buffer to renamed.
|
|
|
|
|
+* Flags Flags to set for the buffer.
|
|
|
|
|
+*
|
|
|
|
|
+* Return value
|
|
|
|
|
+* >= 0 O.K.
|
|
|
|
|
+* < 0 Error
|
|
|
|
|
+*/
|
|
|
|
|
+int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
|
|
|
|
|
+ int r;
|
|
|
|
|
+
|
|
|
|
|
+ INIT();
|
|
|
|
|
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
|
|
|
|
|
+ SEGGER_RTT_LOCK();
|
|
|
|
|
+ _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
|
|
|
|
|
+ SEGGER_RTT_UNLOCK();
|
|
|
|
|
+ r = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ r = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
|
*
|
|
*
|
|
|
* SEGGER_RTT_Init
|
|
* SEGGER_RTT_Init
|
|
@@ -1201,7 +1621,7 @@ void SEGGER_RTT_Init (void) {
|
|
|
* < 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)
|
|
* < 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)
|
|
|
*/
|
|
*/
|
|
|
int SEGGER_RTT_SetTerminal (char TerminalId) {
|
|
int SEGGER_RTT_SetTerminal (char TerminalId) {
|
|
|
- char ac[2];
|
|
|
|
|
|
|
+ unsigned char ac[2];
|
|
|
SEGGER_RTT_BUFFER_UP* pRing;
|
|
SEGGER_RTT_BUFFER_UP* pRing;
|
|
|
unsigned Avail;
|
|
unsigned Avail;
|
|
|
int r;
|
|
int r;
|
|
@@ -1209,19 +1629,19 @@ int SEGGER_RTT_SetTerminal (char TerminalId) {
|
|
|
INIT();
|
|
INIT();
|
|
|
//
|
|
//
|
|
|
r = 0;
|
|
r = 0;
|
|
|
- ac[0] = 0xFFU;
|
|
|
|
|
|
|
+ ac[0] = 0xFFu;
|
|
|
if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
|
|
if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
|
|
|
ac[1] = _aTerminalId[(unsigned char)TerminalId];
|
|
ac[1] = _aTerminalId[(unsigned char)TerminalId];
|
|
|
pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
|
|
pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
|
|
|
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
|
|
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
|
|
|
if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
|
|
if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
|
|
|
_ActiveTerminal = TerminalId;
|
|
_ActiveTerminal = TerminalId;
|
|
|
- _WriteBlocking(pRing, ac, 2u);
|
|
|
|
|
|
|
+ _WriteBlocking(pRing, (const char*)ac, 2u);
|
|
|
} else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
|
|
} else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
|
|
|
Avail = _GetAvailWriteSpace(pRing);
|
|
Avail = _GetAvailWriteSpace(pRing);
|
|
|
if (Avail >= 2) {
|
|
if (Avail >= 2) {
|
|
|
_ActiveTerminal = TerminalId; // Only change active terminal in case of success
|
|
_ActiveTerminal = TerminalId; // Only change active terminal in case of success
|
|
|
- _WriteNoCheck(pRing, ac, 2u);
|
|
|
|
|
|
|
+ _WriteNoCheck(pRing, (const char*)ac, 2u);
|
|
|
} else {
|
|
} else {
|
|
|
r = -1;
|
|
r = -1;
|
|
|
}
|
|
}
|
|
@@ -1269,7 +1689,7 @@ int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
|
|
|
// Need to be able to change terminal, write data, change back.
|
|
// Need to be able to change terminal, write data, change back.
|
|
|
// Compute the fixed and variable sizes.
|
|
// Compute the fixed and variable sizes.
|
|
|
//
|
|
//
|
|
|
- FragLen = strlen(s);
|
|
|
|
|
|
|
+ FragLen = STRLEN(s);
|
|
|
//
|
|
//
|
|
|
// How we output depends upon the mode...
|
|
// How we output depends upon the mode...
|
|
|
//
|
|
//
|