added test folder
This commit is contained in:
parent
642e94621f
commit
56e93b5fd7
7
test/CMakeLists.txt
Normal file
7
test/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
target_sources(${TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
TestTask.cpp
|
||||||
|
FsfwReaderTask.cpp
|
||||||
|
FsfwExampleTask.cpp
|
||||||
|
MutexExample.cpp
|
||||||
|
)
|
264
test/FsfwExampleTask.cpp
Normal file
264
test/FsfwExampleTask.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
#include "FsfwExampleTask.h"
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
#include "commonSystemObjects.h"
|
||||||
|
#include "objects/systemObjectList.h"
|
||||||
|
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw/ipc/QueueFactory.h>
|
||||||
|
#include <fsfw/ipc/CommandMessage.h>
|
||||||
|
|
||||||
|
|
||||||
|
FsfwExampleTask::FsfwExampleTask(object_id_t objectId): SystemObject(objectId),
|
||||||
|
poolManager(this, nullptr), demoSet(this),
|
||||||
|
monitor(objectId, MONITOR_ID, gp_id_t(objectId, FsfwDemoSet::VARIABLE_LIMIT), 30, 10)
|
||||||
|
{
|
||||||
|
commandQueue = QueueFactory::instance()->createMessageQueue(10,
|
||||||
|
CommandMessage::MAX_MESSAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FsfwExampleTask::~FsfwExampleTask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) {
|
||||||
|
if(operationCode == OpCodes::DELAY_SHORT){
|
||||||
|
TaskFactory::delayTask(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this to new test controller?
|
||||||
|
ReturnValue_t result = performMonitoringDemo();
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operationCode == OpCodes::SEND_RAND_NUM) {
|
||||||
|
result = performSendOperation();
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (operationCode == OpCodes::RECEIVE_RAND_NUM) {
|
||||||
|
result = performReceiveOperation();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t FsfwExampleTask::getNextRecipient() {
|
||||||
|
switch(this->getObjectId()) {
|
||||||
|
case(objects::TEST_DUMMY_1): {
|
||||||
|
return objects::TEST_DUMMY_2;
|
||||||
|
}
|
||||||
|
case(objects::TEST_DUMMY_2): {
|
||||||
|
return objects::TEST_DUMMY_3;
|
||||||
|
}
|
||||||
|
case(objects::TEST_DUMMY_3): {
|
||||||
|
return objects::TEST_DUMMY_1;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return objects::TEST_DUMMY_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t FsfwExampleTask::getSender() {
|
||||||
|
switch(this->getObjectId()) {
|
||||||
|
case(objects::TEST_DUMMY_1): {
|
||||||
|
return objects::TEST_DUMMY_3;
|
||||||
|
}
|
||||||
|
case(objects::TEST_DUMMY_2): {
|
||||||
|
return objects::TEST_DUMMY_1;
|
||||||
|
}
|
||||||
|
case(objects::TEST_DUMMY_3): {
|
||||||
|
return objects::TEST_DUMMY_2;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return objects::TEST_DUMMY_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::initialize() {
|
||||||
|
// Get the dataset of the sender. Will be cached for later checks.
|
||||||
|
object_id_t sender = getSender();
|
||||||
|
HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
|
||||||
|
if(senderIF == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need a private copy of the previous dataset.. or we use the shared dataset.
|
||||||
|
senderSet = new FsfwDemoSet(senderIF);
|
||||||
|
if(senderSet == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return poolManager.initialize(commandQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::initializeAfterTaskCreation() {
|
||||||
|
return poolManager.initializeAfterTaskCreation();
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t FsfwExampleTask::getObjectId() const {
|
||||||
|
return SystemObject::getObjectId();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t FsfwExampleTask::getMessageQueueId(){
|
||||||
|
return commandQueue->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FsfwExampleTask::setTaskIF(PeriodicTaskIF* task){
|
||||||
|
this->task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalPoolDataSetBase* FsfwExampleTask::getDataSetHandle(sid_t sid) {
|
||||||
|
return &demoSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const {
|
||||||
|
return task->getPeriodMs();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::initializeLocalDataPool(
|
||||||
|
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||||
|
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0}));
|
||||||
|
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0}));
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
|
||||||
|
ReturnValue_t result = demoSet.variableLimit.read(
|
||||||
|
MutexIF::TimeoutType::WAITING, 20);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
/* Configuration error */
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("DummyObject::performOperation: Could not read variableLimit!\n");
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if(this->getObjectId() == objects::TEST_DUMMY_5){
|
||||||
|
if(demoSet.variableLimit.value > 20){
|
||||||
|
demoSet.variableLimit.value = 0;
|
||||||
|
}
|
||||||
|
demoSet.variableLimit.value++;
|
||||||
|
demoSet.variableLimit.commit(20);
|
||||||
|
monitor.check();
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::performSendOperation() {
|
||||||
|
object_id_t nextRecipient = getNextRecipient();
|
||||||
|
FsfwExampleTask* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
|
||||||
|
if (target == nullptr) {
|
||||||
|
/* Configuration error */
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("DummyObject::performOperation: Next recipient does not exist!\n");
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t randomNumber = rand() % 100;
|
||||||
|
CommandMessage message;
|
||||||
|
message.setParameter(randomNumber);
|
||||||
|
message.setParameter2(this->getMessageQueueId());
|
||||||
|
|
||||||
|
/* Send message using own message queue */
|
||||||
|
ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK
|
||||||
|
&& result != MessageQueueIF::FULL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result <<
|
||||||
|
std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send message without via MessageQueueSenderIF */
|
||||||
|
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
|
||||||
|
commandQueue->getId());
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK
|
||||||
|
&& result != MessageQueueIF::FULL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
demoSet.variableWrite.value = randomNumber;
|
||||||
|
result = demoSet.variableWrite.commit(20);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwExampleTask::performReceiveOperation() {
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
|
while (result != MessageQueueIF::EMPTY) {
|
||||||
|
CommandMessage receivedMessage;
|
||||||
|
result = commandQueue->receiveMessage(&receivedMessage);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK
|
||||||
|
&& result != MessageQueueIF::EMPTY) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::debug << "Receive failed with " << result << std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (result != MessageQueueIF::EMPTY) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
#if OBSW_VERBOSE_LEVEL >= 2
|
||||||
|
sif::debug << "Message Received by " << getObjectId() << " from Queue " <<
|
||||||
|
receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter() <<
|
||||||
|
" Queue " << receivedMessage.getParameter2() << std::endl;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(senderSet == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING,
|
||||||
|
20);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if(senderSet->variableRead.value != receivedMessage.getParameter()) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex <<
|
||||||
|
"0x" << senderSet->variableRead.getDataPoolId() << std::dec <<
|
||||||
|
" has wrong value." << std::endl;
|
||||||
|
sif::error << "Value: " << demoSet.variableRead.value << ", expected: " <<
|
||||||
|
receivedMessage.getParameter() << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t FsfwExampleTask::getCommandQueue() const {
|
||||||
|
return commandQueue->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDataPoolManager* FsfwExampleTask::getHkManagerHandle() {
|
||||||
|
return &poolManager;
|
||||||
|
}
|
116
test/FsfwExampleTask.h
Normal file
116
test/FsfwExampleTask.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#ifndef MISSION_DEMO_FSFWDEMOTASK_H_
|
||||||
|
#define MISSION_DEMO_FSFWDEMOTASK_H_
|
||||||
|
|
||||||
|
#include "testdefinitions/demoDefinitions.h"
|
||||||
|
|
||||||
|
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||||
|
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||||
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
#include <fsfw/monitoring/AbsLimitMonitor.h>
|
||||||
|
|
||||||
|
class PeriodicTaskIF;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This demo set shows the local data pool functionality and fixed
|
||||||
|
* timeslot capabilities of the FSFW.
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* There will be multiple demo objects. Each demo object will generate a random
|
||||||
|
* number and send that number via message queues to the next demo object
|
||||||
|
* (e.g. DUMMY_1 sends the number to DUMMY_2 etc.). The receiving object
|
||||||
|
* will check the received value against the sent value by extracting the sent
|
||||||
|
* value directly from the sender via the local data pool interface.
|
||||||
|
* If the timing is set up correctly, the values will always be the same.
|
||||||
|
*/
|
||||||
|
class FsfwExampleTask:
|
||||||
|
public ExecutableObjectIF,
|
||||||
|
public SystemObject,
|
||||||
|
public HasLocalDataPoolIF {
|
||||||
|
public:
|
||||||
|
enum OpCodes {
|
||||||
|
SEND_RAND_NUM,
|
||||||
|
RECEIVE_RAND_NUM,
|
||||||
|
DELAY_SHORT
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr uint8_t MONITOR_ID = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple constructor, only expects object ID.
|
||||||
|
* @param objectId
|
||||||
|
*/
|
||||||
|
FsfwExampleTask(object_id_t objectId);
|
||||||
|
|
||||||
|
virtual ~FsfwExampleTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The performOperation method is executed in a task.
|
||||||
|
* @details There are no restrictions for calls within this method, so any
|
||||||
|
* other member of the class can be used.
|
||||||
|
* @return Currently, the return value is ignored.
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function will be called by the global object manager
|
||||||
|
* @details
|
||||||
|
* This function will always be called before any tasks are started.
|
||||||
|
* It can also be used to return error codes in the software initialization
|
||||||
|
* process cleanly.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function will be called by the OSAL task handlers
|
||||||
|
* @details
|
||||||
|
* This function will be called before the first #performOperation
|
||||||
|
* call after the tasks have been started. It can be used if some
|
||||||
|
* initialization process requires task specific properties like
|
||||||
|
* periodic intervals (by using the PeriodicTaskIF* handle).
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will be called by the OSAL task handler. The
|
||||||
|
* task interface handle can be cached to access task specific properties.
|
||||||
|
* @param task
|
||||||
|
*/
|
||||||
|
void setTaskIF(PeriodicTaskIF* task) override;
|
||||||
|
|
||||||
|
object_id_t getObjectId() const override;
|
||||||
|
|
||||||
|
MessageQueueId_t getMessageQueueId();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
LocalDataPoolManager poolManager;
|
||||||
|
FsfwDemoSet* senderSet = nullptr;
|
||||||
|
FsfwDemoSet demoSet;
|
||||||
|
AbsLimitMonitor<int32_t> monitor;
|
||||||
|
PeriodicTaskIF* task = nullptr;
|
||||||
|
MessageQueueIF* commandQueue = nullptr;
|
||||||
|
|
||||||
|
/* HasLocalDatapoolIF overrides */
|
||||||
|
MessageQueueId_t getCommandQueue() const override;
|
||||||
|
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||||
|
uint32_t getPeriodicOperationFrequency() const override;
|
||||||
|
virtual ReturnValue_t initializeLocalDataPool(
|
||||||
|
localpool::DataPool& localDataPoolMap,
|
||||||
|
LocalDataPoolManager& poolManager) override;
|
||||||
|
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||||
|
|
||||||
|
object_id_t getNextRecipient();
|
||||||
|
object_id_t getSender();
|
||||||
|
|
||||||
|
ReturnValue_t performMonitoringDemo();
|
||||||
|
ReturnValue_t performSendOperation();
|
||||||
|
ReturnValue_t performReceiveOperation();
|
||||||
|
uint8_t execCounter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_DEMO_FSFWDEMOTASK_H_ */
|
55
test/FsfwReaderTask.cpp
Normal file
55
test/FsfwReaderTask.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "FsfwReaderTask.h"
|
||||||
|
|
||||||
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw/timemanager/Stopwatch.h>
|
||||||
|
|
||||||
|
#include <OBSWConfig.h>
|
||||||
|
|
||||||
|
|
||||||
|
FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout):
|
||||||
|
SystemObject(objectId), printoutEnabled(enablePrintout), opDivider(10),
|
||||||
|
readSet(this->getObjectId(),
|
||||||
|
gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE),
|
||||||
|
gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE),
|
||||||
|
gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) {
|
||||||
|
/* Special protection for set reading because each variable is read from a different pool */
|
||||||
|
readSet.setReadCommitProtectionBehaviour(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FsfwReaderTask::~FsfwReaderTask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() {
|
||||||
|
/* Give other task some time to set up local data pools. */
|
||||||
|
TaskFactory::delayTask(20);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
|
||||||
|
PoolReadGuard readHelper(&readSet);
|
||||||
|
|
||||||
|
uint32_t variable1 = readSet.variable1.value;
|
||||||
|
uint32_t variable2 = readSet.variable2.value;
|
||||||
|
uint32_t variable3 = readSet.variable3.value;
|
||||||
|
|
||||||
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
|
if(opDivider.checkAndIncrement() and printoutEnabled) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::info << "FsfwPeriodicTask::performOperation: Reading variables." << std::endl;
|
||||||
|
sif::info << "Variable read from demo object 1: " << variable1 << std::endl;
|
||||||
|
sif::info << "Variable read from demo object 2: " << variable2 << std::endl;
|
||||||
|
sif::info << "Variable read from demo object 3: " << variable3 << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printInfo("FsfwPeriodicTask::performOperation: Reading variables.\n\r");
|
||||||
|
sif::printInfo("Variable read from demo object 1: %d\n\r", variable1);
|
||||||
|
sif::printInfo("Variable read from demo object 2: %d\n\r", variable2);
|
||||||
|
sif::printInfo("Variable read from demo object 3: %d\n\r", variable3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(variable1 and variable2 and variable3) {};
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
24
test/FsfwReaderTask.h
Normal file
24
test/FsfwReaderTask.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef MISSION_DEMO_FSFWPERIODICTASK_H_
|
||||||
|
#define MISSION_DEMO_FSFWPERIODICTASK_H_
|
||||||
|
|
||||||
|
#include "testdefinitions/demoDefinitions.h"
|
||||||
|
|
||||||
|
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||||
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
|
||||||
|
class FsfwReaderTask: public ExecutableObjectIF, public SystemObject {
|
||||||
|
public:
|
||||||
|
FsfwReaderTask(object_id_t objectId, bool enablePrintout);
|
||||||
|
virtual ~FsfwReaderTask();
|
||||||
|
|
||||||
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool printoutEnabled = false;
|
||||||
|
PeriodicOperationDivider opDivider;
|
||||||
|
CompleteDemoReadSet readSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_DEMO_FSFWPERIODICTASK_H_ */
|
47
test/MutexExample.cpp
Normal file
47
test/MutexExample.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "MutexExample.h"
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MutexFactory.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
|
|
||||||
|
void MutexExample::example(){
|
||||||
|
MutexIF* mutex = MutexFactory::instance()->createMutex();
|
||||||
|
MutexIF* mutex2 = MutexFactory::instance()->createMutex();
|
||||||
|
|
||||||
|
ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
|
||||||
|
2 * 60 * 1000);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mutex->unlockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mutex2->unlockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
8
test/MutexExample.h
Normal file
8
test/MutexExample.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef MISSION_DEMO_MUTEXEXAMPLE_H_
|
||||||
|
#define MISSION_DEMO_MUTEXEXAMPLE_H_
|
||||||
|
|
||||||
|
namespace MutexExample {
|
||||||
|
void example();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_DEMO_MUTEXEXAMPLE_H_ */
|
77
test/TestTask.cpp
Normal file
77
test/TestTask.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "TestTask.h"
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
|
bool TestTask::oneShotAction = true;
|
||||||
|
MutexIF* TestTask::testLock = nullptr;
|
||||||
|
|
||||||
|
TestTask::TestTask(object_id_t objectId, bool periodicPrintout):
|
||||||
|
SystemObject(objectId), testMode(testModes::A),
|
||||||
|
periodicPrinout(periodicPrintout) {
|
||||||
|
if(testLock == nullptr) {
|
||||||
|
testLock = MutexFactory::instance()->createMutex();
|
||||||
|
}
|
||||||
|
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestTask::~TestTask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TestTask::performOperation(uint8_t operationCode) {
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
testLock->lockMutex(MutexIF::TimeoutType::WAITING, 20);
|
||||||
|
if(oneShotAction) {
|
||||||
|
// Add code here which should only be run once
|
||||||
|
performOneShotAction();
|
||||||
|
oneShotAction = false;
|
||||||
|
}
|
||||||
|
testLock->unlockMutex();
|
||||||
|
|
||||||
|
// Add code here which should only be run once per performOperation
|
||||||
|
performPeriodicAction();
|
||||||
|
|
||||||
|
// Add code here which should only be run on alternating cycles.
|
||||||
|
if(testMode == testModes::A) {
|
||||||
|
performActionA();
|
||||||
|
testMode = testModes::B;
|
||||||
|
}
|
||||||
|
else if(testMode == testModes::B) {
|
||||||
|
performActionB();
|
||||||
|
testMode = testModes::A;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TestTask::performOneShotAction() {
|
||||||
|
/* Everything here will only be performed once. */
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t TestTask::performPeriodicAction() {
|
||||||
|
/* This is performed each task cycle */
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
|
||||||
|
if(periodicPrinout) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::info << "TestTask::performPeriodicAction: Hello World!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printInfo("TestTask::performPeriodicAction: Hello World!\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TestTask::performActionA() {
|
||||||
|
/* This is performed each alternating task cycle */
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TestTask::performActionB() {
|
||||||
|
/* This is performed each alternating task cycle */
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
50
test/TestTask.h
Normal file
50
test/TestTask.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef MISSION_DEMO_TESTTASK_H_
|
||||||
|
#define MISSION_DEMO_TESTTASK_H_
|
||||||
|
|
||||||
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test class for general C++ testing and any other code which will not be part of the
|
||||||
|
* primary mission software.
|
||||||
|
* @details
|
||||||
|
* Should not be used for board specific tests. Instead, a derived board test class should be used.
|
||||||
|
*/
|
||||||
|
class TestTask :
|
||||||
|
public SystemObject,
|
||||||
|
public ExecutableObjectIF,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
|
public:
|
||||||
|
TestTask(object_id_t objectId, bool periodicPrintout);
|
||||||
|
virtual ~TestTask();
|
||||||
|
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ReturnValue_t performOneShotAction();
|
||||||
|
virtual ReturnValue_t performPeriodicAction();
|
||||||
|
virtual ReturnValue_t performActionA();
|
||||||
|
virtual ReturnValue_t performActionB();
|
||||||
|
|
||||||
|
enum testModes: uint8_t {
|
||||||
|
A,
|
||||||
|
B
|
||||||
|
};
|
||||||
|
|
||||||
|
testModes testMode;
|
||||||
|
bool periodicPrinout = false;
|
||||||
|
|
||||||
|
bool testFlag = false;
|
||||||
|
uint8_t counter { 1 };
|
||||||
|
uint8_t counterTrigger { 3 };
|
||||||
|
|
||||||
|
void performPusInjectorTest();
|
||||||
|
void examplePacketTest();
|
||||||
|
private:
|
||||||
|
static bool oneShotAction;
|
||||||
|
static MutexIF* testLock;
|
||||||
|
StorageManagerIF* IPCStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TESTTASK_H_ */
|
63
test/testdefinitions/demoDefinitions.h
Normal file
63
test/testdefinitions/demoDefinitions.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef MISSION_DEMO_DEMODEFINITIONS_H_
|
||||||
|
#define MISSION_DEMO_DEMODEFINITIONS_H_
|
||||||
|
|
||||||
|
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||||
|
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This demo set showcases the local data pool functionality of the
|
||||||
|
* FSFW
|
||||||
|
* @details
|
||||||
|
* Each demo object will have an own instance of this set class, which contains
|
||||||
|
* pool variables (for read and write access respectively).
|
||||||
|
*/
|
||||||
|
class FsfwDemoSet: public StaticLocalDataSet<3> {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||||
|
|
||||||
|
enum PoolIds {
|
||||||
|
VARIABLE,
|
||||||
|
VARIABLE_LIMIT
|
||||||
|
};
|
||||||
|
|
||||||
|
FsfwDemoSet(HasLocalDataPoolIF* hkOwner):
|
||||||
|
StaticLocalDataSet(hkOwner, DEMO_SET_ID) {}
|
||||||
|
|
||||||
|
lp_var_t<uint32_t> variableRead = lp_var_t<uint32_t>(sid.objectId,
|
||||||
|
PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ);
|
||||||
|
lp_var_t<uint32_t> variableWrite = lp_var_t<uint32_t>(sid.objectId,
|
||||||
|
PoolIds::VARIABLE, this, pool_rwm_t::VAR_WRITE);
|
||||||
|
lp_var_t<uint16_t> variableLimit = lp_var_t<uint16_t>(sid.objectId,
|
||||||
|
PoolIds::VARIABLE_LIMIT, this);
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This set will enable object to read the dummy variables from the dataset
|
||||||
|
* above. An example application would be a consumer object like a controller
|
||||||
|
* which reads multiple sensor values at once.
|
||||||
|
*/
|
||||||
|
class CompleteDemoReadSet: public StaticLocalDataSet<3> {
|
||||||
|
public:
|
||||||
|
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||||
|
|
||||||
|
CompleteDemoReadSet(object_id_t owner, gp_id_t variable1,
|
||||||
|
gp_id_t variable2, gp_id_t variable3):
|
||||||
|
StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)),
|
||||||
|
variable1(variable1, this, pool_rwm_t::VAR_READ),
|
||||||
|
variable2(variable2, this, pool_rwm_t::VAR_READ),
|
||||||
|
variable3(variable3, this, pool_rwm_t::VAR_READ) {}
|
||||||
|
|
||||||
|
|
||||||
|
lp_var_t<uint32_t> variable1;
|
||||||
|
lp_var_t<uint32_t> variable2;
|
||||||
|
lp_var_t<uint32_t> variable3;
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MISSION_DEMO_DEMODEFINITIONS_H_ */
|
Loading…
Reference in New Issue
Block a user