82 #include "SEGGER_RTT.h" 93 #ifndef BUFFER_SIZE_UP 94 #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 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) 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 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 109 #ifndef SEGGER_RTT_BUFFER_SECTION 110 #if defined(SEGGER_RTT_SECTION) 111 #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION 115 #ifndef SEGGER_RTT_ALIGNMENT 116 #define SEGGER_RTT_ALIGNMENT 0 119 #ifndef SEGGER_RTT_BUFFER_ALIGNMENT 120 #define SEGGER_RTT_BUFFER_ALIGNMENT 0 123 #ifndef SEGGER_RTT_MODE_DEFAULT 124 #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 127 #ifndef SEGGER_RTT_LOCK 128 #define SEGGER_RTT_LOCK() 131 #ifndef SEGGER_RTT_UNLOCK 132 #define SEGGER_RTT_UNLOCK() 136 #define STRLEN(a) strlen((a)) 140 #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 144 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 148 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 163 #if (defined __ICCARM__) || (defined __ICCRX__) 164 #define RTT_PRAGMA(P) _Pragma(#P) 167 #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 168 #if (defined __GNUC__) 169 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 170 #elif (defined __ICCARM__) || (defined __ICCRX__) 171 #define PRAGMA(A) _Pragma(#A) 172 #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 174 #elif (defined __CC_ARM__) 175 #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 177 #error "Alignment not supported for this compiler." 180 #define SEGGER_RTT_ALIGN(Var, Alignment) Var 183 #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 184 #if (defined __GNUC__) 185 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 186 #elif (defined __ICCARM__) || (defined __ICCRX__) 187 #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 189 #elif (defined __CC_ARM__) 190 #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 192 #error "Section placement not supported for this compiler." 195 #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 199 #if SEGGER_RTT_ALIGNMENT 200 #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 202 #define SEGGER_RTT_CB_ALIGN(Var) Var 205 #if SEGGER_RTT_BUFFER_ALIGNMENT 206 #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 208 #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 212 #if defined(SEGGER_RTT_SECTION) 213 #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 215 #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 218 #if defined(SEGGER_RTT_BUFFER_SECTION) 219 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 221 #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 231 static unsigned char _aTerminalId[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
242 SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
244 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(
static char _acUpBuffer [BUFFER_SIZE_UP]));
245 SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(
static char _acDownBuffer[BUFFER_SIZE_DOWN]));
247 static char _ActiveTerminal;
265 #define INIT() do { \ 266 if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ 268 static void _DoInit(
void) {
274 p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
275 p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
279 p->aUp[0].sName =
"Terminal";
280 p->aUp[0].pBuffer = _acUpBuffer;
281 p->aUp[0].SizeOfBuffer =
sizeof(_acUpBuffer);
282 p->aUp[0].RdOff = 0u;
283 p->aUp[0].WrOff = 0u;
284 p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
288 p->aDown[0].sName =
"Terminal";
289 p->aDown[0].pBuffer = _acDownBuffer;
290 p->aDown[0].SizeOfBuffer =
sizeof(_acDownBuffer);
291 p->aDown[0].RdOff = 0u;
292 p->aDown[0].WrOff = 0u;
293 p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
299 strcpy(&p->acID[7],
"RTT");
300 strcpy(&p->acID[0],
"SEGGER");
323 static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing,
const char* pBuffer,
unsigned NumBytes) {
324 unsigned NumBytesToWrite;
325 unsigned NumBytesWritten;
331 NumBytesWritten = 0u;
332 WrOff = pRing->WrOff;
334 RdOff = pRing->RdOff;
336 NumBytesToWrite = RdOff - WrOff - 1u;
338 NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
340 NumBytesToWrite =
MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));
341 NumBytesToWrite =
MIN(NumBytesToWrite, NumBytes);
342 memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
343 NumBytesWritten += NumBytesToWrite;
344 pBuffer += NumBytesToWrite;
345 NumBytes -= NumBytesToWrite;
346 WrOff += NumBytesToWrite;
347 if (WrOff == pRing->SizeOfBuffer) {
350 pRing->WrOff = WrOff;
353 return NumBytesWritten;
374 static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing,
const char* pData,
unsigned NumBytes) {
375 unsigned NumBytesAtOnce;
379 WrOff = pRing->WrOff;
380 Rem = pRing->SizeOfBuffer - WrOff;
381 if (Rem > NumBytes) {
385 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
386 pRing->WrOff = WrOff + NumBytes;
391 NumBytesAtOnce = Rem;
392 memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
393 NumBytesAtOnce = NumBytes - Rem;
394 memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
395 pRing->WrOff = NumBytesAtOnce;
412 static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing,
unsigned char TerminalId) {
416 ac[1] = _aTerminalId[TerminalId];
417 _WriteBlocking(pRing, ac, 2u);
434 static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
442 RdOff = pRing->RdOff;
443 WrOff = pRing->WrOff;
444 if (RdOff <= WrOff) {
445 r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
447 r = RdOff - WrOff - 1u;
475 unsigned SEGGER_RTT_ReadNoLock(
unsigned BufferIndex,
void* pData,
unsigned BufferSize) {
476 unsigned NumBytesRem;
477 unsigned NumBytesRead;
480 unsigned char* pBuffer;
481 SEGGER_RTT_BUFFER_DOWN* pRing;
484 pRing = &_SEGGER_RTT.aDown[BufferIndex];
485 pBuffer = (
unsigned char*)pData;
486 RdOff = pRing->RdOff;
487 WrOff = pRing->WrOff;
493 NumBytesRem = pRing->SizeOfBuffer - RdOff;
494 NumBytesRem =
MIN(NumBytesRem, BufferSize);
495 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
496 NumBytesRead += NumBytesRem;
497 pBuffer += NumBytesRem;
498 BufferSize -= NumBytesRem;
499 RdOff += NumBytesRem;
503 if (RdOff == pRing->SizeOfBuffer) {
510 NumBytesRem = WrOff - RdOff;
511 NumBytesRem =
MIN(NumBytesRem, BufferSize);
512 if (NumBytesRem > 0u) {
513 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
514 NumBytesRead += NumBytesRem;
515 pBuffer += NumBytesRem;
516 BufferSize -= NumBytesRem;
517 RdOff += NumBytesRem;
520 pRing->RdOff = RdOff;
542 unsigned SEGGER_RTT_Read(
unsigned BufferIndex,
void* pBuffer,
unsigned BufferSize) {
543 unsigned NumBytesRead;
549 NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
581 void SEGGER_RTT_WriteWithOverwriteNoLock(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
583 SEGGER_RTT_BUFFER_UP* pRing;
586 pData = (
const char *)pBuffer;
590 pRing = &_SEGGER_RTT.aUp[BufferIndex];
594 if (pRing->WrOff == pRing->RdOff) {
595 Avail = pRing->SizeOfBuffer - 1u;
596 }
else if ( pRing->WrOff < pRing->RdOff) {
597 Avail = pRing->RdOff - pRing->WrOff - 1u;
599 Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
601 if (NumBytes > Avail) {
602 pRing->RdOff += (NumBytes - Avail);
603 while (pRing->RdOff >= pRing->SizeOfBuffer) {
604 pRing->RdOff -= pRing->SizeOfBuffer;
610 Avail = pRing->SizeOfBuffer - pRing->WrOff;
612 if (Avail > NumBytes) {
616 #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. 618 pDst = pRing->pBuffer + pRing->WrOff;
619 pRing->WrOff += NumBytes;
622 }
while (--NumBytes);
624 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
625 pRing->WrOff += NumBytes;
632 memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
636 Avail = (pRing->SizeOfBuffer - 1);
665 unsigned SEGGER_RTT_WriteSkipNoLock(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
667 SEGGER_RTT_BUFFER_UP* pRing;
673 pData = (
const char *)pBuffer;
677 pRing = &_SEGGER_RTT.aUp[BufferIndex];
678 RdOff = pRing->RdOff;
679 WrOff = pRing->WrOff;
693 if (RdOff <= WrOff) {
697 Avail = pRing->SizeOfBuffer - 1u - WrOff ;
698 if (Avail >= NumBytes) {
699 #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. 701 pDst = pRing->pBuffer + WrOff;
705 }
while (--NumBytes);
706 pRing->WrOff = WrOff + NumBytes;
708 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
709 pRing->WrOff = WrOff + NumBytes;
720 if (Avail >= NumBytes) {
724 Rem = pRing->SizeOfBuffer - WrOff;
725 if (Rem > NumBytes) {
726 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
727 pRing->WrOff = WrOff + NumBytes;
732 memcpy(pRing->pBuffer + WrOff, pData, Rem);
733 memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
734 pRing->WrOff = NumBytes - Rem;
739 Avail = RdOff - WrOff - 1u;
740 if (Avail >= NumBytes) {
741 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
742 pRing->WrOff = WrOff + NumBytes;
775 unsigned SEGGER_RTT_WriteNoLock(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
779 SEGGER_RTT_BUFFER_UP* pRing;
781 pData = (
const char *)pBuffer;
785 pRing = &_SEGGER_RTT.aUp[BufferIndex];
789 switch (pRing->Flags) {
790 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
795 Avail = _GetAvailWriteSpace(pRing);
796 if (Avail < NumBytes) {
800 _WriteNoCheck(pRing, pData, NumBytes);
803 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
807 Avail = _GetAvailWriteSpace(pRing);
808 Status = Avail < NumBytes ? Avail : NumBytes;
809 _WriteNoCheck(pRing, pData, Status);
811 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
815 Status = _WriteBlocking(pRing, pData, NumBytes);
846 unsigned SEGGER_RTT_Write(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
854 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
884 unsigned SEGGER_RTT_WriteString(
unsigned BufferIndex,
const char* s) {
888 return SEGGER_RTT_Write(BufferIndex, s, Len);
906 int SEGGER_RTT_GetKey(
void) {
910 r = (int)SEGGER_RTT_Read(0u, &c, 1u);
912 r = (int)(
unsigned char)c;
934 int SEGGER_RTT_WaitKey(
void) {
938 r = SEGGER_RTT_GetKey();
957 int SEGGER_RTT_HasKey(
void) {
962 RdOff = _SEGGER_RTT.aDown[0].RdOff;
963 if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
983 unsigned SEGGER_RTT_HasData(
unsigned BufferIndex) {
984 SEGGER_RTT_BUFFER_DOWN* pRing;
987 pRing = &_SEGGER_RTT.aDown[BufferIndex];
989 return v - pRing->RdOff;
1011 int SEGGER_RTT_AllocDownBuffer(
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
1018 if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
1022 }
while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
1023 if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
1024 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1025 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (
char*)pBuffer;
1026 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1027 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
1028 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
1029 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1033 SEGGER_RTT_UNLOCK();
1056 int SEGGER_RTT_AllocUpBuffer(
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
1063 if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
1067 }
while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
1068 if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
1069 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1070 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (
char*)pBuffer;
1071 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1072 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
1073 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
1074 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1078 SEGGER_RTT_UNLOCK();
1107 int SEGGER_RTT_ConfigUpBuffer(
unsigned BufferIndex,
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
1111 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1113 if (BufferIndex > 0u) {
1114 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1115 _SEGGER_RTT.aUp[BufferIndex].pBuffer = (
char*)pBuffer;
1116 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
1117 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
1118 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
1120 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1121 SEGGER_RTT_UNLOCK();
1154 int SEGGER_RTT_ConfigDownBuffer(
unsigned BufferIndex,
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
1158 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1160 if (BufferIndex > 0u) {
1161 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1162 _SEGGER_RTT.aDown[BufferIndex].pBuffer = (
char*)pBuffer;
1163 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
1164 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
1165 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
1167 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1168 SEGGER_RTT_UNLOCK();
1192 int SEGGER_RTT_SetNameUpBuffer(
unsigned BufferIndex,
const char* sName) {
1196 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1198 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
1199 SEGGER_RTT_UNLOCK();
1223 int SEGGER_RTT_SetNameDownBuffer(
unsigned BufferIndex,
const char* sName) {
1227 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1229 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
1230 SEGGER_RTT_UNLOCK();
1254 int SEGGER_RTT_SetFlagsUpBuffer(
unsigned BufferIndex,
unsigned Flags) {
1258 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
1260 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
1261 SEGGER_RTT_UNLOCK();
1285 int SEGGER_RTT_SetFlagsDownBuffer(
unsigned BufferIndex,
unsigned Flags) {
1289 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
1291 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
1292 SEGGER_RTT_UNLOCK();
1309 void SEGGER_RTT_Init (
void) {
1327 int SEGGER_RTT_SetTerminal (
char TerminalId) {
1329 SEGGER_RTT_BUFFER_UP* pRing;
1337 if ((
unsigned char)TerminalId < (
unsigned char)
sizeof(_aTerminalId)) {
1338 ac[1] = _aTerminalId[(
unsigned char)TerminalId];
1339 pRing = &_SEGGER_RTT.aUp[0];
1341 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
1342 _ActiveTerminal = TerminalId;
1343 _WriteBlocking(pRing, ac, 2u);
1345 Avail = _GetAvailWriteSpace(pRing);
1347 _ActiveTerminal = TerminalId;
1348 _WriteNoCheck(pRing, ac, 2u);
1353 SEGGER_RTT_UNLOCK();
1377 int SEGGER_RTT_TerminalOut (
char TerminalId,
const char* s) {
1381 SEGGER_RTT_BUFFER_UP* pRing;
1387 if (TerminalId < (
char)
sizeof(_aTerminalId)) {
1391 pRing = &_SEGGER_RTT.aUp[0];
1396 FragLen = strlen(s);
1401 Avail = _GetAvailWriteSpace(pRing);
1402 switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1403 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1408 if (Avail < (FragLen + 4u)) {
1411 _PostTerminalSwitch(pRing, TerminalId);
1412 Status = (int)_WriteBlocking(pRing, s, FragLen);
1413 _PostTerminalSwitch(pRing, _ActiveTerminal);
1416 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1425 _PostTerminalSwitch(pRing, TerminalId);
1426 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1427 _PostTerminalSwitch(pRing, _ActiveTerminal);
1430 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1434 _PostTerminalSwitch(pRing, TerminalId);
1435 Status = (int)_WriteBlocking(pRing, s, FragLen);
1436 _PostTerminalSwitch(pRing, _ActiveTerminal);
1445 SEGGER_RTT_UNLOCK();