Compare commits

...

41 Commits

Author SHA1 Message Date
muellerr a747be6c65 Some fixes
1. InternalUnitTester: Mutex test now uses new defines
2. CMakeLists.txt: The OSAL defines are now defined in the FSFW.h file
2021-08-10 11:21:57 +02:00
muellerr 09d76c2e26 made semaphore tests optional 2021-08-10 11:14:18 +02:00
muellerr d06c92c478 Merge remote-tracking branch 'eive/mueller/tcp-udp-tweaks' into mueller/master 2021-08-10 11:11:06 +02:00
muellerr c6d80a5c81 Merge remote-tracking branch 'origin/development' into mueller/master 2021-08-10 11:07:58 +02:00
muellerr eecb69d230 getter function for UDP port 2021-08-09 18:22:51 +02:00
muellerr 14a30f30db More improvements for TCP/UDP port definition 2021-08-09 18:13:02 +02:00
muellerr ccaa0aa24f Cleaning up TCP and UDP code
Same port number used as before, but some inconsistencies fixed
2021-08-09 16:59:41 +02:00
mohr d92a796705 Merge pull request 'FSFW Restructuring' (#445) from mueller/restructuring into development
Reviewed-on: #445
2021-08-09 16:00:26 +02:00
mohr 1fa59c5cae Merge pull request 'Linux HAL updates' (#456) from mueller/hal-linux-spi-uart-update into mueller/restructuring
Reviewed-on: #456
2021-08-09 15:39:18 +02:00
muellerr 83b5ade6b7 Merge branch 'mueller/hal-linux-spi-uart-update' of https://egit.irs.uni-stuttgart.de/fsfw/fsfw into mueller/hal-linux-spi-uart-update 2021-08-09 15:38:07 +02:00
muellerr 62873c3118 UartComIF check iter validity 2021-08-09 15:37:12 +02:00
muellerr 1301988892 Merge branch 'mueller/restructuring' into mueller/hal-linux-spi-uart-update 2021-08-09 15:31:56 +02:00
mohr 1c3770ce96 Merge pull request 'Printer updates' (#453) from mueller/updated-serviceinterface into mueller/restructuring
Reviewed-on: #453
2021-08-09 15:24:44 +02:00
muellerr 90a1571707 Linux HAL updates
1. The type correction was merged as part of
   eive/fsfw#7 in the
   EIVE project. Quotation of PR

definition of getSpiParameters is `void getSpiParameters(spi::SpiModes& spiMode, uint32_t& spiSpeed, UncommonParameters* parameters = nullptr) const;`.

Here, size_t spiSpeed is passed, which implicitely gets converted to a temporary, which can not be bound to uint32_t& and, at least in gcc 9.3.0, leads to a compiler error.

2. Allow flushing the UART buffers
2021-08-06 11:23:31 +02:00
muellerr 2706b8fa24 Printer updates
1. Only prefix is colored now
2. Minor formatting change
2021-08-06 11:06:33 +02:00
muellerr 7b4fb3041c important bugfix 2021-08-06 11:05:56 +02:00
muellerr 1684c3983f minor format tweak 2021-08-06 11:02:35 +02:00
muellerr 722cf5b6fe Merge remote-tracking branch 'eive/mueller/master' into mueller/master 2021-08-06 10:57:31 +02:00
muellerr 3704d2b829 bugfix 2021-08-05 18:24:56 +02:00
muellerr 6073abb12d added some utility to timer module 2021-08-05 18:13:01 +02:00
muellerr b2c102b2c1 Service Interface and Bugfix
1. Service Interface looks better now
2. Bugfix in CommandExecutor blocking mode
2021-08-05 16:13:22 +02:00
muellerr 4202205182 getter function for current state 2021-08-05 16:02:17 +02:00
muellerr c8472beb5f added new command executor 2021-08-05 15:42:47 +02:00
muellerr 1a4a85ceb2 Merge branch 'mueller/master' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/master 2021-08-03 18:38:27 +02:00
muellerr 7922bf76da corrected README 2021-08-03 18:38:18 +02:00
muellerr bb88490cc6 Merge remote-tracking branch 'upstream/mueller/restructuring' into mueller/master 2021-08-03 15:55:38 +02:00
muellerr 296c587e3d additional nullptr check 2021-08-03 15:29:22 +02:00
muellerr 0ff81294e7 Merge branch 'eive/develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into eive/develop 2021-08-02 12:49:50 +02:00
muellerr b6e243b8b3 var name clarification 2021-08-02 12:49:40 +02:00
meierj 3bbcc42d39 Merge pull request 'type missmatch' (#7) from mohr-patch-1 into eive/develop
Reviewed-on: eive/fsfw#7
2021-07-26 19:04:06 +02:00
mohr fc4324a2fa type missmatch 2021-07-26 18:35:53 +02:00
muellerr 54c028f913 naming adaptions 2021-07-26 13:50:45 +02:00
muellerr 1f6a5e635f naming fixes 2021-07-26 11:46:58 +02:00
muellerr c5b4b01362 Merge branch 'mueller/master' into eive/develop 2021-07-24 15:04:01 +02:00
muellerr c5420c7b53 bumped subversion 2021-07-24 14:39:43 +02:00
muellerr 3e422f51bd corrected version number 2021-07-24 13:43:13 +02:00
meierj d1be0f9843 Merge pull request 'Update framework' (#6) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#6
2021-07-23 18:26:39 +02:00
Jakob.Meier b83259592a uart flush function 2021-07-23 18:06:36 +02:00
muellerr a7a4e0f219 api consistent now 2021-07-19 19:03:20 +02:00
muellerr bdc5f593e2 Merge remote-tracking branch 'upstream/mueller/master' into mueller/master 2021-07-19 18:50:20 +02:00
muellerr 10f7185e81 added includes 2021-07-19 13:08:40 +02:00
28 changed files with 496 additions and 63 deletions
+4 -11
View File
@@ -63,18 +63,19 @@ set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
if(FSFW_OSAL MATCHES host)
set(OS_FSFW_NAME "Host")
set(FSFW_OSAL_HOST ON)
elseif(FSFW_OSAL MATCHES linux)
set(OS_FSFW_NAME "Linux")
set(FSFW_OSAL_DEFINITION FSFW_OSAL_LINUX)
set(FSFW_OSAL_HOST ON)
elseif(FSFW_OSAL MATCHES freertos)
set(OS_FSFW_NAME "FreeRTOS")
set(FSFW_OSAL_DEFINITION FSFW_OSAL_FREERTOS)
set(FSFW_OSAL_FREERTOS ON)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${LIB_OS_NAME}
)
elseif(FSFW_OSAL STREQUAL rtems)
set(OS_FSFW_NAME "RTEMS")
set(FSFW_OSAL_DEFINITION FSFW_OSAL_RTEMS)
set(FSFW_OSAL_RTEMS ON)
else()
message(WARNING
"Invalid operating system for FSFW specified! Setting to host.."
@@ -83,14 +84,6 @@ else()
set(OS_FSFW "host")
endif()
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
${FSFW_OSAL_DEFINITION}
)
target_compile_definitions(${LIB_FSFW_NAME} INTERFACE
${FSFW_OSAL_DEFINITION}
)
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
add_subdirectory(src)
+1 -1
View File
@@ -82,7 +82,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) {
gpioComIF->pullHigh(gpioId);
}
size_t spiSpeed = 0;
uint32_t spiSpeed = 0;
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
SpiCookie::UncommonParameters params;
+54
View File
@@ -443,6 +443,60 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF *cookie,
return RETURN_OK;
}
ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF *cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
if(uartCookie == nullptr) {
sif::warning << "UartComIF::flushUartRxBuffer: Invalid uart cookie!" << std::endl;
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if(uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCIFLUSH);
return RETURN_OK;
}
return RETURN_FAILED;
}
ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF *cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
if(uartCookie == nullptr) {
sif::warning << "UartComIF::flushUartTxBuffer: Invalid uart cookie!" << std::endl;
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if(uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCOFLUSH);
return RETURN_OK;
}
return RETURN_FAILED;
}
ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF *cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
if(uartCookie == nullptr) {
sif::warning << "UartComIF::flushUartTxAndRxBuf: Invalid uart cookie!" << std::endl;
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if(uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCIOFLUSH);
return RETURN_OK;
}
return RETURN_FAILED;
}
void UartComIF::setUartMode(struct termios *options, UartCookie &uartCookie) {
UartModes uartMode = uartCookie.getUartMode();
if(uartMode == UartModes::NON_CANONICAL) {
+15
View File
@@ -41,6 +41,21 @@ public:
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) override;
/**
* @brief This function discards all data received but not read in the UART buffer.
*/
ReturnValue_t flushUartRxBuffer(CookieIF *cookie);
/**
* @brief This function discards all data in the transmit buffer of the UART driver.
*/
ReturnValue_t flushUartTxBuffer(CookieIF *cookie);
/**
* @brief This function discards both data in the transmit and receive buffer of the UART.
*/
ReturnValue_t flushUartTxAndRxBuf(CookieIF *cookie);
private:
using UartDeviceFile_t = std::string;
+5
View File
@@ -3,6 +3,11 @@
#include "FSFWConfig.h"
#cmakedefine FSFW_OSAL_RTEMS
#cmakedefine FSFW_OSAL_FREERTOS
#cmakedefine FSFW_OSAL_LINUX
#cmakedefine FSFW_OSAL_HOST
#cmakedefine FSFW_ADD_RMAP
#cmakedefine FSFW_ADD_DATALINKLAYER
#cmakedefine FSFW_ADD_TMSTORAGE
+4 -6
View File
@@ -1,12 +1,10 @@
#ifndef FSFW_DEFAULTCFG_VERSION_H_
#define FSFW_DEFAULTCFG_VERSION_H_
#ifndef FSFW_VERSION_H_
#define FSFW_VERSION_H_
const char* const FSFW_VERSION_NAME = "ASTP";
#define FSFW_VERSION 1
#define FSFW_SUBVERSION 0
#define FSFW_SUBVERSION 3
#define FSFW_REVISION 0
#endif /* FSFW_DEFAULTCFG_VERSION_H_ */
#endif /* FSFW_VERSION_H_ */
+13 -1
View File
@@ -55,7 +55,19 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress) {
const uint8_t* dataPtr = NULL;
if(ipcStore == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ActionHelper::prepareExecution: IPC Store not set. Call initialize first"
<< std::endl;
#else
sif::printWarning("ActionHelper::prepareExecution: "
"IPC Store not set. Call initialize first\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return;
}
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != HasReturnvaluesIF::RETURN_OK) {
+1 -1
View File
@@ -81,7 +81,7 @@ public:
* @param args Any other arguments which an implementation might require
* @return
*/
virtual ReturnValue_t deleteFile(const char* repositoryPath,
virtual ReturnValue_t removeFile(const char* repositoryPath,
const char* filename, void* args = nullptr) = 0;
/**
-3
View File
@@ -1,6 +1,5 @@
#include "fsfw/platform.h"
#include "fsfw/osal/common/TcpTmTcBridge.h"
#include "fsfw/osal/common/tcpipHelpers.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/ipc/MutexGuard.h"
@@ -17,8 +16,6 @@
#endif
const std::string TcpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId):
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
+1 -3
View File
@@ -2,7 +2,7 @@
#define FSFW_OSAL_COMMON_TCPTMTCBRIDGE_H_
#include "TcpIpBase.h"
#include "../../tmtcservices/TmTcBridge.h"
#include "fsfw/tmtcservices/TmTcBridge.h"
#ifdef _WIN32
@@ -29,8 +29,6 @@ class TcpTmTcBridge:
public TmTcBridge {
friend class TcpTmTcServer;
public:
/* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_UDP_SERVER_PORT;
/**
* Constructor
+6 -2
View File
@@ -22,14 +22,14 @@
#define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0
#endif
const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7303";
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
size_t receptionBufferSize, std::string customTcpServerPort):
SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge),
tcpPort(customTcpServerPort), receptionBuffer(receptionBufferSize) {
if(tcpPort == "") {
tcpPort = DEFAULT_TCP_SERVER_PORT;
tcpPort = DEFAULT_SERVER_PORT;
}
}
@@ -200,6 +200,10 @@ void TcpTmTcServer::setTcpBacklog(uint8_t tcpBacklog) {
this->tcpBacklog = tcpBacklog;
}
std::string TcpTmTcServer::getTcpPort() const {
return tcpPort;
}
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket) {
// Access to the FIFO is mutex protected because it is filled by the bridge
MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
+12 -10
View File
@@ -3,13 +3,14 @@
#include "TcpIpBase.h"
#include "../../platform.h"
#include "../../ipc/messageQueueDefinitions.h"
#include "../../ipc/MessageQueueIF.h"
#include "../../objectmanager/frameworkObjects.h"
#include "../../objectmanager/SystemObject.h"
#include "../../storagemanager/StorageManagerIF.h"
#include "../../tasks/ExecutableObjectIF.h"
#include "fsfw/platform.h"
#include "fsfw/osal/common/tcpipHelpers.h"
#include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/objectmanager/frameworkObjects.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#ifdef PLATFORM_UNIX
#include <sys/socket.h>
@@ -41,10 +42,9 @@ class TcpTmTcServer:
public TcpIpBase,
public ExecutableObjectIF {
public:
/* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_TCP_SERVER_PORT;
static const std::string DEFAULT_SERVER_PORT;
static constexpr size_t ETHERNET_MTU_SIZE = 1500;
static constexpr size_t ETHERNET_MTU_SIZE = 1500;
/**
* TCP Server Constructor
@@ -65,6 +65,8 @@ public:
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
std::string getTcpPort() const;
protected:
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
+6 -2
View File
@@ -17,13 +17,13 @@
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
#endif
const std::string UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
std::string udpServerPort, object_id_t tmStoreId, object_id_t tcStoreId):
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
if(udpServerPort == "") {
this->udpServerPort = DEFAULT_UDP_SERVER_PORT;
this->udpServerPort = DEFAULT_SERVER_PORT;
}
else {
this->udpServerPort = udpServerPort;
@@ -108,6 +108,10 @@ UdpTmTcBridge::~UdpTmTcBridge() {
}
}
std::string UdpTmTcBridge::getUdpPort() const {
return udpServerPort;
}
ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
int flags = 0;
+5 -3
View File
@@ -2,8 +2,8 @@
#define FSFW_OSAL_COMMON_TMTCUDPBRIDGE_H_
#include "TcpIpBase.h"
#include "../../platform.h"
#include "../../tmtcservices/TmTcBridge.h"
#include "fsfw/platform.h"
#include "fsfw/tmtcservices/TmTcBridge.h"
#ifdef PLATFORM_WIN
#include <ws2tcpip.h>
@@ -28,7 +28,7 @@ class UdpTmTcBridge:
friend class UdpTcPollingTask;
public:
/* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_UDP_SERVER_PORT;
static const std::string DEFAULT_SERVER_PORT;
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
std::string udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
@@ -44,6 +44,8 @@ public:
void checkAndSetClientAddress(sockaddr& clientAddress);
std::string getUdpPort() const;
protected:
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
+2 -2
View File
@@ -1,7 +1,7 @@
#ifndef FSFW_OSAL_COMMON_TCPIPCOMMON_H_
#define FSFW_OSAL_COMMON_TCPIPCOMMON_H_
#include "../../timemanager/clockDefinitions.h"
#include "fsfw/timemanager/clockDefinitions.h"
#include <string>
#ifdef _WIN32
@@ -13,7 +13,7 @@
namespace tcpip {
const char* const DEFAULT_SERVER_PORT = "7301";
static constexpr char DEFAULT_SERVER_PORT[] = "7301";
enum class Protocol {
UDP,
+1
View File
@@ -16,6 +16,7 @@ target_sources(${LIB_FSFW_NAME}
Timer.cpp
tcpipHelpers.cpp
unixUtility.cpp
CommandExecutor.cpp
)
find_package(Threads REQUIRED)
+185
View File
@@ -0,0 +1,185 @@
#include "CommandExecutor.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/container/SimpleRingBuffer.h"
#include "fsfw/container/DynamicFIFO.h"
#include <unistd.h>
#include <cstring>
CommandExecutor::CommandExecutor(const size_t maxSize):
readVec(maxSize) {
waiter.events = POLLIN;
}
ReturnValue_t CommandExecutor::load(std::string command, bool blocking, bool printOutput) {
if(state == States::PENDING) {
return COMMAND_PENDING;
}
currentCmd = command;
this->blocking = blocking;
this->printOutput = printOutput;
if(state == States::IDLE) {
state = States::COMMAND_LOADED;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CommandExecutor::execute() {
if(state == States::IDLE) {
return NO_COMMAND_LOADED_OR_PENDING;
}
else if(state == States::PENDING) {
return COMMAND_PENDING;
}
currentCmdFile = popen(currentCmd.c_str(), "r");
if(currentCmdFile == nullptr) {
lastError = errno;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(blocking) {
return executeBlocking();
}
else {
currentFd = fileno(currentCmdFile);
waiter.fd = currentFd;
}
state = States::PENDING;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CommandExecutor::close() {
if(state == States::PENDING) {
// Attempt to close process, irrespective of if it is running or not
if(currentCmdFile != nullptr) {
pclose(currentCmdFile);
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void CommandExecutor::printLastError(std::string funcName) const {
if(lastError != 0) {
sif::error << funcName << " pclose failed with code " <<
lastError << ": " << strerror(lastError) << std::endl;
}
}
void CommandExecutor::setRingBuffer(SimpleRingBuffer *ringBuffer,
DynamicFIFO<uint16_t>* sizesFifo) {
this->ringBuffer = ringBuffer;
this->sizesFifo = sizesFifo;
}
ReturnValue_t CommandExecutor::check(bool& bytesRead) {
if(blocking) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(state) {
case(States::IDLE):
case(States::COMMAND_LOADED): {
return NO_COMMAND_LOADED_OR_PENDING;
}
case(States::PENDING): {
break;
}
}
int result = poll(&waiter, 1, 0);
switch(result) {
case(0): {
return HasReturnvaluesIF::RETURN_OK;
break;
}
case(1): {
if (waiter.revents & POLLIN) {
ssize_t readBytes = read(currentFd, readVec.data(), readVec.size());
if(readBytes == 0) {
// Should not happen
sif::warning << "CommandExecutor::check: "
"No bytes read after poll event.." << std::endl;
break;
}
else if(readBytes > 0) {
bytesRead = true;
if(printOutput) {
// It is assumed the command output is line terminated
sif::info << currentCmd << " | " << readVec.data();
}
if(ringBuffer != nullptr) {
ringBuffer->writeData(reinterpret_cast<const uint8_t*>(
readVec.data()), readBytes);
}
if(sizesFifo != nullptr) {
if(not sizesFifo->full()) {
sizesFifo->insert(readBytes);
}
}
return BYTES_READ;
}
else {
// Should also not happen
sif::warning << "CommandExecutor::check: Error " << errno << ": " <<
strerror(errno) << std::endl;
}
}
else if(waiter.revents & POLLERR) {
sif::warning << "CommandExecuter::check: Poll error" << std::endl;
return COMMAND_ERROR;
}
else if(waiter.revents & POLLHUP) {
int result = pclose(currentCmdFile);
if(result != 0) {
lastError = result;
return HasReturnvaluesIF::RETURN_FAILED;
}
state = States::IDLE;
currentCmdFile = nullptr;
currentFd = 0;
return EXECUTION_FINISHED;
}
break;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void CommandExecutor::reset() {
CommandExecutor::close();
currentCmdFile = nullptr;
currentFd = 0;
state = States::IDLE;
}
int CommandExecutor::getLastError() const {
return this->lastError;
}
CommandExecutor::States CommandExecutor::getCurrentState() const {
return state;
}
ReturnValue_t CommandExecutor::executeBlocking() {
while(fgets(readVec.data(), readVec.size(), currentCmdFile) != nullptr) {
std::string output(readVec.data());
if(printOutput) {
sif::info << currentCmd << " | " << output;
}
if(ringBuffer != nullptr) {
ringBuffer->writeData(reinterpret_cast<const uint8_t*>(output.data()), output.size());
}
if(sizesFifo != nullptr) {
if(not sizesFifo->full()) {
sizesFifo->insert(output.size());
}
}
}
int result = pclose(currentCmdFile);
if(result != 0) {
lastError = result;
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
+134
View File
@@ -0,0 +1,134 @@
#ifndef FSFW_SRC_FSFW_OSAL_LINUX_COMMANDEXECUTOR_H_
#define FSFW_SRC_FSFW_OSAL_LINUX_COMMANDEXECUTOR_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/returnvalues/FwClassIds.h"
#include <poll.h>
#include <string>
#include <vector>
class SimpleRingBuffer;
template <typename T> class DynamicFIFO;
/**
* @brief Helper class to execute shell commands in blocking and non-blocking mode
* @details
* This class is able to execute processes by using the Linux popen call. It also has the
* capability of writing the read output of a process into a provided ring buffer.
*
* The executor works by first loading the command which should be executed and specifying
* whether it should be executed blocking or non-blocking. After that, execution can be started
* with the execute command. In blocking mode, the execute command will block until the command
* has finished
*/
class CommandExecutor {
public:
enum class States {
IDLE,
COMMAND_LOADED,
PENDING
};
static constexpr uint8_t CLASS_ID = CLASS_ID::LINUX_OSAL;
//! [EXPORT] : [COMMENT] Execution of the current command has finished
static constexpr ReturnValue_t EXECUTION_FINISHED =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0);
//! [EXPORT] : [COMMENT] Command is pending. This will also be returned if the user tries
//! to load another command but a command is still pending
static constexpr ReturnValue_t COMMAND_PENDING =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1);
//! [EXPORT] : [COMMENT] Some bytes have been read from the executing process
static constexpr ReturnValue_t BYTES_READ =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2);
//! [EXPORT] : [COMMENT] Command execution failed
static constexpr ReturnValue_t COMMAND_ERROR =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 3);
//! [EXPORT] : [COMMENT]
static constexpr ReturnValue_t NO_COMMAND_LOADED_OR_PENDING =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 4);
static constexpr ReturnValue_t PCLOSE_CALL_ERROR =
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 6);
/**
* Constructor. Is initialized with maximum size of internal buffer to read data from the
* executed process.
* @param maxSize
*/
CommandExecutor(const size_t maxSize);
/**
* Load a new command which should be executed
* @param command
* @param blocking
* @param printOutput
* @return
*/
ReturnValue_t load(std::string command, bool blocking, bool printOutput = true);
/**
* Execute the loaded command.
* @return
* - In blocking mode, it will return RETURN_FAILED if
* the result of the system call was not 0. The error value can be accessed using
* getLastError
* - In non-blocking mode, this call will start
* the execution and then return RETURN_OK
*/
ReturnValue_t execute();
/**
* Only used in non-blocking mode. Checks the currently running command.
* @param bytesRead Will be set to the number of bytes read, if bytes have been read
* @return
* - BYTES_READ if bytes have been read from the executing process. It is recommended to call
* check again after this
* - RETURN_OK execution is pending, but no bytes have been read from the executing process
* - RETURN_FAILED if execution has failed, error value can be accessed using getLastError
* - EXECUTION_FINISHED if the process was executed successfully
* - COMMAND_ERROR internal poll error
*/
ReturnValue_t check(bool& bytesRead);
/**
* Abort the current command. Should normally not be necessary, check can be used to find
* out whether command execution was successful
* @return RETURN_OK
*/
ReturnValue_t close();
States getCurrentState() const;
int getLastError() const;
void printLastError(std::string funcName) const;
/**
* Assign a ring buffer and a FIFO which will be filled by the executor with the output
* read from the started process
* @param ringBuffer
* @param sizesFifo
*/
void setRingBuffer(SimpleRingBuffer* ringBuffer, DynamicFIFO<uint16_t>* sizesFifo);
/**
* Reset the executor. This calls close internally and then reset the state machine so new
* commands can be loaded and executed
*/
void reset();
private:
std::string currentCmd;
bool blocking = true;
FILE* currentCmdFile = nullptr;
int currentFd = 0;
bool printOutput = true;
std::vector<char> readVec;
struct pollfd waiter {};
SimpleRingBuffer* ringBuffer = nullptr;
DynamicFIFO<uint16_t>* sizesFifo = nullptr;
States state = States::IDLE;
int lastError = 0;
ReturnValue_t executeBlocking();
};
#endif /* FSFW_SRC_FSFW_OSAL_LINUX_COMMANDEXECUTOR_H_ */
+12
View File
@@ -27,6 +27,7 @@ int Timer::setTimer(uint32_t intervalMs) {
timer.it_value.tv_nsec = (intervalMs * 1000000) % (1000000000);
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
set = true;
return timer_settime(timerId, 0, &timer, NULL);
}
@@ -43,3 +44,14 @@ int Timer::getTimer(uint32_t* remainingTimeMs){
return status;
}
bool Timer::isSet() const {
return this->set;
}
void Timer::resetTimer() {
if(not this->set) {
set = false;
}
setTimer(0);
}
+4
View File
@@ -38,7 +38,11 @@ public:
*/
int getTimer(uint32_t* remainingTimeMs);
bool isSet() const;
void resetTimer();
private:
bool set = true;
timer_t timerId;
};
+1
View File
@@ -72,6 +72,7 @@ enum: uint8_t {
PUS_SERVICE_3, //PUS3
PUS_SERVICE_9, //PUS9
FILE_SYSTEM, //FILS
LINUX_OSAL, //UXOS
HAL_SPI, //HSPI
HAL_UART, //HURT
HAL_I2C, //HI2C
+2 -2
View File
@@ -22,9 +22,9 @@ public:
* @param number
* @return
*/
static constexpr ReturnValue_t makeReturnCode(uint8_t interfaceId,
static constexpr ReturnValue_t makeReturnCode(uint8_t classId,
uint8_t number) {
return (static_cast<ReturnValue_t>(interfaceId) << 8) + number;
return (static_cast<ReturnValue_t>(classId) << 8) + number;
}
};
@@ -146,8 +146,8 @@ std::string* ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) {
#endif
int32_t charCount = sprintf(parsePosition,
"%s: | %02" SCNu32 ":%02" SCNu32 ":%02" SCNu32 ".%03" SCNu32 " | ",
this->logMessage.c_str(), loggerTime.hour,
"%s%s | %02" SCNu32 ":%02" SCNu32 ":%02" SCNu32 ".%03" SCNu32 " | ",
this->logMessage.c_str(), sif::ANSI_COLOR_RESET, loggerTime.hour,
loggerTime.minute,
loggerTime.second,
loggerTime.usecond /1000);
@@ -56,25 +56,29 @@ void fsfwPrint(sif::PrintLevel printType, const char* fmt, va_list arg) {
#endif
if (printType == sif::PrintLevel::INFO_LEVEL) {
len += sprintf(bufferPosition + len, "INFO: ");
len += sprintf(bufferPosition + len, "INFO");
}
if(printType == sif::PrintLevel::DEBUG_LEVEL) {
len += sprintf(bufferPosition + len, "DEBUG: ");
len += sprintf(bufferPosition + len, "DEBUG");
}
if(printType == sif::PrintLevel::WARNING_LEVEL) {
len += sprintf(bufferPosition + len, "WARNING: ");
len += sprintf(bufferPosition + len, "WARNING");
}
if(printType == sif::PrintLevel::ERROR_LEVEL) {
len += sprintf(bufferPosition + len, "ERROR: ");
len += sprintf(bufferPosition + len, "ERROR");
}
#if FSFW_COLORED_OUTPUT == 1
len += sprintf(bufferPosition + len, sif::ANSI_COLOR_RESET);
#endif
Clock::TimeOfDay_t now;
Clock::getDateAndTime(&now);
/*
* Log current time to terminal if desired.
*/
len += sprintf(bufferPosition + len, "| %lu:%02lu:%02lu.%03lu | ",
len += sprintf(bufferPosition + len, " | %lu:%02lu:%02lu.%03lu | ",
(unsigned long) now.hour,
(unsigned long) now.minute,
(unsigned long) now.second,
+6 -3
View File
@@ -1,5 +1,8 @@
#ifndef FRAMEWORK_TASKS_TYPEDEF_H_
#define FRAMEWORK_TASKS_TYPEDEF_H_
#ifndef FSFW_TASKS_TYPEDEF_H_
#define FSFW_TASKS_TYPEDEF_H_
#include <cstdint>
#include <cstddef>
typedef const char* TaskName;
typedef uint32_t TaskPriority;
@@ -7,4 +10,4 @@ typedef size_t TaskStackSize;
typedef double TaskPeriod;
typedef void (*TaskDeadlineMissedFunction)();
#endif /* FRAMEWORK_TASKS_TYPEDEF_H_ */
#endif /* FSFW_TASKS_TYPEDEF_H_ */
@@ -23,8 +23,10 @@ ReturnValue_t InternalUnitTester::performTests(
testserialize::test_serialization();
testmq::testMq();
testsemaph::testBinSemaph();
testsemaph::testCountingSemaph();
if(testConfig.testSemaphores) {
testsemaph::testBinSemaph();
testsemaph::testCountingSemaph();
}
testmutex::testMutex();
if(testConfig.testArrayPrinter) {
arrayprinter::testArrayPrinter();
@@ -18,6 +18,7 @@ class InternalUnitTester: public HasReturnvaluesIF {
public:
struct TestConfig {
bool testArrayPrinter = false;
bool testSemaphores = true;
};
InternalUnitTester();
@@ -1,10 +1,12 @@
#include "fsfw_tests/internal/osal/IntTestMutex.h"
#include "fsfw_tests/internal/UnittDefinitions.h"
#include "fsfw/platform.h"
#include <fsfw/ipc/MutexFactory.h>
#if defined(WIN32) || defined(UNIX)
#include <fsfw/osal/host/Mutex.h>
#if defined PLATFORM_WIN || defined PLATFORM_UNIX
#include "fsfw/osal/host/Mutex.h"
#include <thread>
#include <future>
#endif
@@ -20,7 +22,7 @@ void testmutex::testMutex() {
// timed_mutex from the C++ library specifies undefined behaviour if
// the timed mutex is locked twice from the same thread.
// TODO: we should pass a define like FSFW_OSAL_HOST to the build.
#if defined(WIN32) || defined(UNIX)
#if defined PLATFORM_WIN || defined PLATFORM_UNIX
// This calls the function from
// another thread and stores the returnvalue in a future.
auto future = std::async(&MutexIF::lockMutex, mutex, MutexIF::TimeoutType::WAITING, 1);
@@ -38,7 +40,7 @@ void testmutex::testMutex() {
}
// TODO: we should pass a define like FSFW_OSAL_HOST to the build.
#if !defined(WIN32) && !defined(UNIX)
#if !defined PLATFORM_WIN && !defined PLATFORM_UNIX
result = mutex->unlockMutex();
if(result != MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX) {
unitt::put_error(id);