56 #include "segger-rtt.h" 67 #ifndef BUFFER_SIZE_UP 68 #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 71 #ifndef BUFFER_SIZE_DOWN 72 #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) 75 #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 76 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target 79 #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 80 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target 83 #ifndef SEGGER_RTT_MODE_DEFAULT 84 #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 87 #ifndef SEGGER_RTT_LOCK 88 #define SEGGER_RTT_LOCK(SavedState) 91 #ifndef SEGGER_RTT_UNLOCK 92 #define SEGGER_RTT_UNLOCK(SavedState) 96 #define STRLEN(a) strlen((a)) 100 #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 104 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 108 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 124 static unsigned char _aTerminalId[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
135 static char _acUpBuffer [BUFFER_SIZE_UP];
136 static char _acDownBuffer[BUFFER_SIZE_DOWN];
140 SEGGER_RTT_CB _SEGGER_RTT;
142 static char _ActiveTerminal;
160 #define INIT() do { \ 161 if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ 163 static void _DoInit(
void) {
169 p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
170 p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
174 p->aUp[0].sName =
"Terminal";
175 p->aUp[0].pBuffer = _acUpBuffer;
176 p->aUp[0].SizeOfBuffer =
sizeof(_acUpBuffer);
177 p->aUp[0].RdOff = 0u;
178 p->aUp[0].WrOff = 0u;
179 p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
183 p->aDown[0].sName =
"Terminal";
184 p->aDown[0].pBuffer = _acDownBuffer;
185 p->aDown[0].SizeOfBuffer =
sizeof(_acDownBuffer);
186 p->aDown[0].RdOff = 0u;
187 p->aDown[0].WrOff = 0u;
188 p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
194 strcpy(&p->acID[7],
"RTT");
195 strcpy(&p->acID[0],
"SEGGER");
218 static unsigned _WriteBlocking(SEGGER_RTT_RING_BUFFER *pRing,
const char* pBuffer,
unsigned NumBytes) {
219 unsigned NumBytesToWrite;
220 unsigned NumBytesWritten;
226 NumBytesWritten = 0u;
227 WrOff = pRing->WrOff;
229 RdOff = pRing->RdOff;
231 NumBytesToWrite = RdOff - WrOff - 1u;
233 NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
235 NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));
236 NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
237 memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
238 NumBytesWritten += NumBytesToWrite;
239 pBuffer += NumBytesToWrite;
240 NumBytes -= NumBytesToWrite;
241 WrOff += NumBytesToWrite;
242 if (WrOff == pRing->SizeOfBuffer) {
245 pRing->WrOff = WrOff;
248 return NumBytesWritten;
269 static void _WriteNoCheck(SEGGER_RTT_RING_BUFFER *pRing,
const char* pData,
unsigned NumBytes) {
270 unsigned NumBytesAtOnce;
274 WrOff = pRing->WrOff;
275 Rem = pRing->SizeOfBuffer - WrOff;
276 if (Rem > NumBytes) {
280 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
281 pRing->WrOff = WrOff + NumBytes;
286 NumBytesAtOnce = Rem;
287 memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
288 NumBytesAtOnce = NumBytes - Rem;
289 memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
290 pRing->WrOff = NumBytesAtOnce;
307 static void _PostTerminalSwitch(SEGGER_RTT_RING_BUFFER *pRing,
char TerminalId) {
311 ac[1] = _aTerminalId[(int)TerminalId];
312 _WriteBlocking(pRing, ac, 2u);
329 static unsigned _GetAvailWriteSpace(SEGGER_RTT_RING_BUFFER *pRing) {
337 RdOff = pRing->RdOff;
338 WrOff = pRing->WrOff;
339 if (RdOff <= WrOff) {
340 r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
342 r = RdOff - WrOff - 1u;
370 unsigned SEGGER_RTT_ReadNoLock(
unsigned BufferIndex,
void* pData,
unsigned BufferSize) {
371 unsigned NumBytesRem;
372 unsigned NumBytesRead;
375 unsigned char* pBuffer;
376 SEGGER_RTT_RING_BUFFER* pRing;
379 pRing = &_SEGGER_RTT.aDown[BufferIndex];
380 pBuffer = (
unsigned char*)pData;
381 RdOff = pRing->RdOff;
382 WrOff = pRing->WrOff;
388 NumBytesRem = pRing->SizeOfBuffer - RdOff;
389 NumBytesRem = MIN(NumBytesRem, BufferSize);
390 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
391 NumBytesRead += NumBytesRem;
392 pBuffer += NumBytesRem;
393 BufferSize -= NumBytesRem;
394 RdOff += NumBytesRem;
398 if (RdOff == pRing->SizeOfBuffer) {
405 NumBytesRem = WrOff - RdOff;
406 NumBytesRem = MIN(NumBytesRem, BufferSize);
407 if (NumBytesRem > 0u) {
408 memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
409 NumBytesRead += NumBytesRem;
410 pBuffer += NumBytesRem;
411 BufferSize -= NumBytesRem;
412 RdOff += NumBytesRem;
415 pRing->RdOff = RdOff;
437 unsigned SEGGER_RTT_Read(
unsigned BufferIndex,
void* pBuffer,
unsigned BufferSize) {
438 unsigned NumBytesRead;
439 volatile unsigned SavedState;
441 SEGGER_RTT_LOCK(SavedState);
445 NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
449 SEGGER_RTT_UNLOCK(SavedState);
478 unsigned SEGGER_RTT_WriteSkipNoLock(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
480 SEGGER_RTT_RING_BUFFER* pRing;
486 pData = (
const char *)pBuffer;
490 pRing = &_SEGGER_RTT.aUp[BufferIndex];
491 RdOff = pRing->RdOff;
492 WrOff = pRing->WrOff;
506 if (RdOff <= WrOff) {
510 Avail = pRing->SizeOfBuffer - 1u - WrOff ;
511 if (Avail >= NumBytes) {
512 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
513 pRing->WrOff = WrOff + NumBytes;
523 if (Avail >= NumBytes) {
527 Rem = pRing->SizeOfBuffer - WrOff;
528 if (Rem > NumBytes) {
529 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
530 pRing->WrOff = WrOff + NumBytes;
535 memcpy(pRing->pBuffer + WrOff, pData, Rem);
536 memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
537 pRing->WrOff = NumBytes - Rem;
542 Avail = RdOff - WrOff - 1u;
543 if (Avail >= NumBytes) {
544 memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
545 pRing->WrOff = WrOff + NumBytes;
578 unsigned SEGGER_RTT_WriteNoLock(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
582 SEGGER_RTT_RING_BUFFER *pRing;
584 pData = (
const char *)pBuffer;
588 pRing = &_SEGGER_RTT.aUp[BufferIndex];
592 switch (pRing->Flags) {
593 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
598 Avail = _GetAvailWriteSpace(pRing);
599 if (Avail < NumBytes) {
603 _WriteNoCheck(pRing, pData, NumBytes);
606 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
610 Avail = _GetAvailWriteSpace(pRing);
611 Status = Avail < NumBytes ? Avail : NumBytes;
612 _WriteNoCheck(pRing, pData, Status);
614 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
618 Status = _WriteBlocking(pRing, pData, NumBytes);
649 unsigned SEGGER_RTT_Write(
unsigned BufferIndex,
const void* pBuffer,
unsigned NumBytes) {
651 volatile unsigned SavedState;
654 SEGGER_RTT_LOCK(SavedState);
658 Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
662 SEGGER_RTT_UNLOCK(SavedState);
688 unsigned SEGGER_RTT_WriteString(
unsigned BufferIndex,
const char* s) {
692 return SEGGER_RTT_Write(BufferIndex, s, Len);
710 int SEGGER_RTT_GetKey(
void) {
714 r = (int)SEGGER_RTT_Read(0u, &c, 1u);
716 r = (int)(
unsigned char)c;
738 int SEGGER_RTT_WaitKey(
void) {
742 r = SEGGER_RTT_GetKey();
761 int SEGGER_RTT_HasKey(
void) {
766 RdOff = _SEGGER_RTT.aDown[0].RdOff;
767 if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
787 unsigned SEGGER_RTT_HasData(
unsigned BufferIndex) {
788 SEGGER_RTT_RING_BUFFER *pRing;
791 pRing = &_SEGGER_RTT.aDown[BufferIndex];
793 return v - pRing->RdOff;
817 int SEGGER_RTT_ConfigUpBuffer(
unsigned BufferIndex,
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
819 volatile unsigned SavedState;
822 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
823 SEGGER_RTT_LOCK(SavedState);
824 if (BufferIndex > 0u) {
825 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
826 _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer;
827 _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
828 _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
829 _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
831 _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
832 SEGGER_RTT_UNLOCK(SavedState);
860 int SEGGER_RTT_ConfigDownBuffer(
unsigned BufferIndex,
const char* sName,
void* pBuffer,
unsigned BufferSize,
unsigned Flags) {
862 volatile unsigned SavedState;
865 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
866 SEGGER_RTT_LOCK(SavedState);
867 if (BufferIndex > 0u) {
868 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
869 _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer;
870 _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
871 _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
872 _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
874 _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
875 SEGGER_RTT_UNLOCK(SavedState);
899 int SEGGER_RTT_SetNameUpBuffer(
unsigned BufferIndex,
const char* sName) {
901 volatile unsigned SavedState;
904 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
905 SEGGER_RTT_LOCK(SavedState);
906 _SEGGER_RTT.aUp[BufferIndex].sName = sName;
907 SEGGER_RTT_UNLOCK(SavedState);
931 int SEGGER_RTT_SetNameDownBuffer(
unsigned BufferIndex,
const char* sName) {
933 volatile unsigned SavedState;
936 if (BufferIndex < (
unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
937 SEGGER_RTT_LOCK(SavedState);
938 _SEGGER_RTT.aDown[BufferIndex].sName = sName;
939 SEGGER_RTT_UNLOCK(SavedState);
956 void SEGGER_RTT_Init (
void) {
974 int SEGGER_RTT_SetTerminal (
char TerminalId) {
976 SEGGER_RTT_RING_BUFFER *pRing;
977 volatile unsigned SavedState;
985 if (TerminalId < (
char)
sizeof(_aTerminalId)) {
986 ac[1] = _aTerminalId[(int)TerminalId];
987 pRing = &_SEGGER_RTT.aUp[0];
988 SEGGER_RTT_LOCK(SavedState);
989 if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
990 _ActiveTerminal = TerminalId;
991 _WriteBlocking(pRing, ac, 2u);
993 Avail = _GetAvailWriteSpace(pRing);
995 _ActiveTerminal = TerminalId;
996 _WriteNoCheck(pRing, ac, 2u);
1001 SEGGER_RTT_UNLOCK(SavedState);
1025 int SEGGER_RTT_TerminalOut (
char TerminalId,
const char* s) {
1029 SEGGER_RTT_RING_BUFFER *pRing;
1030 volatile unsigned SavedState;
1036 if (TerminalId < (
char)
sizeof(_aTerminalId)) {
1040 pRing = &_SEGGER_RTT.aUp[0];
1045 FragLen = strlen(s);
1049 SEGGER_RTT_LOCK(SavedState);
1050 Avail = _GetAvailWriteSpace(pRing);
1051 switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
1052 case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
1057 if (Avail < (FragLen + 4u)) {
1060 _PostTerminalSwitch(pRing, TerminalId);
1061 Status = (int)_WriteBlocking(pRing, s, FragLen);
1062 _PostTerminalSwitch(pRing, _ActiveTerminal);
1065 case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
1074 _PostTerminalSwitch(pRing, TerminalId);
1075 Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
1076 _PostTerminalSwitch(pRing, _ActiveTerminal);
1079 case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
1083 _PostTerminalSwitch(pRing, TerminalId);
1084 Status = (int)_WriteBlocking(pRing, s, FragLen);
1085 _PostTerminalSwitch(pRing, _ActiveTerminal);
1094 SEGGER_RTT_UNLOCK(SavedState);