/********************************************************************* * * SEGGER_RTT_SetNameUpBuffer * * Function description * Run-time configuration of a specific up-buffer name (T->H). * Buffer to be configured is specified by index. * * Parameters * BufferIndex Index of the buffer to renamed. * sName Pointer to a constant name string. * * Return value * >= 0 O.K. * < 0 Error */ int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { int r; INIT(); if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { SEGGER_RTT_LOCK(); _SEGGER_RTT.aUp[BufferIndex].sName = sName; 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_Read * * Function description * Reads characters from SEGGER real-time-terminal control block * which have been previously stored by the host. * * Parameters * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. * BufferSize Size of the target application buffer. * * Return value * Number of bytes that have been read. */ unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { unsigned NumBytesRead; // SEGGER_RTT_LOCK(); // // Call the non-locking read function // NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); // // Finish up. // SEGGER_RTT_UNLOCK(); // return NumBytesRead; }
/********************************************************************* * * SEGGER_RTT_Write * * Function description * Stores a specified number of characters in SEGGER RTT * control block which is then read by the host. * * Parameters * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. * NumBytes Number of bytes to be stored in the SEGGER RTT control block. * * 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, remaining characters of pBuffer are dropped. */ unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { unsigned Status; // INIT(); SEGGER_RTT_LOCK(); // // Call the non-locking write function // Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // // Finish up. // SEGGER_RTT_UNLOCK(); // return Status; }
/********************************************************************* * * SEGGER_RTT_Read * * Function description * Reads characters from SEGGER real-time-terminal control block * which have been previously stored by the host. * * Parameters * BufferIndex Index of Down-buffer to be used. (e.g. 0 for "Terminal") * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. * BufferSize Size of the target application buffer * * Return values * Number of bytes that have been read */ int32_t SEGGER_RTT_Read(unsigned BufferIndex, char* pBuffer, unsigned BufferSize) { int32_t NumBytesRem; unsigned NumBytesRead; int32_t RdOff; int32_t WrOff; SEGGER_RTT_LOCK(); _Init(); RdOff = _SEGGER_RTT.aDown[BufferIndex].RdOff; WrOff = _SEGGER_RTT.aDown[BufferIndex].WrOff; NumBytesRead = 0; // // Read from current read position to wrap-around of buffer, first // if (RdOff > WrOff) { NumBytesRem = _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer - RdOff; NumBytesRem = MIN(NumBytesRem, (int32_t)BufferSize); MEMCPY(pBuffer, _SEGGER_RTT.aDown[BufferIndex].pBuffer + RdOff, NumBytesRem); NumBytesRead += NumBytesRem; pBuffer += NumBytesRem; BufferSize -= NumBytesRem; RdOff += NumBytesRem; // // Handle wrap-around of buffer // if (RdOff == _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer) { RdOff = 0; } } // // Read remaining items of buffer // NumBytesRem = WrOff - RdOff; NumBytesRem = MIN(NumBytesRem, (int32_t)BufferSize); if (NumBytesRem > 0) { MEMCPY(pBuffer, _SEGGER_RTT.aDown[BufferIndex].pBuffer + RdOff, NumBytesRem); NumBytesRead += NumBytesRem; pBuffer += NumBytesRem; BufferSize -= NumBytesRem; RdOff += NumBytesRem; } if (NumBytesRead) { _SEGGER_RTT.aDown[BufferIndex].RdOff = RdOff; } SEGGER_RTT_UNLOCK(); return NumBytesRead; }
/********************************************************************* * * SEGGER_RTT_ConfigDownBuffer * * Function description * Run-time configuration of a specific down-buffer (H->T). * Buffer to be configured is specified by index. * This includes: Buffer address, size, name, flags, ... * * Return value * >= 0 O.K. * < 0 Error */ int32_t SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, char* pBuffer, int32_t BufferSize, int32_t Flags) { _Init(); if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { SEGGER_RTT_LOCK(); if (BufferIndex > 0) { _SEGGER_RTT.aDown[BufferIndex].sName = sName; _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; _SEGGER_RTT.aDown[BufferIndex].RdOff = 0; _SEGGER_RTT.aDown[BufferIndex].WrOff = 0; } _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; SEGGER_RTT_UNLOCK(); return 0; } return -1; }
/********************************************************************* * * SEGGER_RTT_ConfigDownBuffer * * Function description * Run-time configuration of a specific down-buffer (H->T). * Buffer to be configured is specified by index. * This includes: Buffer address, size, name, flags, ... * * Parameters * BufferIndex Index of the buffer to configure. * sName Pointer to a constant name string. * pBuffer Pointer to a buffer to be used. * BufferSize Size of the buffer. * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). * * Return value * >= 0 O.K. * < 0 Error */ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { int r; INIT(); if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { SEGGER_RTT_LOCK(); if (BufferIndex > 0u) { _SEGGER_RTT.aDown[BufferIndex].sName = sName; _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; } _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; SEGGER_RTT_UNLOCK(); r = 0; } else { r = -1; } return r; }
/********************************************************************* * * SEGGER_RTT_TerminalOut * * Function description * Writes a string to the given terminal * without changing the terminal for channel 0. * * Parameters * TerminalId Index of the terminal. * s String to be printed on the terminal. * * Return value * >= 0 - Number of bytes written. * < 0 - Error. * */ int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { int Status; unsigned FragLen; unsigned Avail; SEGGER_RTT_BUFFER_UP* pRing; // INIT(); // // Validate terminal ID. // if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels // // Get "to-host" ring buffer. // pRing = &_SEGGER_RTT.aUp[0]; // // Need to be able to change terminal, write data, change back. // Compute the fixed and variable sizes. // FragLen = strlen(s); // // How we output depends upon the mode... // SEGGER_RTT_LOCK(); Avail = _GetAvailWriteSpace(pRing); switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { case SEGGER_RTT_MODE_NO_BLOCK_SKIP: // // If we are in skip mode and there is no space for the whole // of this output, don't bother switching terminals at all. // if (Avail < (FragLen + 4u)) { Status = 0; } else { _PostTerminalSwitch(pRing, TerminalId); Status = (int)_WriteBlocking(pRing, s, FragLen); _PostTerminalSwitch(pRing, _ActiveTerminal); } break; case SEGGER_RTT_MODE_NO_BLOCK_TRIM: // // If we are in trim mode and there is not enough space for everything, // trim the output but always include the terminal switch. If no room // for terminal switch, skip that totally. // if (Avail < 4u) { Status = -1; } else { _PostTerminalSwitch(pRing, TerminalId); Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); _PostTerminalSwitch(pRing, _ActiveTerminal); } break; case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: // // If we are in blocking mode, output everything. // _PostTerminalSwitch(pRing, TerminalId); Status = (int)_WriteBlocking(pRing, s, FragLen); _PostTerminalSwitch(pRing, _ActiveTerminal); break; default: Status = -1; break; } // // Finish up. // SEGGER_RTT_UNLOCK(); } else { Status = -1; } return Status; }
/********************************************************************* * * SEGGER_RTT_Write * * Function description * Stores a specified number of characters in SEGGER RTT * control block which is then read by the host. * * Parameters * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. * NumBytes Number of bytes to be stored in the SEGGER RTT control block. * * Return values * Number of bytes which have been stored in the "Up"-buffer. * * Notes * (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. */ int32_t SEGGER_RTT_Write(unsigned BufferIndex, const char* pBuffer, unsigned NumBytes) { int32_t NumBytesToWrite; unsigned NumBytesWritten; int32_t RdOff; // // Target is not allowed to perform other RTT operations while string still has not been stored completely. // Otherwise we would probably end up with a mixed string in the buffer. // SEGGER_RTT_LOCK(); _Init(); // // In case we are not in blocking mode, // we need to calculate, how many bytes we can put into the buffer at all. // if ((_SEGGER_RTT.aUp[BufferIndex].Flags & SEGGER_RTT_MODE_MASK) != SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; NumBytesToWrite = RdOff - _SEGGER_RTT.aUp[BufferIndex].WrOff - 1; if (NumBytesToWrite < 0) { NumBytesToWrite += _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer; } // // If the complete data does not fit in the buffer, check if we have to skip it completely or trim the data // if ((int32_t)NumBytes > NumBytesToWrite) { if ((_SEGGER_RTT.aUp[BufferIndex].Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_NO_BLOCK_SKIP) { SEGGER_RTT_UNLOCK(); return 0; } else { NumBytes = NumBytesToWrite; } } } // // Early out if nothing is to do // if (NumBytes == 0) { SEGGER_RTT_UNLOCK(); return 0; } // // Write data to buffer and handle wrap-around if necessary // NumBytesWritten = 0; do { RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; // May be changed by host (debug probe) in the meantime NumBytesToWrite = RdOff - _SEGGER_RTT.aUp[BufferIndex].WrOff - 1; if (NumBytesToWrite < 0) { NumBytesToWrite += _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer; } NumBytesToWrite = MIN(NumBytesToWrite, (_SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - _SEGGER_RTT.aUp[BufferIndex].WrOff)); // Number of bytes that can be written until buffer wrap-around NumBytesToWrite = MIN(NumBytesToWrite, (int32_t)NumBytes); MEMCPY(_SEGGER_RTT.aUp[BufferIndex].pBuffer + _SEGGER_RTT.aUp[BufferIndex].WrOff, pBuffer, NumBytesToWrite); NumBytesWritten += NumBytesToWrite; pBuffer += NumBytesToWrite; NumBytes -= NumBytesToWrite; _SEGGER_RTT.aUp[BufferIndex].WrOff += NumBytesToWrite; if (_SEGGER_RTT.aUp[BufferIndex].WrOff == _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer) { _SEGGER_RTT.aUp[BufferIndex].WrOff = 0; } } while (NumBytes); SEGGER_RTT_UNLOCK(); return NumBytesWritten; }