apply auto-formatter

This commit is contained in:
Robin Müller 2022-05-05 20:55:28 +02:00
parent c2a9db8ac8
commit c88a534e1c
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
42 changed files with 1667 additions and 1859 deletions

View File

@ -1,8 +1,8 @@
#ifndef COMMON_OBSWVERSION_H_ #ifndef COMMON_OBSWVERSION_H_
#define COMMON_OBSWVERSION_H_ #define COMMON_OBSWVERSION_H_
#define FSFW_EXAMPLE_VERSION 1 #define FSFW_EXAMPLE_VERSION 1
#define FSFW_EXAMPLE_SUBVERSION 4 #define FSFW_EXAMPLE_SUBVERSION 4
#define FSFW_EXAMPLE_REVISION 0 #define FSFW_EXAMPLE_REVISION 0
#endif /* COMMON_OBSWVERSION_H_ */ #endif /* COMMON_OBSWVERSION_H_ */

View File

@ -4,10 +4,10 @@
#include "fsfw/returnvalues/FwClassIds.h" #include "fsfw/returnvalues/FwClassIds.h"
namespace CLASS_ID { namespace CLASS_ID {
enum commonClassIds: uint8_t { enum commonClassIds : uint8_t {
COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT, COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT,
DUMMY_HANDLER, //DDH DUMMY_HANDLER, // DDH
COMMON_CLASS_ID_END // [EXPORT] : [END] COMMON_CLASS_ID_END // [EXPORT] : [END]
}; };
} }

View File

@ -1,83 +1,67 @@
#include "pollingsequence/pollingSequenceFactory.h"
#include "objects/systemObjectList.h"
#include "example/test/FsfwExampleTask.h"
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h> #include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h> #include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include "example/test/FsfwExampleTask.h"
#include "objects/systemObjectList.h"
#include "pollingsequence/pollingSequenceFactory.h"
ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF* thisSequence) { ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF* thisSequence) {
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0, thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
FsfwExampleTask::OpCodes::SEND_RAND_NUM); thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0, thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
FsfwExampleTask::OpCodes::SEND_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0,
FsfwExampleTask::OpCodes::SEND_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.2, thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.2,
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM); FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.2, thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.2,
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM); FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.2, thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.2,
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM); FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.5, thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
FsfwExampleTask::OpCodes::DELAY_SHORT); thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.5, thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
FsfwExampleTask::OpCodes::DELAY_SHORT);
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.5,
FsfwExampleTask::OpCodes::DELAY_SHORT);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} } else {
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl; sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl;
#else #else
sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n"); sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF *thisSequence) { ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF* thisSequence) {
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.3 * length, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.3 * length, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.3 * length, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.3 * length, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.45 * length, thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.45 * length, DeviceHandlerIF::GET_WRITE);
DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.45 * length, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.45 * length,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.6 * length, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.6 * length, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.6 * length, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.6 * length, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} } else {
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl; sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl;
#else #else
sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n"); sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }

View File

@ -7,12 +7,11 @@
* The subsystem IDs will be part of the event IDs used throughout the FSFW. * The subsystem IDs will be part of the event IDs used throughout the FSFW.
*/ */
namespace SUBSYSTEM_ID { namespace SUBSYSTEM_ID {
enum commonSubsystemId: uint8_t { enum commonSubsystemId : uint8_t {
COMMON_SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE, COMMON_SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
TEST_TASK_ID = 105, TEST_TASK_ID = 105,
COMMON_SUBSYSTEM_ID_END COMMON_SUBSYSTEM_ID_END
}; };
} }
#endif /* COMMON_CONFIG_COMMONSUBSYSTEMIDS_H_ */ #endif /* COMMON_CONFIG_COMMONSUBSYSTEMIDS_H_ */

View File

@ -1,40 +1,39 @@
#ifndef COMMON_COMMONSYSTEMOBJECTS_H_ #ifndef COMMON_COMMONSYSTEMOBJECTS_H_
#define COMMON_COMMONSYSTEMOBJECTS_H_ #define COMMON_COMMONSYSTEMOBJECTS_H_
#include <cstdint>
#include <fsfw/objectmanager/frameworkObjects.h> #include <fsfw/objectmanager/frameworkObjects.h>
#include <cstdint>
namespace objects { namespace objects {
enum commonObjects: object_id_t { enum commonObjects : object_id_t {
/* 0x41 ('A') for Assemblies */ /* 0x41 ('A') for Assemblies */
TEST_ASSEMBLY = 0x4100CAFE, TEST_ASSEMBLY = 0x4100CAFE,
/* 0x43 ('C') for Controllers */ /* 0x43 ('C') for Controllers */
TEST_CONTROLLER = 0x4301CAFE, TEST_CONTROLLER = 0x4301CAFE,
/* 0x44 ('D') for Device Handlers */ /* 0x44 ('D') for Device Handlers */
TEST_DEVICE_HANDLER_0 = 0x4401AFFE, TEST_DEVICE_HANDLER_0 = 0x4401AFFE,
TEST_DEVICE_HANDLER_1 = 0x4402AFFE, TEST_DEVICE_HANDLER_1 = 0x4402AFFE,
/* 0x49 ('I') for Communication Interfaces */ /* 0x49 ('I') for Communication Interfaces */
TEST_ECHO_COM_IF = 0x4900AFFE, TEST_ECHO_COM_IF = 0x4900AFFE,
/* 0x63 ('C') for core objects */ /* 0x63 ('C') for core objects */
CCSDS_DISTRIBUTOR = 0x63000000, CCSDS_DISTRIBUTOR = 0x63000000,
PUS_DISTRIBUTOR = 0x63000001, PUS_DISTRIBUTOR = 0x63000001,
TM_FUNNEL = 0x63000002, TM_FUNNEL = 0x63000002,
/* 0x74 ('t') for test and example objects */ /* 0x74 ('t') for test and example objects */
TEST_TASK = 0x7400CAFE, TEST_TASK = 0x7400CAFE,
TEST_DUMMY_1 = 0x74000001, TEST_DUMMY_1 = 0x74000001,
TEST_DUMMY_2 = 0x74000002, TEST_DUMMY_2 = 0x74000002,
TEST_DUMMY_3= 0x74000003, TEST_DUMMY_3 = 0x74000003,
TEST_DUMMY_4 = 0x74000004, TEST_DUMMY_4 = 0x74000004,
TEST_DUMMY_5 = 0x74000005, TEST_DUMMY_5 = 0x74000005,
}; };
} }
#endif /* COMMON_COMMONSYSTEMOBJECTS_H_ */ #endif /* COMMON_COMMONSYSTEMOBJECTS_H_ */

View File

@ -1,217 +1,220 @@
#include <fsfw/datapool/PoolReadGuard.h>
#include "FsfwTestController.h" #include "FsfwTestController.h"
#include <fsfw/datapool/PoolReadGuard.h>
FsfwTestController::FsfwTestController(object_id_t objectId, object_id_t device0, FsfwTestController::FsfwTestController(object_id_t objectId, object_id_t device0,
object_id_t device1, uint8_t verboseLevel): object_id_t device1, uint8_t verboseLevel)
TestController(objectId, objects::NO_OBJECT, 5), device0Id(device0), : TestController(objectId, objects::NO_OBJECT, 5),
device1Id(device1), deviceDataset0(device0), deviceDataset1(device1) { device0Id(device0),
device1Id(device1),
deviceDataset0(device0),
deviceDataset1(device1) {}
FsfwTestController::~FsfwTestController() {}
ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage* message) {
return HasReturnvaluesIF::RETURN_OK;
} }
FsfwTestController::~FsfwTestController() { ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
} return HasReturnvaluesIF::RETURN_OK;
ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage *message) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
return HasReturnvaluesIF::RETURN_OK;
} }
void FsfwTestController::performControlOperation() { void FsfwTestController::performControlOperation() {
// We will trace variables if we received an update notification or snapshots // We will trace variables if we received an update notification or snapshots
if (verboseLevel >= 1) { if (verboseLevel >= 1) {
if(not traceVariable) { if (not traceVariable) {
return; return;
}
switch(currentTraceType) {
case(NONE): {
break;
}
case(TRACE_DEV_0_UINT8): {
if(traceCounter == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Tracing finished" << std::endl;
#else
sif::printInfo("Tracing finished\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
traceVariable = false;
traceCounter = traceCycles;
currentTraceType = TraceTypes::NONE;
break;
}
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Tracing device 0 variable 0 (UINT8), current value: " <<
static_cast<int>(deviceDataset0.testUint8Var.value) << std::endl;
#else
sif::printInfo("Tracing device 0 variable 0 (UINT8), current value: %d\n",
deviceDataset0.testUint8Var.value);
#endif
traceCounter--;
break;
}
case(TRACE_DEV_0_VECTOR): {
break;
}
}
} }
switch (currentTraceType) {
case (NONE): {
break;
}
case (TRACE_DEV_0_UINT8): {
if (traceCounter == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Tracing finished" << std::endl;
#else
sif::printInfo("Tracing finished\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
traceVariable = false;
traceCounter = traceCycles;
currentTraceType = TraceTypes::NONE;
break;
}
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Tracing device 0 variable 0 (UINT8), current value: "
<< static_cast<int>(deviceDataset0.testUint8Var.value) << std::endl;
#else
sif::printInfo("Tracing device 0 variable 0 (UINT8), current value: %d\n",
deviceDataset0.testUint8Var.value);
#endif
traceCounter--;
break;
}
case (TRACE_DEV_0_VECTOR): {
break;
}
}
}
} }
ReturnValue_t FsfwTestController::initializeAfterTaskCreation() { ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
namespace td = testdevice; namespace td = testdevice;
ReturnValue_t result = TestController::initializeAfterTaskCreation(); ReturnValue_t result = TestController::initializeAfterTaskCreation();
if(result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
HasLocalDataPoolIF* device0 = ObjectManager::instance()->get<HasLocalDataPoolIF>(
deviceDataset0.getCreatorObjectId());
if(device0 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 0 "
"handle invalid!" << std::endl;
#else
sif::printWarning("TestController::initializeAfterTaskCreation: Test device handler 0 "
"handle invalid!");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ProvidesDataPoolSubscriptionIF* subscriptionIF = device0->getSubscriptionInterface();
if(subscriptionIF != nullptr) {
/* For DEVICE_0, we only subscribe for notifications */
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(),
getCommandQueue(), false);
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID,
getObjectId(), getCommandQueue(), false);
}
HasLocalDataPoolIF* device1 = ObjectManager::instance()->get<HasLocalDataPoolIF>(
deviceDataset0.getCreatorObjectId());
if(device1 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 1 "
"handle invalid!" << std::endl;
#else
sif::printWarning("TestController::initializeAfterTaskCreation: Test device handler 1 "
"handle invalid!");
#endif
}
subscriptionIF = device1->getSubscriptionInterface();
if(subscriptionIF != nullptr) {
/* For DEVICE_1, we will subscribe for snapshots */
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(),
getCommandQueue(), true);
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID,
getObjectId(), getCommandQueue(), true);
}
return result; return result;
}
HasLocalDataPoolIF* device0 =
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
if (device0 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 0 "
"handle invalid!"
<< std::endl;
#else
sif::printWarning(
"TestController::initializeAfterTaskCreation: Test device handler 0 "
"handle invalid!");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ProvidesDataPoolSubscriptionIF* subscriptionIF = device0->getSubscriptionInterface();
if (subscriptionIF != nullptr) {
/* For DEVICE_0, we only subscribe for notifications */
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(),
false);
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID, getObjectId(),
getCommandQueue(), false);
}
HasLocalDataPoolIF* device1 =
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
if (device1 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 1 "
"handle invalid!"
<< std::endl;
#else
sif::printWarning(
"TestController::initializeAfterTaskCreation: Test device handler 1 "
"handle invalid!");
#endif
}
subscriptionIF = device1->getSubscriptionInterface();
if (subscriptionIF != nullptr) {
/* For DEVICE_1, we will subscribe for snapshots */
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(),
true);
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID, getObjectId(),
getCommandQueue(), true);
}
return result;
} }
LocalPoolDataSetBase* FsfwTestController::getDataSetHandle(sid_t sid) { LocalPoolDataSetBase* FsfwTestController::getDataSetHandle(sid_t sid) { return nullptr; }
return nullptr;
}
ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode, ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) { uint32_t* msToReachTheMode) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId, void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId,
bool* clearMessage) { bool* clearMessage) {
using namespace std; using namespace std;
if (verboseLevel >= 1) { if (verboseLevel >= 1) {
char const* printout = nullptr; char const* printout = nullptr;
if(storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == storeId::INVALID_STORE_ADDRESS) {
printout = "Notification"; printout = "Notification";
} } else {
else { printout = "Snapshot";
printout = "Snapshot"; }
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "FsfwTestController::handleChangedDataset: " << printout << " update" sif::info << "FsfwTestController::handleChangedDataset: " << printout
"from object ID " << setw(8) << setfill('0') << hex << sid.objectId << << " update"
" and set ID " << sid.ownerSetId << dec << setfill(' ') << endl; "from object ID "
<< setw(8) << setfill('0') << hex << sid.objectId << " and set ID " << sid.ownerSetId
<< dec << setfill(' ') << endl;
#else #else
sif::printInfo("FsfwTestController::handleChangedPoolVariable: %s update from" sif::printInfo(
"object ID 0x%08x and set ID %lu\n", printout, sid.objectId, sid.ownerSetId); "FsfwTestController::handleChangedPoolVariable: %s update from"
"object ID 0x%08x and set ID %lu\n",
printout, sid.objectId, sid.ownerSetId);
#endif #endif
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == storeId::INVALID_STORE_ADDRESS) {
if(sid.objectId == device0Id) { if (sid.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec); PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec);
float floatVec[3]; float floatVec[3];
floatVec[0] = deviceDataset0.testFloat3Vec.value[0]; floatVec[0] = deviceDataset0.testFloat3Vec.value[0];
floatVec[1] = deviceDataset0.testFloat3Vec.value[1]; floatVec[1] = deviceDataset0.testFloat3Vec.value[1];
floatVec[2] = deviceDataset0.testFloat3Vec.value[2]; floatVec[2] = deviceDataset0.testFloat3Vec.value[2];
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Current float vector (3) values: [" << floatVec[0] << ", " << sif::info << "Current float vector (3) values: [" << floatVec[0] << ", " << floatVec[1]
floatVec[1] << ", " << floatVec[2] << "]" << std::endl; << ", " << floatVec[2] << "]" << std::endl;
#else #else
sif::printInfo("Current float vector (3) values: [%f, %f, %f]\n", sif::printInfo("Current float vector (3) values: [%f, %f, %f]\n", floatVec[0], floatVec[1],
floatVec[0], floatVec[1], floatVec[2]); floatVec[2]);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }
}
} }
}
/* We will trace the variables for snapshots and update notifications */ /* We will trace the variables for snapshots and update notifications */
if(not traceVariable) { if (not traceVariable) {
traceVariable = true; traceVariable = true;
traceCounter = traceCycles; traceCounter = traceCycles;
currentTraceType = TraceTypes::TRACE_DEV_0_VECTOR; currentTraceType = TraceTypes::TRACE_DEV_0_VECTOR;
} }
} }
void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId, void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) { bool* clearMessage) {
using namespace std;
using namespace std; if (verboseLevel >= 1) {
char const* printout = nullptr;
if (verboseLevel >= 1) { if (storeId == storeId::INVALID_STORE_ADDRESS) {
char const* printout = nullptr; printout = "Notification";
if (storeId == storeId::INVALID_STORE_ADDRESS) { } else {
printout = "Notification"; printout = "Snapshot";
}
else {
printout = "Snapshot";
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestController::handleChangedPoolVariable: " << printout << " update from object "
"ID 0x" << setw(8) << setfill('0') << hex << globPoolId.objectId <<
" and local pool ID " << globPoolId.localPoolId << dec << setfill(' ') << endl;
#else
sif::printInfo("TestController::handleChangedPoolVariable: %s update from object ID 0x%08x and "
"local pool ID %lu\n", printout, globPoolId.objectId, globPoolId.localPoolId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if (storeId == storeId::INVALID_STORE_ADDRESS) {
if(globPoolId.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Current test variable 0 (UINT8) value: " << static_cast<int>(
deviceDataset0.testUint8Var.value) << std::endl;
#else
sif::printInfo("Current test variable 0 (UINT8) value %d\n",
deviceDataset0.testUint8Var.value);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
}
} }
/* We will trace the variables for snapshots and update notifications */ #if FSFW_CPP_OSTREAM_ENABLED == 1
if(not traceVariable) { sif::info << "TestController::handleChangedPoolVariable: " << printout
traceVariable = true; << " update from object "
traceCounter = traceCycles; "ID 0x"
currentTraceType = TraceTypes::TRACE_DEV_0_UINT8; << setw(8) << setfill('0') << hex << globPoolId.objectId << " and local pool ID "
<< globPoolId.localPoolId << dec << setfill(' ') << endl;
#else
sif::printInfo(
"TestController::handleChangedPoolVariable: %s update from object ID 0x%08x and "
"local pool ID %lu\n",
printout, globPoolId.objectId, globPoolId.localPoolId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if (storeId == storeId::INVALID_STORE_ADDRESS) {
if (globPoolId.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Current test variable 0 (UINT8) value: "
<< static_cast<int>(deviceDataset0.testUint8Var.value) << std::endl;
#else
sif::printInfo("Current test variable 0 (UINT8) value %d\n",
deviceDataset0.testUint8Var.value);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
} }
}
/* We will trace the variables for snapshots and update notifications */
if (not traceVariable) {
traceVariable = true;
traceCounter = traceCycles;
currentTraceType = TraceTypes::TRACE_DEV_0_UINT8;
}
} }

View File

@ -4,50 +4,41 @@
#include "fsfw/controller/ExtendedControllerBase.h" #include "fsfw/controller/ExtendedControllerBase.h"
#include "fsfw_tests/integration/controller/TestController.h" #include "fsfw_tests/integration/controller/TestController.h"
class FsfwTestController: public TestController { class FsfwTestController : public TestController {
public: public:
FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1, FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1,
uint8_t verboseLevel = 0); uint8_t verboseLevel = 0);
virtual~ FsfwTestController(); virtual ~FsfwTestController();
ReturnValue_t handleCommandMessage(CommandMessage *message) override; ReturnValue_t handleCommandMessage(CommandMessage* message) override;
/** /**
* Periodic helper from ControllerBase, implemented by child class. * Periodic helper from ControllerBase, implemented by child class.
*/ */
void performControlOperation() override; void performControlOperation() override;
private: private:
object_id_t device0Id;
object_id_t device1Id;
testdevice::TestDataSet deviceDataset0;
testdevice::TestDataSet deviceDataset1;
object_id_t device0Id; uint8_t verboseLevel = 0;
object_id_t device1Id; bool traceVariable = false;
testdevice::TestDataSet deviceDataset0; uint8_t traceCycles = 5;
testdevice::TestDataSet deviceDataset1; uint8_t traceCounter = traceCycles;
uint8_t verboseLevel = 0; enum TraceTypes { NONE, TRACE_DEV_0_UINT8, TRACE_DEV_0_VECTOR };
bool traceVariable = false; TraceTypes currentTraceType = TraceTypes::NONE;
uint8_t traceCycles = 5;
uint8_t traceCounter = traceCycles;
enum TraceTypes {
NONE,
TRACE_DEV_0_UINT8,
TRACE_DEV_0_VECTOR
};
TraceTypes currentTraceType = TraceTypes::NONE;
ReturnValue_t initializeAfterTaskCreation() override;
void handleChangedDataset(sid_t sid, store_address_t storeId,
bool* clearMessage) override;
void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override ;
ReturnValue_t initializeAfterTaskCreation() override;
void handleChangedDataset(sid_t sid, store_address_t storeId, bool* clearMessage) override;
void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
}; };
#endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */ #endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */

View File

@ -1,22 +1,10 @@
#include "GenericFactory.h" #include "GenericFactory.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/FSFW.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
#include "objects/systemObjectList.h"
#include "example/utility/TmFunnel.h"
#include "example/test/FsfwExampleTask.h" #include "example/test/FsfwExampleTask.h"
#include "example/test/FsfwReaderTask.h" #include "example/test/FsfwReaderTask.h"
#include "example/utility/TmFunnel.h"
#include "fsfw_tests/internal/InternalUnitTester.h" #include "fsfw/FSFW.h"
#include "fsfw_tests/integration/assemblies/TestAssembly.h"
#include "fsfw_tests/integration/devices/TestCookie.h"
#include "fsfw_tests/integration/devices/TestDeviceHandler.h"
#include "fsfw_tests/integration/devices/TestEchoComIF.h"
#include "fsfw_tests/integration/controller/TestController.h"
#include "fsfw/devicehandlers/CookieIF.h" #include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/events/EventManager.h" #include "fsfw/events/EventManager.h"
#include "fsfw/health/HealthTable.h" #include "fsfw/health/HealthTable.h"
@ -34,126 +22,125 @@
#include "fsfw/tcdistribution/PUSDistributor.h" #include "fsfw/tcdistribution/PUSDistributor.h"
#include "fsfw/timemanager/TimeStamper.h" #include "fsfw/timemanager/TimeStamper.h"
#include "fsfw/tmtcpacket/pus/tm.h" #include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw_tests/integration/assemblies/TestAssembly.h"
#include "fsfw_tests/integration/controller/TestController.h"
#include "fsfw_tests/integration/devices/TestCookie.h"
#include "fsfw_tests/integration/devices/TestDeviceHandler.h"
#include "fsfw_tests/integration/devices/TestEchoComIF.h"
#include "fsfw_tests/internal/InternalUnitTester.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
void ObjectFactory::produceGenericObjects() { void ObjectFactory::produceGenericObjects() {
#if OBSW_ADD_CORE_COMPONENTS == 1 #if OBSW_ADD_CORE_COMPONENTS == 1
/* Framework objects */ /* Framework objects */
new EventManager(objects::EVENT_MANAGER); new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE); new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new TimeStamper(objects::TIME_STAMPER); new TimeStamper(objects::TIME_STAMPER);
new CCSDSDistributor(apid::APID, objects::CCSDS_DISTRIBUTOR); new CCSDSDistributor(apid::APID, objects::CCSDS_DISTRIBUTOR);
new PUSDistributor(apid::APID, objects::PUS_DISTRIBUTOR, new PUSDistributor(apid::APID, objects::PUS_DISTRIBUTOR, objects::CCSDS_DISTRIBUTOR);
objects::CCSDS_DISTRIBUTOR); new TmFunnel(objects::TM_FUNNEL);
new TmFunnel(objects::TM_FUNNEL);
#endif /* OBSW_ADD_CORE_COMPONENTS == 1 */ #endif /* OBSW_ADD_CORE_COMPONENTS == 1 */
/* PUS stack */ /* PUS stack */
#if OBSW_ADD_PUS_STACK == 1 #if OBSW_ADD_PUS_STACK == 1
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, apid::APID,
apid::APID, pus::PUS_SERVICE_1, objects::TM_FUNNEL, 5); pus::PUS_SERVICE_1, objects::TM_FUNNEL, 5);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, apid::APID, pus::PUS_SERVICE_2, 3,
apid::APID, pus::PUS_SERVICE_2, 3, 10); 10);
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::APID, pus::PUS_SERVICE_3); new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::APID, pus::PUS_SERVICE_3);
new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING, new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING, apid::APID, pus::PUS_SERVICE_5,
apid::APID, pus::PUS_SERVICE_5, 50); 50);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, apid::APID,
apid::APID, pus::PUS_SERVICE_8, 3, 10); pus::PUS_SERVICE_8, 3, 10);
new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT, apid::APID, new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT, apid::APID, pus::PUS_SERVICE_9);
pus::PUS_SERVICE_9); new Service17Test(objects::PUS_SERVICE_17_TEST, apid::APID, pus::PUS_SERVICE_17);
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::APID, new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::APID,
pus::PUS_SERVICE_17); pus::PUS_SERVICE_20);
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::APID, new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::APID,
pus::PUS_SERVICE_20); pus::PUS_SERVICE_200);
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT,
apid::APID, pus::PUS_SERVICE_200);
#endif /* OBSW_ADD_PUS_STACK == 1 */ #endif /* OBSW_ADD_PUS_STACK == 1 */
#if OBSW_ADD_TASK_EXAMPLE == 1 #if OBSW_ADD_TASK_EXAMPLE == 1
/* Demo objects */ /* Demo objects */
new FsfwExampleTask(objects::TEST_DUMMY_1); new FsfwExampleTask(objects::TEST_DUMMY_1);
new FsfwExampleTask(objects::TEST_DUMMY_2); new FsfwExampleTask(objects::TEST_DUMMY_2);
new FsfwExampleTask(objects::TEST_DUMMY_3); new FsfwExampleTask(objects::TEST_DUMMY_3);
bool enablePrintout = false;
bool enablePrintout = false;
#if OBSW_TASK_EXAMPLE_PRINTOUT == 1 #if OBSW_TASK_EXAMPLE_PRINTOUT == 1
enablePrintout = true; enablePrintout = true;
#endif #endif
new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout); new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout);
#endif /* OBSW_ADD_TASK_EXAMPLE == 1 */ #endif /* OBSW_ADD_TASK_EXAMPLE == 1 */
#if OBSW_ADD_DEVICE_HANDLER_DEMO == 1 #if OBSW_ADD_DEVICE_HANDLER_DEMO == 1
#if OBSW_DEVICE_HANDLER_PRINTOUT == 1 #if OBSW_DEVICE_HANDLER_PRINTOUT == 1
bool enableInfoPrintout = true; bool enableInfoPrintout = true;
#else #else
bool enableInfoPrintout = false; bool enableInfoPrintout = false;
#endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */ #endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */
/* Demo device handler object */ /* Demo device handler object */
size_t expectedMaxReplyLen = 64; size_t expectedMaxReplyLen = 64;
CookieIF* testCookie = new TestCookie( CookieIF* testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0),
static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0), expectedMaxReplyLen); expectedMaxReplyLen);
new TestEchoComIF(objects::TEST_ECHO_COM_IF); new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie, new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout); testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1), testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1),
expectedMaxReplyLen); expectedMaxReplyLen);
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie, new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout); testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);
new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0, new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0,
objects::TEST_DEVICE_HANDLER_1); objects::TEST_DEVICE_HANDLER_1);
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */ #endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
/* Demo controller object */
/* Demo controller object */
#if OBSW_ADD_CONTROLLER_DEMO == 1 #if OBSW_ADD_CONTROLLER_DEMO == 1
#if OBSW_CONTROLLER_PRINTOUT == 1 #if OBSW_CONTROLLER_PRINTOUT == 1
#endif #endif
new TestController(objects::TEST_CONTROLLER, objects::NO_OBJECT); new TestController(objects::TEST_CONTROLLER, objects::NO_OBJECT);
#endif /* OBSW_ADD_CONTROLLER_DEMO == 1 */ #endif /* OBSW_ADD_CONTROLLER_DEMO == 1 */
#if OBSW_PERFORM_INTERNAL_UNITTEST == 1 #if OBSW_PERFORM_INTERNAL_UNITTEST == 1
InternalUnitTester::TestConfig testCfg; InternalUnitTester::TestConfig testCfg;
testCfg.testArrayPrinter = false; testCfg.testArrayPrinter = false;
#if defined FSFW_OSAL_HOST #if defined FSFW_OSAL_HOST
// Not implemented yet for hosted OSAL (requires C++20) // Not implemented yet for hosted OSAL (requires C++20)
testCfg.testSemaphores = false; testCfg.testSemaphores = false;
#endif #endif
InternalUnitTester unittester; InternalUnitTester unittester;
unittester.performTests(testCfg); unittester.performTests(testCfg);
#endif /* OBSW_PERFORM_INTERNAL_UNITTEST == 1 */ #endif /* OBSW_PERFORM_INTERNAL_UNITTEST == 1 */
} }
void Factory::setStaticFrameworkObjectIds() { void Factory::setStaticFrameworkObjectIds() {
MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
TmFunnel::downlinkDestination = objects::DOWNLINK_DESTINATION; TmFunnel::downlinkDestination = objects::DOWNLINK_DESTINATION;
// No storage object for now. // No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT; TmFunnel::storageDestination = objects::NO_OBJECT;
PusServiceBase::packetSource = objects::PUS_DISTRIBUTOR; PusServiceBase::packetSource = objects::PUS_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL; PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR; CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL; CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
} }

View File

@ -11,7 +11,6 @@ namespace ObjectFactory {
*/ */
void produceGenericObjects(); void produceGenericObjects();
} } // namespace ObjectFactory
#endif /* MISSION_CORE_GENERICFACTORY_H_ */ #endif /* MISSION_CORE_GENERICFACTORY_H_ */

View File

@ -3,10 +3,8 @@
//#include "fsfw_tests/integration/TestDeviceHandler.h" //#include "fsfw_tests/integration/TestDeviceHandler.h"
// //
//class FsfwTestDeviceHandler: public TestDeviceHandler { // class FsfwTestDeviceHandler: public TestDeviceHandler {
// //
//}; //};
#endif /* EXAMPLE_COMMON_DEVICES_TESTDEVICEHANDLER_H_ */ #endif /* EXAMPLE_COMMON_DEVICES_TESTDEVICEHANDLER_H_ */

View File

@ -1,264 +1,238 @@
#include "FsfwExampleTask.h" #include "FsfwExampleTask.h"
#include <fsfw/ipc/CommandMessage.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tasks/TaskFactory.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "commonSystemObjects.h" #include "commonSystemObjects.h"
#include "objects/systemObjectList.h" #include "objects/systemObjectList.h"
#include <fsfw/serviceinterface/ServiceInterface.h> FsfwExampleTask::FsfwExampleTask(object_id_t objectId)
#include <fsfw/objectmanager/ObjectManager.h> : SystemObject(objectId),
#include <fsfw/tasks/TaskFactory.h> poolManager(this, nullptr),
#include <fsfw/ipc/QueueFactory.h> demoSet(this),
#include <fsfw/ipc/CommandMessage.h> monitor(objectId, MONITOR_ID, gp_id_t(objectId, FsfwDemoSet::VARIABLE_LIMIT), 30, 10) {
commandQueue = QueueFactory::instance()->createMessageQueue(10, CommandMessage::MAX_MESSAGE_SIZE);
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() { FsfwExampleTask::~FsfwExampleTask() {}
}
ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) { ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) {
if(operationCode == OpCodes::DELAY_SHORT){ if (operationCode == OpCodes::DELAY_SHORT) {
TaskFactory::delayTask(5); 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;
} }
}
// TODO: Move this to new test controller? if (operationCode == OpCodes::RECEIVE_RAND_NUM) {
ReturnValue_t result = performMonitoringDemo(); result = performReceiveOperation();
if(result != HasReturnvaluesIF::RETURN_OK) { }
return result;
}
if (operationCode == OpCodes::SEND_RAND_NUM) { return 0;
result = performSendOperation();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
if (operationCode == OpCodes::RECEIVE_RAND_NUM) {
result = performReceiveOperation();
}
return 0;
} }
object_id_t FsfwExampleTask::getNextRecipient() { object_id_t FsfwExampleTask::getNextRecipient() {
switch(this->getObjectId()) { switch (this->getObjectId()) {
case(objects::TEST_DUMMY_1): { case (objects::TEST_DUMMY_1): {
return objects::TEST_DUMMY_2; return objects::TEST_DUMMY_2;
} }
case(objects::TEST_DUMMY_2): { case (objects::TEST_DUMMY_2): {
return objects::TEST_DUMMY_3; return objects::TEST_DUMMY_3;
} }
case(objects::TEST_DUMMY_3): { case (objects::TEST_DUMMY_3): {
return objects::TEST_DUMMY_1; return objects::TEST_DUMMY_1;
} }
default: default:
return objects::TEST_DUMMY_1; return objects::TEST_DUMMY_1;
} }
} }
object_id_t FsfwExampleTask::getSender() { object_id_t FsfwExampleTask::getSender() {
switch(this->getObjectId()) { switch (this->getObjectId()) {
case(objects::TEST_DUMMY_1): { case (objects::TEST_DUMMY_1): {
return objects::TEST_DUMMY_3; return objects::TEST_DUMMY_3;
} }
case(objects::TEST_DUMMY_2): { case (objects::TEST_DUMMY_2): {
return objects::TEST_DUMMY_1; return objects::TEST_DUMMY_1;
} }
case(objects::TEST_DUMMY_3): { case (objects::TEST_DUMMY_3): {
return objects::TEST_DUMMY_2; return objects::TEST_DUMMY_2;
} }
default: default:
return objects::TEST_DUMMY_1; return objects::TEST_DUMMY_1;
} }
} }
ReturnValue_t FsfwExampleTask::initialize() { ReturnValue_t FsfwExampleTask::initialize() {
// Get the dataset of the sender. Will be cached for later checks. // Get the dataset of the sender. Will be cached for later checks.
object_id_t sender = getSender(); object_id_t sender = getSender();
HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender); HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
if(senderIF == nullptr) { if (senderIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl; sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl;
#else #else
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n"); sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
// we need a private copy of the previous dataset.. or we use the shared dataset. // we need a private copy of the previous dataset.. or we use the shared dataset.
senderSet = new FsfwDemoSet(senderIF); senderSet = new FsfwDemoSet(senderIF);
if(senderSet == nullptr) { if (senderSet == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl; sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl;
#else #else
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n"); sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return poolManager.initialize(commandQueue); return poolManager.initialize(commandQueue);
} }
ReturnValue_t FsfwExampleTask::initializeAfterTaskCreation() { ReturnValue_t FsfwExampleTask::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation(); return poolManager.initializeAfterTaskCreation();
} }
object_id_t FsfwExampleTask::getObjectId() const { object_id_t FsfwExampleTask::getObjectId() const { return SystemObject::getObjectId(); }
return SystemObject::getObjectId();
}
MessageQueueId_t FsfwExampleTask::getMessageQueueId(){ MessageQueueId_t FsfwExampleTask::getMessageQueueId() { return commandQueue->getId(); }
return commandQueue->getId();
}
void FsfwExampleTask::setTaskIF(PeriodicTaskIF* task){ void FsfwExampleTask::setTaskIF(PeriodicTaskIF* task) { this->task = task; }
this->task = task;
}
LocalPoolDataSetBase* FsfwExampleTask::getDataSetHandle(sid_t sid) { LocalPoolDataSetBase* FsfwExampleTask::getDataSetHandle(sid_t sid) { return &demoSet; }
return &demoSet;
}
uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const { uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const { return task->getPeriodMs(); }
return task->getPeriodMs();
}
ReturnValue_t FsfwExampleTask::initializeLocalDataPool( ReturnValue_t FsfwExampleTask::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0})); localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0})); localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0}));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t FsfwExampleTask::performMonitoringDemo() { ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
ReturnValue_t result = demoSet.variableLimit.read( ReturnValue_t result = demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20);
MutexIF::TimeoutType::WAITING, 20); if (result != HasReturnvaluesIF::RETURN_OK) {
if(result != HasReturnvaluesIF::RETURN_OK) { /* Configuration error */
/* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl; sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl;
#else #else
sif::printError("DummyObject::performOperation: Could not read variableLimit!\n"); sif::printError("DummyObject::performOperation: Could not read variableLimit!\n");
#endif #endif
return result; return result;
}
if (this->getObjectId() == objects::TEST_DUMMY_5) {
if (demoSet.variableLimit.value > 20) {
demoSet.variableLimit.value = 0;
} }
if(this->getObjectId() == objects::TEST_DUMMY_5){ demoSet.variableLimit.value++;
if(demoSet.variableLimit.value > 20){ demoSet.variableLimit.commit(20);
demoSet.variableLimit.value = 0; monitor.check();
} }
demoSet.variableLimit.value++; return HasReturnvaluesIF::RETURN_OK;
demoSet.variableLimit.commit(20);
monitor.check();
}
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t FsfwExampleTask::performSendOperation() { ReturnValue_t FsfwExampleTask::performSendOperation() {
object_id_t nextRecipient = getNextRecipient(); object_id_t nextRecipient = getNextRecipient();
FsfwExampleTask* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient); FsfwExampleTask* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
if (target == nullptr) { if (target == nullptr) {
/* Configuration error */ /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl; sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl;
#else #else
sif::printError("DummyObject::performOperation: Next recipient does not exist!\n"); sif::printError("DummyObject::performOperation: Next recipient does not exist!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
uint32_t randomNumber = rand() % 100;
CommandMessage message;
message.setParameter(randomNumber);
message.setParameter2(this->getMessageQueueId());
uint32_t randomNumber = rand() % 100; /* Send message using own message queue */
CommandMessage message; ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
message.setParameter(randomNumber); if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) {
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 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
std::endl;
#else #else
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result); sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
#endif #endif
} }
/* Send message without via MessageQueueSenderIF */ /* Send message without via MessageQueueSenderIF */
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message, result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
commandQueue->getId()); commandQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) {
&& result != MessageQueueIF::FULL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl; sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
#else #else
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result); sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
#endif #endif
} }
demoSet.variableWrite.value = randomNumber; demoSet.variableWrite.value = randomNumber;
result = demoSet.variableWrite.commit(20); result = demoSet.variableWrite.commit(20);
return result; return result;
} }
ReturnValue_t FsfwExampleTask::performReceiveOperation() { ReturnValue_t FsfwExampleTask::performReceiveOperation() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
while (result != MessageQueueIF::EMPTY) { while (result != MessageQueueIF::EMPTY) {
CommandMessage receivedMessage; CommandMessage receivedMessage;
result = commandQueue->receiveMessage(&receivedMessage); result = commandQueue->receiveMessage(&receivedMessage);
if (result != HasReturnvaluesIF::RETURN_OK if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::EMPTY) {
&& result != MessageQueueIF::EMPTY) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Receive failed with " << result << std::endl; sif::debug << "Receive failed with " << result << std::endl;
#endif #endif
break; break;
} }
if (result != MessageQueueIF::EMPTY) { if (result != MessageQueueIF::EMPTY) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
#if OBSW_VERBOSE_LEVEL >= 2 #if OBSW_VERBOSE_LEVEL >= 2
sif::debug << "Message Received by " << getObjectId() << " from Queue " << sif::debug << "Message Received by " << getObjectId() << " from Queue "
receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter() << << receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter()
" Queue " << receivedMessage.getParameter2() << std::endl; << " Queue " << receivedMessage.getParameter2() << std::endl;
#endif #endif
#endif #endif
if(senderSet == nullptr) { if (senderSet == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, 20);
20); if (result != HasReturnvaluesIF::RETURN_OK) {
if(result != HasReturnvaluesIF::RETURN_OK) { return result;
return result; }
} if (senderSet->variableRead.value != receivedMessage.getParameter()) {
if(senderSet->variableRead.value != receivedMessage.getParameter()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex << sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex << "0x"
"0x" << senderSet->variableRead.getDataPoolId() << std::dec << << senderSet->variableRead.getDataPoolId() << std::dec << " has wrong value."
" has wrong value." << std::endl; << std::endl;
sif::error << "Value: " << demoSet.variableRead.value << ", expected: " << sif::error << "Value: " << demoSet.variableRead.value
receivedMessage.getParameter() << std::endl; << ", expected: " << receivedMessage.getParameter() << std::endl;
#endif #endif
} }
}
} }
return result; }
return result;
} }
MessageQueueId_t FsfwExampleTask::getCommandQueue() const { MessageQueueId_t FsfwExampleTask::getCommandQueue() const { return commandQueue->getId(); }
return commandQueue->getId();
}
LocalDataPoolManager* FsfwExampleTask::getHkManagerHandle() { LocalDataPoolManager* FsfwExampleTask::getHkManagerHandle() { return &poolManager; }
return &poolManager;
}

View File

@ -1,18 +1,17 @@
#ifndef MISSION_DEMO_FSFWDEMOTASK_H_ #ifndef MISSION_DEMO_FSFWDEMOTASK_H_
#define 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/datapoollocal/LocalPoolVariable.h>
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/ipc/MessageQueueIF.h> #include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/monitoring/AbsLimitMonitor.h> #include <fsfw/monitoring/AbsLimitMonitor.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include "testdefinitions/demoDefinitions.h"
class PeriodicTaskIF; class PeriodicTaskIF;
/** /**
* @brief This demo set shows the local data pool functionality and fixed * @brief This demo set shows the local data pool functionality and fixed
* timeslot capabilities of the FSFW. * timeslot capabilities of the FSFW.
@ -25,91 +24,82 @@ class PeriodicTaskIF;
* value directly from the sender via the local data pool interface. * 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. * If the timing is set up correctly, the values will always be the same.
*/ */
class FsfwExampleTask: class FsfwExampleTask : public ExecutableObjectIF, public SystemObject, public HasLocalDataPoolIF {
public ExecutableObjectIF, public:
public SystemObject, enum OpCodes { SEND_RAND_NUM, RECEIVE_RAND_NUM, DELAY_SHORT };
public HasLocalDataPoolIF {
public:
enum OpCodes {
SEND_RAND_NUM,
RECEIVE_RAND_NUM,
DELAY_SHORT
};
static constexpr uint8_t MONITOR_ID = 2; static constexpr uint8_t MONITOR_ID = 2;
/** /**
* @brief Simple constructor, only expects object ID. * @brief Simple constructor, only expects object ID.
* @param objectId * @param objectId
*/ */
FsfwExampleTask(object_id_t objectId); FsfwExampleTask(object_id_t objectId);
virtual ~FsfwExampleTask(); virtual ~FsfwExampleTask();
/** /**
* @brief The performOperation method is executed in a task. * @brief The performOperation method is executed in a task.
* @details There are no restrictions for calls within this method, so any * @details There are no restrictions for calls within this method, so any
* other member of the class can be used. * other member of the class can be used.
* @return Currently, the return value is ignored. * @return Currently, the return value is ignored.
*/ */
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/** /**
* @brief This function will be called by the global object manager * @brief This function will be called by the global object manager
* @details * @details
* This function will always be called before any tasks are started. * This function will always be called before any tasks are started.
* It can also be used to return error codes in the software initialization * It can also be used to return error codes in the software initialization
* process cleanly. * process cleanly.
* @return * @return
*/ */
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
/** /**
* @brief This function will be called by the OSAL task handlers * @brief This function will be called by the OSAL task handlers
* @details * @details
* This function will be called before the first #performOperation * This function will be called before the first #performOperation
* call after the tasks have been started. It can be used if some * call after the tasks have been started. It can be used if some
* initialization process requires task specific properties like * initialization process requires task specific properties like
* periodic intervals (by using the PeriodicTaskIF* handle). * periodic intervals (by using the PeriodicTaskIF* handle).
* @return * @return
*/ */
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
/** /**
* This function will be called by the OSAL task handler. The * This function will be called by the OSAL task handler. The
* task interface handle can be cached to access task specific properties. * task interface handle can be cached to access task specific properties.
* @param task * @param task
*/ */
void setTaskIF(PeriodicTaskIF* task) override; void setTaskIF(PeriodicTaskIF* task) override;
object_id_t getObjectId() const override; object_id_t getObjectId() const override;
MessageQueueId_t getMessageQueueId(); MessageQueueId_t getMessageQueueId();
private:
LocalDataPoolManager poolManager;
FsfwDemoSet* senderSet = nullptr;
FsfwDemoSet demoSet;
AbsLimitMonitor<int32_t> monitor;
PeriodicTaskIF* task = nullptr;
MessageQueueIF* commandQueue = nullptr;
private: /* HasLocalDatapoolIF overrides */
LocalDataPoolManager poolManager; MessageQueueId_t getCommandQueue() const override;
FsfwDemoSet* senderSet = nullptr; LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
FsfwDemoSet demoSet; uint32_t getPeriodicOperationFrequency() const override;
AbsLimitMonitor<int32_t> monitor; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
PeriodicTaskIF* task = nullptr; LocalDataPoolManager& poolManager) override;
MessageQueueIF* commandQueue = nullptr; LocalDataPoolManager* getHkManagerHandle() override;
/* HasLocalDatapoolIF overrides */ object_id_t getNextRecipient();
MessageQueueId_t getCommandQueue() const override; object_id_t getSender();
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
uint32_t getPeriodicOperationFrequency() const override;
ReturnValue_t initializeLocalDataPool(
localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalDataPoolManager* getHkManagerHandle() override;
object_id_t getNextRecipient(); ReturnValue_t performMonitoringDemo();
object_id_t getSender(); ReturnValue_t performSendOperation();
ReturnValue_t performReceiveOperation();
ReturnValue_t performMonitoringDemo();
ReturnValue_t performSendOperation();
ReturnValue_t performReceiveOperation();
}; };
#endif /* MISSION_DEMO_FSFWDEMOTASK_H_ */ #endif /* MISSION_DEMO_FSFWDEMOTASK_H_ */

View File

@ -1,55 +1,54 @@
#include "FsfwReaderTask.h" #include "FsfwReaderTask.h"
#include <OBSWConfig.h>
#include <fsfw/datapool/PoolReadGuard.h> #include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h> #include <fsfw/timemanager/Stopwatch.h>
#include <OBSWConfig.h> FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout)
: SystemObject(objectId),
printoutEnabled(enablePrintout),
FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout): opDivider(10),
SystemObject(objectId), printoutEnabled(enablePrintout), opDivider(10), readSet(this->getObjectId(), gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE),
readSet(this->getObjectId(), gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE),
gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE), gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) {
gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE), /* Special protection for set reading because each variable is read from a different pool */
gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) { readSet.setReadCommitProtectionBehaviour(true);
/* Special protection for set reading because each variable is read from a different pool */
readSet.setReadCommitProtectionBehaviour(true);
} }
FsfwReaderTask::~FsfwReaderTask() { FsfwReaderTask::~FsfwReaderTask() {}
}
ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() { ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() {
/* Give other task some time to set up local data pools. */ /* Give other task some time to set up local data pools. */
TaskFactory::delayTask(20); TaskFactory::delayTask(20);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) { ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
PoolReadGuard readHelper(&readSet); PoolReadGuard readHelper(&readSet);
uint32_t variable1 = readSet.variable1.value; uint32_t variable1 = readSet.variable1.value;
uint32_t variable2 = readSet.variable2.value; uint32_t variable2 = readSet.variable2.value;
uint32_t variable3 = readSet.variable3.value; uint32_t variable3 = readSet.variable3.value;
#if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_VERBOSE_LEVEL >= 1
if(opDivider.checkAndIncrement() and printoutEnabled) { if (opDivider.checkAndIncrement() and printoutEnabled) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "FsfwPeriodicTask::performOperation: Reading variables." << std::endl; 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 1: " << variable1 << std::endl;
sif::info << "Variable read from demo object 2: " << variable2 << std::endl; sif::info << "Variable read from demo object 2: " << variable2 << std::endl;
sif::info << "Variable read from demo object 3: " << variable3 << std::endl; sif::info << "Variable read from demo object 3: " << variable3 << std::endl;
#else #else
sif::printInfo("FsfwPeriodicTask::performOperation: Reading variables.\n\r"); 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 1: %d\n\r", variable1);
sif::printInfo("Variable read from demo object 2: %d\n\r", variable2); sif::printInfo("Variable read from demo object 2: %d\n\r", variable2);
sif::printInfo("Variable read from demo object 3: %d\n\r", variable3); sif::printInfo("Variable read from demo object 3: %d\n\r", variable3);
#endif #endif
} }
#else #else
if(variable1 and variable2 and variable3) {}; if (variable1 and variable2 and variable3) {
};
#endif #endif
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,24 +1,24 @@
#ifndef MISSION_DEMO_FSFWPERIODICTASK_H_ #ifndef MISSION_DEMO_FSFWPERIODICTASK_H_
#define MISSION_DEMO_FSFWPERIODICTASK_H_ #define MISSION_DEMO_FSFWPERIODICTASK_H_
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include "testdefinitions/demoDefinitions.h" #include "testdefinitions/demoDefinitions.h"
#include <fsfw/globalfunctions/PeriodicOperationDivider.h> class FsfwReaderTask : public ExecutableObjectIF, public SystemObject {
#include <fsfw/tasks/ExecutableObjectIF.h> public:
#include <fsfw/objectmanager/SystemObject.h> FsfwReaderTask(object_id_t objectId, bool enablePrintout);
~FsfwReaderTask() override;
class FsfwReaderTask: public ExecutableObjectIF, public SystemObject { ReturnValue_t initializeAfterTaskCreation() override;
public: ReturnValue_t performOperation(uint8_t operationCode = 0) override;
FsfwReaderTask(object_id_t objectId, bool enablePrintout);
~FsfwReaderTask() override;
ReturnValue_t initializeAfterTaskCreation() override; private:
ReturnValue_t performOperation(uint8_t operationCode = 0) override; bool printoutEnabled = false;
PeriodicOperationDivider opDivider;
private: CompleteDemoReadSet readSet;
bool printoutEnabled = false;
PeriodicOperationDivider opDivider;
CompleteDemoReadSet readSet;
}; };
#endif /* MISSION_DEMO_FSFWPERIODICTASK_H_ */ #endif /* MISSION_DEMO_FSFWPERIODICTASK_H_ */

View File

@ -1,12 +1,11 @@
#include "FsfwTestTask.h" #include "FsfwTestTask.h"
FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent): FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent)
TestTask(objectId), periodicEvent(periodicEvent) { : TestTask(objectId), periodicEvent(periodicEvent) {}
}
ReturnValue_t FsfwTestTask::performPeriodicAction() { ReturnValue_t FsfwTestTask::performPeriodicAction() {
if(periodicEvent) { if (periodicEvent) {
triggerEvent(TEST_EVENT, 0x1234, 0x4321); triggerEvent(TEST_EVENT, 0x1234, 0x4321);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,21 +1,20 @@
#ifndef EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_ #ifndef EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_
#define EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_ #define EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_
#include "events/subsystemIdRanges.h"
#include "fsfw/events/Event.h"
#include "fsfw_tests/integration/task/TestTask.h" #include "fsfw_tests/integration/task/TestTask.h"
#include "fsfw/events/Event.h" class FsfwTestTask : public TestTask {
#include "events/subsystemIdRanges.h" public:
FsfwTestTask(object_id_t objectId, bool periodicEvent);
class FsfwTestTask: public TestTask { ReturnValue_t performPeriodicAction() override;
public:
FsfwTestTask(object_id_t objectId, bool periodicEvent);
ReturnValue_t performPeriodicAction() override; private:
private: bool periodicEvent = false;
static constexpr uint8_t subsystemId = SUBSYSTEM_ID::TEST_TASK_ID;
bool periodicEvent = false; static constexpr Event TEST_EVENT = event::makeEvent(subsystemId, 0, severity::INFO);
static constexpr uint8_t subsystemId = SUBSYSTEM_ID::TEST_TASK_ID;
static constexpr Event TEST_EVENT = event::makeEvent(subsystemId, 0, severity::INFO);
}; };
#endif /* EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_ */ #endif /* EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_ */

View File

@ -3,45 +3,43 @@
#include <fsfw/ipc/MutexFactory.h> #include <fsfw/ipc/MutexFactory.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
void MutexExample::example() {
MutexIF* mutex = MutexFactory::instance()->createMutex();
MutexIF* mutex2 = MutexFactory::instance()->createMutex();
void MutexExample::example(){ ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, 2 * 60 * 1000);
MutexIF* mutex = MutexFactory::instance()->createMutex(); if (result != HasReturnvaluesIF::RETURN_OK) {
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 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
#else #else
sif::printError("MutexExample::example: Lock Failed with %hu\n", result); sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
#endif #endif
} }
result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING); result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
#else #else
sif::printError("MutexExample::example: Lock Failed with %hu\n", result); sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
#endif #endif
} }
result = mutex->unlockMutex(); result = mutex->unlockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
#else #else
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result); sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
#endif #endif
} }
result = mutex2->unlockMutex(); result = mutex2->unlockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
#else #else
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result); sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
#endif #endif
} }
} }

View File

@ -2,7 +2,7 @@
#define EXAMPLE_COMMON_MUTEXEXAMPLE_H_ #define EXAMPLE_COMMON_MUTEXEXAMPLE_H_
namespace MutexExample { namespace MutexExample {
void example(); void example();
}; };
#endif /* EXAMPLE_COMMON_MUTEXEXAMPLE_H_ */ #endif /* EXAMPLE_COMMON_MUTEXEXAMPLE_H_ */

View File

@ -1,8 +1,8 @@
#ifndef MISSION_DEMO_DEMODEFINITIONS_H_ #ifndef MISSION_DEMO_DEMODEFINITIONS_H_
#define MISSION_DEMO_DEMODEFINITIONS_H_ #define MISSION_DEMO_DEMODEFINITIONS_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h> #include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
/** /**
* @brief This demo set showcases the local data pool functionality of the * @brief This demo set showcases the local data pool functionality of the
@ -11,27 +11,22 @@
* Each demo object will have an own instance of this set class, which contains * Each demo object will have an own instance of this set class, which contains
* pool variables (for read and write access respectively). * pool variables (for read and write access respectively).
*/ */
class FsfwDemoSet: public StaticLocalDataSet<3> { class FsfwDemoSet : public StaticLocalDataSet<3> {
public: public:
static constexpr uint32_t DEMO_SET_ID = 0;
static constexpr uint32_t DEMO_SET_ID = 0; enum PoolIds { VARIABLE, VARIABLE_LIMIT };
enum PoolIds { FsfwDemoSet(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, DEMO_SET_ID) {}
VARIABLE,
VARIABLE_LIMIT
};
FsfwDemoSet(HasLocalDataPoolIF* hkOwner): lp_var_t<uint32_t> variableRead =
StaticLocalDataSet(hkOwner, DEMO_SET_ID) {} 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> variableRead = lp_var_t<uint32_t>(sid.objectId, lp_var_t<uint32_t>(sid.objectId, PoolIds::VARIABLE, this, pool_rwm_t::VAR_WRITE);
PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ); lp_var_t<uint16_t> variableLimit =
lp_var_t<uint32_t> variableWrite = lp_var_t<uint32_t>(sid.objectId, lp_var_t<uint16_t>(sid.objectId, PoolIds::VARIABLE_LIMIT, this);
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:
private:
}; };
/** /**
@ -39,25 +34,21 @@ private:
* above. An example application would be a consumer object like a controller * above. An example application would be a consumer object like a controller
* which reads multiple sensor values at once. * which reads multiple sensor values at once.
*/ */
class CompleteDemoReadSet: public StaticLocalDataSet<3> { class CompleteDemoReadSet : public StaticLocalDataSet<3> {
public: public:
static constexpr uint32_t DEMO_SET_ID = 0; static constexpr uint32_t DEMO_SET_ID = 0;
CompleteDemoReadSet(object_id_t owner, gp_id_t variable1, CompleteDemoReadSet(object_id_t owner, gp_id_t variable1, gp_id_t variable2, gp_id_t variable3)
gp_id_t variable2, gp_id_t variable3): : StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)),
StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)), variable1(variable1, this, pool_rwm_t::VAR_READ),
variable1(variable1, this, pool_rwm_t::VAR_READ), variable2(variable2, this, pool_rwm_t::VAR_READ),
variable2(variable2, this, pool_rwm_t::VAR_READ), variable3(variable3, 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;
lp_var_t<uint32_t> variable1; private:
lp_var_t<uint32_t> variable2;
lp_var_t<uint32_t> variable3;
private:
}; };
#endif /* MISSION_DEMO_DEMODEFINITIONS_H_ */ #endif /* MISSION_DEMO_DEMODEFINITIONS_H_ */

View File

@ -1,10 +1,9 @@
#include <fsfw/tmtcpacket/pus/tc.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#include <fsfw/globalfunctions/arrayprinter.h> #include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tmtcpacket/pus/tc.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#include <mission/utility/PusPacketCreator.h> #include <mission/utility/PusPacketCreator.h>
void PusPacketCreator::createPusPacketAndPrint() { void PusPacketCreator::createPusPacketAndPrint() {
// TODO: use TC packet stored here instead.. // TODO: use TC packet stored here instead..
} }

View File

@ -9,8 +9,8 @@
#define MISSION_UTILITY_PUSPACKETCREATOR_H_ #define MISSION_UTILITY_PUSPACKETCREATOR_H_
class PusPacketCreator { class PusPacketCreator {
public: public:
static void createPusPacketAndPrint(); static void createPusPacketAndPrint();
}; };
#endif /* MISSION_UTILITY_PUSPACKETCREATOR_H_ */ #endif /* MISSION_UTILITY_PUSPACKETCREATOR_H_ */

View File

@ -8,15 +8,14 @@ namespace task {
void printInitError(const char* objName, object_id_t objectId) { void printInitError(const char* objName, object_id_t objectId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "InitMission: Adding object " << objName << "(" sif::error << "InitMission: Adding object " << objName << "(" << std::setw(8) << std::setfill('0')
<< std::setw(8) << std::setfill('0') << std::hex << objectId << std::hex << objectId << std::dec << ") failed." << std::endl;
<< std::dec << ") failed." << std::endl;
#else #else
sif::printError("InitMission: Adding object %s (0x%08x) failed.\n", sif::printError("InitMission: Adding object %s (0x%08x) failed.\n", objName,
objName, static_cast<unsigned int>(objectId)); static_cast<unsigned int>(objectId));
#endif #endif
} }
} } // namespace task
#endif /* MISSION_UTILITY_TASKCREATION_H_ */ #endif /* MISSION_UTILITY_TASKCREATION_H_ */

View File

@ -2,119 +2,113 @@
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h> #include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tmtcpacket/pus/tm.h>
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT; object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT;
object_id_t TmFunnel::storageDestination = objects::NO_OBJECT; object_id_t TmFunnel::storageDestination = objects::NO_OBJECT;
TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth): TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth)
SystemObject(objectId), messageDepth(messageDepth) { : SystemObject(objectId), messageDepth(messageDepth) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth, tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE); MessageQueueMessage::MAX_MESSAGE_SIZE);
storageQueue = QueueFactory::instance()->createMessageQueue(messageDepth, storageQueue = QueueFactory::instance()->createMessageQueue(
MessageQueueMessage::MAX_MESSAGE_SIZE); messageDepth, MessageQueueMessage::MAX_MESSAGE_SIZE);
} }
TmFunnel::~TmFunnel() { TmFunnel::~TmFunnel() {}
}
MessageQueueId_t TmFunnel::getReportReceptionQueue(uint8_t virtualChannel) { MessageQueueId_t TmFunnel::getReportReceptionQueue(uint8_t virtualChannel) {
return tmQueue->getId(); return tmQueue->getId();
} }
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) { ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
TmTcMessage currentMessage; TmTcMessage currentMessage;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage); ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
while(status == HasReturnvaluesIF::RETURN_OK) while (status == HasReturnvaluesIF::RETURN_OK) {
{ status = handlePacket(&currentMessage);
status = handlePacket(&currentMessage); if (status != HasReturnvaluesIF::RETURN_OK) {
if(status != HasReturnvaluesIF::RETURN_OK){ break;
break;
}
status = tmQueue->receiveMessage(&currentMessage);
} }
status = tmQueue->receiveMessage(&currentMessage);
}
if (status == MessageQueueIF::EMPTY) { if (status == MessageQueueIF::EMPTY) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} } else {
else { return status;
return status; }
}
} }
ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) { ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
uint8_t* packetData = nullptr; uint8_t* packetData = nullptr;
size_t size = 0; size_t size = 0;
ReturnValue_t result = tmPool->modifyData(message->getStorageId(), ReturnValue_t result = tmPool->modifyData(message->getStorageId(), &packetData, &size);
&packetData, &size); if (result != HasReturnvaluesIF::RETURN_OK) {
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
TmPacketPusC packet(packetData);
packet.setPacketSequenceCount(this->sourceSequenceCount);
sourceSequenceCount++;
sourceSequenceCount = sourceSequenceCount %
SpacePacketBase::LIMIT_SEQUENCE_COUNT;
packet.setErrorControl();
result = tmQueue->sendToDefault(message);
if(result != HasReturnvaluesIF::RETURN_OK){
tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::handlePacket: Error sending to downlink handler" << std::endl;
#endif
return result;
}
if(storageDestination != objects::NO_OBJECT) {
result = storageQueue->sendToDefault(message);
if(result != HasReturnvaluesIF::RETURN_OK){
tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::handlePacket: Error sending to storage handler" << std::endl;
#endif
return result;
}
}
return result; return result;
}
TmPacketPusC packet(packetData);
packet.setPacketSequenceCount(this->sourceSequenceCount);
sourceSequenceCount++;
sourceSequenceCount = sourceSequenceCount % SpacePacketBase::LIMIT_SEQUENCE_COUNT;
packet.setErrorControl();
result = tmQueue->sendToDefault(message);
if (result != HasReturnvaluesIF::RETURN_OK) {
tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::handlePacket: Error sending to downlink handler" << std::endl;
#endif
return result;
}
if (storageDestination != objects::NO_OBJECT) {
result = storageQueue->sendToDefault(message);
if (result != HasReturnvaluesIF::RETURN_OK) {
tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::handlePacket: Error sending to storage handler" << std::endl;
#endif
return result;
}
}
return result;
} }
ReturnValue_t TmFunnel::initialize() { ReturnValue_t TmFunnel::initialize() {
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE); if (tmPool == nullptr) {
if(tmPool == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::initialize: TM store not set." << std::endl; sif::error << "TmFunnel::initialize: TM store not set." << std::endl;
sif::error << "Make sure the tm store is set up properly and implements StorageManagerIF" << sif::error << "Make sure the tm store is set up properly and implements StorageManagerIF"
std::endl; << std::endl;
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
AcceptsTelemetryIF* tmTarget = ObjectManager::instance()-> AcceptsTelemetryIF* tmTarget =
get<AcceptsTelemetryIF>(downlinkDestination); ObjectManager::instance()->get<AcceptsTelemetryIF>(downlinkDestination);
if(tmTarget == nullptr){ if (tmTarget == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::initialize: Downlink Destination not set." << std::endl; sif::error << "TmFunnel::initialize: Downlink Destination not set." << std::endl;
sif::error << "Make sure the downlink destination object is set up properly and implements " sif::error << "Make sure the downlink destination object is set up properly and implements "
"AcceptsTelemetryIF" << std::endl; "AcceptsTelemetryIF"
<< std::endl;
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue()); tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue());
// Storage destination is optional.
if(storageDestination == objects::NO_OBJECT) {
return SystemObject::initialize();
}
AcceptsTelemetryIF* storageTarget = ObjectManager::instance()->
get<AcceptsTelemetryIF>(storageDestination);
if(storageTarget != nullptr) {
storageQueue->setDefaultDestination(
storageTarget->getReportReceptionQueue());
}
// Storage destination is optional.
if (storageDestination == objects::NO_OBJECT) {
return SystemObject::initialize(); return SystemObject::initialize();
}
AcceptsTelemetryIF* storageTarget =
ObjectManager::instance()->get<AcceptsTelemetryIF>(storageDestination);
if (storageTarget != nullptr) {
storageQueue->setDefaultDestination(storageTarget->getReportReceptionQueue());
}
return SystemObject::initialize();
} }

View File

@ -1,13 +1,13 @@
#ifndef MISSION_UTILITY_TMFUNNEL_H_ #ifndef MISSION_UTILITY_TMFUNNEL_H_
#define MISSION_UTILITY_TMFUNNEL_H_ #define MISSION_UTILITY_TMFUNNEL_H_
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h> #include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/tmtcservices/TmTcMessage.h> #include <fsfw/tmtcservices/TmTcMessage.h>
namespace Factory{ namespace Factory {
void setStaticFrameworkObjectIds(); void setStaticFrameworkObjectIds();
} }
@ -19,33 +19,30 @@ void setStaticFrameworkObjectIds();
* @ingroup utility * @ingroup utility
* @author J. Meier * @author J. Meier
*/ */
class TmFunnel: class TmFunnel : public AcceptsTelemetryIF, public ExecutableObjectIF, public SystemObject {
public AcceptsTelemetryIF, friend void(Factory::setStaticFrameworkObjectIds)();
public ExecutableObjectIF,
public SystemObject {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
TmFunnel(object_id_t objectId, uint32_t messageDepth = 20);
virtual ~TmFunnel();
virtual MessageQueueId_t getReportReceptionQueue( public:
uint8_t virtualChannel = 0) override; TmFunnel(object_id_t objectId, uint32_t messageDepth = 20);
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; virtual ~TmFunnel();
virtual ReturnValue_t initialize() override;
protected: virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override;
static object_id_t downlinkDestination; virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
static object_id_t storageDestination; virtual ReturnValue_t initialize() override;
private: protected:
uint16_t sourceSequenceCount = 0; static object_id_t downlinkDestination;
MessageQueueIF* tmQueue = nullptr; static object_id_t storageDestination;
MessageQueueIF* storageQueue = nullptr;
StorageManagerIF* tmPool = nullptr; private:
uint32_t messageDepth = 0; uint16_t sourceSequenceCount = 0;
MessageQueueIF* tmQueue = nullptr;
MessageQueueIF* storageQueue = nullptr;
ReturnValue_t handlePacket(TmTcMessage* message); StorageManagerIF* tmPool = nullptr;
uint32_t messageDepth = 0;
ReturnValue_t handlePacket(TmTcMessage* message);
}; };
#endif /* MISSION_UTILITY_TMFUNNEL_H_ */ #endif /* MISSION_UTILITY_TMFUNNEL_H_ */

View File

@ -5,14 +5,17 @@
* Authors: * Authors:
* *
* Assembled from the code released on Stackoverflow by: * Assembled from the code released on Stackoverflow by:
* Dennis (instructable.com/member/nqtronix) | https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string * Dennis (instructable.com/member/nqtronix) |
* https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string
* and * and
* Alexis Wilke | https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date * Alexis Wilke |
* https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date
* *
* Assembled by Jean Rabault * Assembled by Jean Rabault
* *
* UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro. * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of
* This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps. * compilation from macros using the compiler defined __TIME__ macro. This should include Gregorian
* calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
* *
* Careful: __TIME__ is the local time of the computer, NOT the UTC time in general! * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
* *
@ -22,76 +25,66 @@
#define COMPILE_TIME_H_ #define COMPILE_TIME_H_
// Some definitions for calculation // Some definitions for calculation
#define SEC_PER_MIN 60UL #define SEC_PER_MIN 60UL
#define SEC_PER_HOUR 3600UL #define SEC_PER_HOUR 3600UL
#define SEC_PER_DAY 86400UL #define SEC_PER_DAY 86400UL
#define SEC_PER_YEAR (SEC_PER_DAY*365) #define SEC_PER_YEAR (SEC_PER_DAY * 365)
// extracts 1..4 characters from a string and interprets it as a decimal value // extracts 1..4 characters from a string and interprets it as a decimal value
#define CONV_STR2DEC_1(str, i) (str[i]>'0'?str[i]-'0':0) #define CONV_STR2DEC_1(str, i) (str[i] > '0' ? str[i] - '0' : 0)
#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0') #define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i) * 10 + str[i + 1] - '0')
#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0') #define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i) * 10 + str[i + 2] - '0')
#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0') #define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i) * 10 + str[i + 3] - '0')
// Custom "glue logic" to convert the month name to a usable number // Custom "glue logic" to convert the month name to a usable number
#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \ #define GET_MONTH(str, i) \
str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \ (str[i] == 'J' && str[i + 1] == 'a' && str[i + 2] == 'n' ? 1 \
str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \ : str[i] == 'F' && str[i + 1] == 'e' && str[i + 2] == 'b' ? 2 \
str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \ : str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'r' ? 3 \
str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \ : str[i] == 'A' && str[i + 1] == 'p' && str[i + 2] == 'r' ? 4 \
str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \ : str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'y' ? 5 \
str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \ : str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'n' ? 6 \
str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \ : str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'l' ? 7 \
str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \ : str[i] == 'A' && str[i + 1] == 'u' && str[i + 2] == 'g' ? 8 \
str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \ : str[i] == 'S' && str[i + 1] == 'e' && str[i + 2] == 'p' ? 9 \
str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 : \ : str[i] == 'O' && str[i + 1] == 'c' && str[i + 2] == 't' ? 10 \
str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0) : str[i] == 'N' && str[i + 1] == 'o' && str[i + 2] == 'v' ? 11 \
: str[i] == 'D' && str[i + 1] == 'e' && str[i + 2] == 'c' ? 12 \
: 0)
// extract the information from the time string given by __TIME__ and __DATE__ // extract the information from the time string given by __TIME__ and __DATE__
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6) #define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3) #define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0) #define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4) #define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0) #define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7) #define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
// Days in February // Days in February
#define _UNIX_TIMESTAMP_FDAY(year) \ #define _UNIX_TIMESTAMP_FDAY(year) \
(((year) % 400) == 0UL ? 29UL : \ (((year) % 400) == 0UL ? 29UL \
(((year) % 100) == 0UL ? 28UL : \ : (((year) % 100) == 0UL ? 28UL : (((year) % 4) == 0UL ? 29UL : 28UL)))
(((year) % 4) == 0UL ? 29UL : \
28UL)))
// Days in the year // Days in the year
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \ #define _UNIX_TIMESTAMP_YDAY(year, month, day) \
( \ (/* January */ day /* February */ + (month >= 2 ? 31UL : 0UL) /* March */ + \
/* January */ day \ (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) /* April */ + \
/* February */ + (month >= 2 ? 31UL : 0UL) \ (month >= 4 ? 31UL : 0UL) /* May */ + (month >= 5 ? 30UL : 0UL) /* June */ + \
/* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \ (month >= 6 ? 31UL : 0UL) /* July */ + (month >= 7 ? 30UL : 0UL) /* August */ + \
/* April */ + (month >= 4 ? 31UL : 0UL) \ (month >= 8 ? 31UL : 0UL) /* September */ + (month >= 9 ? 31UL : 0UL) /* October */ + \
/* May */ + (month >= 5 ? 30UL : 0UL) \ (month >= 10 ? 30UL : 0UL) /* November */ + (month >= 11 ? 31UL : 0UL) /* December */ + \
/* June */ + (month >= 6 ? 31UL : 0UL) \ (month >= 12 ? 30UL : 0UL))
/* July */ + (month >= 7 ? 30UL : 0UL) \
/* August */ + (month >= 8 ? 31UL : 0UL) \
/* September */+ (month >= 9 ? 31UL : 0UL) \
/* October */ + (month >= 10 ? 30UL : 0UL) \
/* November */ + (month >= 11 ? 31UL : 0UL) \
/* December */ + (month >= 12 ? 30UL : 0UL) \
)
// get the UNIX timestamp from a digits representation // get the UNIX timestamp from a digits representation
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \ #define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
( /* time */ second \ (/* time */ second + minute * SEC_PER_MIN + hour * SEC_PER_HOUR + \
+ minute * SEC_PER_MIN \ /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY + \
+ hour * SEC_PER_HOUR \ /* year */ (year - 1970UL) * SEC_PER_YEAR + ((year - 1969UL) / 4UL) * SEC_PER_DAY - \
+ /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \ ((year - 1901UL) / 100UL) * SEC_PER_DAY + ((year - 1601UL) / 400UL) * SEC_PER_DAY)
+ /* year */ (year - 1970UL) * SEC_PER_YEAR \
+ ((year - 1969UL) / 4UL) * SEC_PER_DAY \
- ((year - 1901UL) / 100UL) * SEC_PER_DAY \
+ ((year - 1601UL) / 400UL) * SEC_PER_DAY \
)
// the UNIX timestamp // the UNIX timestamp
#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__)) #define UNIX_TIMESTAMP \
(_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, \
__TIME_MINUTES__, __TIME_SECONDS__))
#endif #endif

View File

@ -1,22 +1,22 @@
#include "utility.h" #include "utility.h"
#include <FSFWConfig.h> #include <FSFWConfig.h>
#include <OBSWVersion.h> #include <OBSWVersion.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
void utility::commonInitPrint(const char *const os, const char* const board) { void utility::commonInitPrint(const char* const os, const char* const board) {
if(os == nullptr or board == nullptr) { if (os == nullptr or board == nullptr) {
return; return;
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
std::cout << "-- FSFW Example (" << os<< ") v" << FSFW_EXAMPLE_VERSION << "." << std::cout << "-- FSFW Example (" << os << ") v" << FSFW_EXAMPLE_VERSION << "."
FSFW_EXAMPLE_SUBVERSION << "." << FSFW_EXAMPLE_REVISION << " --" << std::endl; << FSFW_EXAMPLE_SUBVERSION << "." << FSFW_EXAMPLE_REVISION << " --" << std::endl;
std::cout << "-- Compiled for " << board << " --" << std::endl; std::cout << "-- Compiled for " << board << " --" << std::endl;
std::cout << "-- Compiled on " << __DATE__ << " " << __TIME__ << " --" << std::endl; std::cout << "-- Compiled on " << __DATE__ << " " << __TIME__ << " --" << std::endl;
#else #else
printf("\n\r-- FSFW Example (%s) v%d.%d.%d --\n", os, FSFW_EXAMPLE_VERSION, printf("\n\r-- FSFW Example (%s) v%d.%d.%d --\n", os, FSFW_EXAMPLE_VERSION,
FSFW_EXAMPLE_SUBVERSION, FSFW_EXAMPLE_REVISION); FSFW_EXAMPLE_SUBVERSION, FSFW_EXAMPLE_REVISION);
printf("-- Compiled for %s --\n", board); printf("-- Compiled for %s --\n", board);
printf("-- Compiled on %s %s --\n", __DATE__, __TIME__); printf("-- Compiled on %s %s --\n", __DATE__, __TIME__);
#endif #endif
} }

View File

@ -3,9 +3,8 @@
namespace utility { namespace utility {
void commonInitPrint(const char *const os, const char* const board); void commonInitPrint(const char* const os, const char* const board);
} }
#endif /* COMMON_UTILITY_UTILITY_H_ */ #endif /* COMMON_UTILITY_UTILITY_H_ */

View File

@ -1,33 +1,33 @@
#include "STM32TestTask.h" #include "STM32TestTask.h"
#include "stm32h7xx_nucleo.h"
#include "OBSWConfig.h"
STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout, #include "OBSWConfig.h"
bool blinkyLed): TestTask(objectId), blinkyLed(blinkyLed) { #include "stm32h7xx_nucleo.h"
BSP_LED_Init(LED1);
BSP_LED_Init(LED2); STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed)
BSP_LED_Init(LED3); : TestTask(objectId), blinkyLed(blinkyLed) {
BSP_LED_Init(LED1);
BSP_LED_Init(LED2);
BSP_LED_Init(LED3);
} }
ReturnValue_t STM32TestTask::performPeriodicAction() { ReturnValue_t STM32TestTask::performPeriodicAction() {
if(blinkyLed) { if (blinkyLed) {
#if OBSW_ETHERNET_USE_LEDS == 0 #if OBSW_ETHERNET_USE_LEDS == 0
BSP_LED_Toggle(LED1); BSP_LED_Toggle(LED1);
BSP_LED_Toggle(LED2); BSP_LED_Toggle(LED2);
#endif #endif
BSP_LED_Toggle(LED3); BSP_LED_Toggle(LED3);
} }
if(testSpi) { if (testSpi) {
spiTest->performOperation(); spiTest->performOperation();
} }
return TestTask::performPeriodicAction(); return TestTask::performPeriodicAction();
} }
ReturnValue_t STM32TestTask::initialize() { ReturnValue_t STM32TestTask::initialize() {
if(testSpi) { if (testSpi) {
spiComIF = new SpiComIF(objects::SPI_COM_IF); spiComIF = new SpiComIF(objects::SPI_COM_IF);
spiTest = new SpiTest(*spiComIF); spiTest = new SpiTest(*spiComIF);
}
} return TestTask::initialize();
return TestTask::initialize();
} }

View File

@ -4,22 +4,19 @@
#include "bsp_stm32h7_freertos/boardtest/SpiTest.h" #include "bsp_stm32h7_freertos/boardtest/SpiTest.h"
#include "fsfw_tests/integration/task/TestTask.h" #include "fsfw_tests/integration/task/TestTask.h"
class STM32TestTask: public TestTask { class STM32TestTask : public TestTask {
public: public:
STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed = true); STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed = true);
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
ReturnValue_t performPeriodicAction() override; ReturnValue_t performPeriodicAction() override;
private:
SpiComIF* spiComIF = nullptr; private:
SpiTest* spiTest = nullptr; SpiComIF* spiComIF = nullptr;
SpiTest* spiTest = nullptr;
bool blinkyLed = false;
bool testSpi = true;
bool blinkyLed = false;
bool testSpi = true;
}; };
#endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */ #endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */

View File

@ -1,204 +1,189 @@
#include "TmTcLwIpUdpBridge.h" #include "TmTcLwIpUdpBridge.h"
#include "udp_config.h"
#include <OBSWConfig.h>
#include <fsfw/ipc/MutexGuard.h>
#include <fsfw/serialize/EndianConverter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include "app_ethernet.h" #include "app_ethernet.h"
#include "ethernetif.h" #include "ethernetif.h"
#include <OBSWConfig.h> #include "udp_config.h"
#include <fsfw/ipc/MutexGuard.h> TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor,
#include <fsfw/serviceinterface/ServiceInterface.h> object_id_t tmStoreId, object_id_t tcStoreId)
#include <fsfw/serialize/EndianConverter.h> : TmTcBridge(objectId, ccsdsPacketDistributor, tmStoreId, tcStoreId) {
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId,
object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
object_id_t tcStoreId):
TmTcBridge(objectId, ccsdsPacketDistributor, tmStoreId, tcStoreId) {
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
} }
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {} TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {}
ReturnValue_t TmTcLwIpUdpBridge::initialize() { ReturnValue_t TmTcLwIpUdpBridge::initialize() {
TmTcBridge::initialize(); TmTcBridge::initialize();
bridgeLock = MutexFactory::instance()->createMutex(); bridgeLock = MutexFactory::instance()->createMutex();
if(bridgeLock == nullptr) { if (bridgeLock == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
ReturnValue_t result = udp_server_init(); ReturnValue_t result = udp_server_init();
return result; return result;
} }
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) { ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) {
err_t err; err_t err;
/* Create a new UDP control block */ /* Create a new UDP control block */
TmTcLwIpUdpBridge::upcb = udp_new(); TmTcLwIpUdpBridge::upcb = udp_new();
if (TmTcLwIpUdpBridge::upcb) if (TmTcLwIpUdpBridge::upcb) {
{ /* Bind the upcb to the UDP_PORT port */
/* Bind the upcb to the UDP_PORT port */ /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
if(err == ERR_OK) if (err == ERR_OK) {
{ /* Set a receive callback for the upcb */
/* Set a receive callback for the upcb */ udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, (void*)this);
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, return RETURN_OK;
(void*) this);
return RETURN_OK;
}
else
{
udp_remove(TmTcLwIpUdpBridge::upcb);
return RETURN_FAILED;
}
} else { } else {
return RETURN_FAILED; udp_remove(TmTcLwIpUdpBridge::upcb);
return RETURN_FAILED;
} }
} else {
return RETURN_FAILED;
}
} }
ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) { ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
TmTcBridge::performOperation(); TmTcBridge::performOperation();
#if TCPIP_RECV_WIRETAPPING == 1 #if TCPIP_RECV_WIRETAPPING == 1
if(connectFlag) { if (connectFlag) {
uint32_t ipAddress = ((ip4_addr*) &lastAdd)->addr; uint32_t ipAddress = ((ip4_addr*)&lastAdd)->addr;
int ipAddress1 = (ipAddress & 0xFF000000) >> 24; int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
int ipAddress2 = (ipAddress & 0xFF0000) >> 16; int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
int ipAddress3 = (ipAddress & 0xFF00) >> 8; int ipAddress3 = (ipAddress & 0xFF00) >> 8;
int ipAddress4 = ipAddress & 0xFF; int ipAddress4 = ipAddress & 0xFF;
#if OBSW_VERBOSE_LEVEL == 1 #if OBSW_VERBOSE_LEVEL == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec << ipAddress4 << "."
<< ipAddress4 << "." << ipAddress3 << "." << ipAddress2 << "." << ipAddress3 << "." << ipAddress2 << "." << ipAddress1 << std::endl;
<< ipAddress1 << std::endl; uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort); sif::info << "TmTcLwIpUdpBridge: Client IP Port " << (int)portSwapped << std::endl;
sif::info << "TmTcLwIpUdpBridge: Client IP Port "
<< (int)portSwapped << std::endl;
#else #else
sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n", sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n", ipAddress4, ipAddress3,
ipAddress4, ipAddress3, ipAddress2, ipAddress1); ipAddress2, ipAddress1);
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort); uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped); sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped);
#endif #endif
#endif #endif
connectFlag = false; connectFlag = false;
} }
#endif #endif
return RETURN_OK; return RETURN_OK;
} }
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t * data, size_t dataLen) { ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t* data, size_t dataLen) {
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM); struct pbuf* p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) { if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
/* copy data to pbuf */ /* copy data to pbuf */
err_t err = pbuf_take(p_tx, (char*) data, dataLen); err_t err = pbuf_take(p_tx, (char*)data, dataLen);
if(err!=ERR_OK){ if (err != ERR_OK) {
pbuf_free(p_tx); pbuf_free(p_tx);
return err; return err;
}
/* Connect to the remote client */
err = udp_connect(TmTcLwIpUdpBridge::upcb, &lastAdd , lastPort);
if(err != ERR_OK){
pbuf_free(p_tx);
return err;
}
/* Tell the client that we have accepted it */
err = udp_send(TmTcLwIpUdpBridge::upcb, p_tx);
pbuf_free(p_tx);
if(err!=ERR_OK){
return err;
}
/* free the UDP connection, so we can accept new clients */
udp_disconnect (TmTcLwIpUdpBridge::upcb);
} }
else{ /* Connect to the remote client */
return RETURN_FAILED; err = udp_connect(TmTcLwIpUdpBridge::upcb, &lastAdd, lastPort);
if (err != ERR_OK) {
pbuf_free(p_tx);
return err;
} }
return RETURN_OK; /* Tell the client that we have accepted it */
} err = udp_send(TmTcLwIpUdpBridge::upcb, p_tx);
void TmTcLwIpUdpBridge::udp_server_receive_callback(void* arg,
struct udp_pcb* upcb_, struct pbuf* p, const ip_addr_t* addr,
u16_t port) {
struct pbuf *p_tx = nullptr;
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge*>(arg);
if(udpBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!" <<
std::endl;
#else
sif::printWarning("TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!\n");
#endif
}
/* allocate pbuf from RAM*/
p_tx = pbuf_alloc(PBUF_TRANSPORT,p->len, PBUF_RAM);
if(p_tx != NULL)
{
if(udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock);
udpBridge->upcb = upcb_;
udpBridge->lastAdd = *addr;
udpBridge->lastPort = port;
if(not udpBridge->comLinkUp()) {
udpBridge->registerCommConnect();
#if TCPIP_RECV_WIRETAPPING == 1
udpBridge->connectFlag = true;
#endif
/* This should have already been done, but we will still do it */
udpBridge->physicalConnectStatusChange(true);
}
}
pbuf_take(p_tx, (char*)p->payload, p->len);
/* send the received data to the uart port */
char* data = reinterpret_cast<char*>(p_tx->payload);
*(data+p_tx->len) = '\0';
#if TCPIP_RECV_WIRETAPPING == 1
udpBridge->printData(p,data);
#endif
store_address_t storeId;
ReturnValue_t returnValue = udpBridge->tcStore->addData(&storeId,
reinterpret_cast<uint8_t*>(p->payload), p->len);
if (returnValue != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UDP Server: Data storage failed" << std::endl;
#endif
pbuf_free(p_tx);
return;
}
TmTcMessage message(storeId);
if (udpBridge->tmTcReceptionQueue->sendToDefault(&message)
!= RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcLwIpUdpBridgw::udp_server_receive_callback:"
<< " Sending message to queue failed" << std::endl;
#endif
udpBridge->tcStore->deleteData(storeId);
}
}
/* Free the p_tx buffer */
pbuf_free(p_tx); pbuf_free(p_tx);
if (err != ERR_OK) {
return err;
}
/* free the UDP connection, so we can accept new clients */
udp_disconnect(TmTcLwIpUdpBridge::upcb);
} else {
return RETURN_FAILED;
}
return RETURN_OK;
}
void TmTcLwIpUdpBridge::udp_server_receive_callback(void* arg, struct udp_pcb* upcb_,
struct pbuf* p, const ip_addr_t* addr,
u16_t port) {
struct pbuf* p_tx = nullptr;
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge*>(arg);
if (udpBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!"
<< std::endl;
#else
sif::printWarning("TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!\n");
#endif
}
/* allocate pbuf from RAM*/
p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
if (p_tx != NULL) {
if (udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock);
udpBridge->upcb = upcb_;
udpBridge->lastAdd = *addr;
udpBridge->lastPort = port;
if (not udpBridge->comLinkUp()) {
udpBridge->registerCommConnect();
#if TCPIP_RECV_WIRETAPPING == 1
udpBridge->connectFlag = true;
#endif
/* This should have already been done, but we will still do it */
udpBridge->physicalConnectStatusChange(true);
}
}
pbuf_take(p_tx, (char*)p->payload, p->len);
/* send the received data to the uart port */
char* data = reinterpret_cast<char*>(p_tx->payload);
*(data + p_tx->len) = '\0';
#if TCPIP_RECV_WIRETAPPING == 1
udpBridge->printData(p, data);
#endif
store_address_t storeId;
ReturnValue_t returnValue =
udpBridge->tcStore->addData(&storeId, reinterpret_cast<uint8_t*>(p->payload), p->len);
if (returnValue != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UDP Server: Data storage failed" << std::endl;
#endif
pbuf_free(p_tx);
return;
}
TmTcMessage message(storeId);
if (udpBridge->tmTcReceptionQueue->sendToDefault(&message) != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcLwIpUdpBridgw::udp_server_receive_callback:"
<< " Sending message to queue failed" << std::endl;
#endif
udpBridge->tcStore->deleteData(storeId);
}
}
/* Free the p_tx buffer */
pbuf_free(p_tx);
} }
/* Caller must ensure thread-safety */ /* Caller must ensure thread-safety */
bool TmTcLwIpUdpBridge::comLinkUp() const { bool TmTcLwIpUdpBridge::comLinkUp() const { return communicationLinkUp; }
return communicationLinkUp;
}
/* Caller must ensure thread-safety */ /* Caller must ensure thread-safety */
void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) { void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) {
if(connect) { if (connect) {
/* Physical connection does not mean there is a recipient to send packets too. /* Physical connection does not mean there is a recipient to send packets too.
This will be done by the receive callback! */ This will be done by the receive callback! */
physicalConnection = true; physicalConnection = true;
} } else {
else { physicalConnection = false;
physicalConnection = false; /* If there is no physical connection, we can't send anything back */
/* If there is no physical connection, we can't send anything back */ registerCommDisconnect();
registerCommDisconnect(); }
}
} }

View File

@ -2,9 +2,8 @@
#define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ #define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#include <fsfw/tmtcservices/TmTcBridge.h> #include <fsfw/tmtcservices/TmTcBridge.h>
#include <lwip/udp.h>
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include <lwip/udp.h>
#define TCPIP_RECV_WIRETAPPING 0 #define TCPIP_RECV_WIRETAPPING 0
@ -12,68 +11,67 @@
* This bridge is used to forward TMTC packets received via LwIP UDP to the internal software bus. * This bridge is used to forward TMTC packets received via LwIP UDP to the internal software bus.
*/ */
class TmTcLwIpUdpBridge : public TmTcBridge { class TmTcLwIpUdpBridge : public TmTcBridge {
friend class UdpTcLwIpPollingTask; friend class UdpTcLwIpPollingTask;
public:
TmTcLwIpUdpBridge(object_id_t objectId,
object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
object_id_t tcStoreId);
virtual ~TmTcLwIpUdpBridge();
virtual ReturnValue_t initialize() override; public:
ReturnValue_t udp_server_init(); TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
object_id_t tcStoreId);
virtual ~TmTcLwIpUdpBridge();
/** virtual ReturnValue_t initialize() override;
* In addition to default implementation, ethernet link status is checked. ReturnValue_t udp_server_init();
* @param operationCode
* @return
*/
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/** TM Send implementation uses udp_send function from lwIP stack /**
* @param data * In addition to default implementation, ethernet link status is checked.
* @param dataLen * @param operationCode
* @return * @return
*/ */
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/** /** TM Send implementation uses udp_send function from lwIP stack
* @brief This function is called when an UDP datagram has been * @param data
* received on the port UDP_PORT. * @param dataLen
* @param arg * @return
* @param upcb_ */
* @param p virtual ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override;
* @param addr Source address which will be bound to TmTcUdpBridge::lastAdd
* @param port
*/
static void udp_server_receive_callback(void *arg,
struct udp_pcb *upcb_, struct pbuf *p, const ip_addr_t *addr,
u16_t port);
/** /**
* Check whether the communication link is up. * @brief This function is called when an UDP datagram has been
* Caller must ensure thread-safety by using the bridge lock. * received on the port UDP_PORT.
* @return * @param arg
*/ * @param upcb_
bool comLinkUp() const; * @param p
* @param addr Source address which will be bound to TmTcUdpBridge::lastAdd
* @param port
*/
static void udp_server_receive_callback(void *arg, struct udp_pcb *upcb_, struct pbuf *p,
const ip_addr_t *addr, u16_t port);
private: /**
struct udp_pcb *upcb = nullptr; * Check whether the communication link is up.
ip_addr_t lastAdd; * Caller must ensure thread-safety by using the bridge lock.
u16_t lastPort = 0; * @return
bool physicalConnection = false; */
MutexIF* bridgeLock = nullptr; bool comLinkUp() const;
private:
struct udp_pcb *upcb = nullptr;
ip_addr_t lastAdd;
u16_t lastPort = 0;
bool physicalConnection = false;
MutexIF *bridgeLock = nullptr;
#if TCPIP_RECV_WIRETAPPING == 1 #if TCPIP_RECV_WIRETAPPING == 1
bool connectFlag = false; bool connectFlag = false;
#endif #endif
/** /**
* Used to notify bridge about change in the physical ethernet connection. * Used to notify bridge about change in the physical ethernet connection.
* Connection does not mean that replies are possible (recipient not set yet), but * Connection does not mean that replies are possible (recipient not set yet), but
* disconnect means that we can't send anything. Caller must ensure thread-safety * disconnect means that we can't send anything. Caller must ensure thread-safety
* by using the bridge lock. * by using the bridge lock.
*/ */
void physicalConnectStatusChange(bool connect); void physicalConnectStatusChange(bool connect);
}; };
#endif /* BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ */ #endif /* BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ */

View File

@ -1,66 +1,60 @@
#include "UdpTcLwIpPollingTask.h" #include "UdpTcLwIpPollingTask.h"
#include "TmTcLwIpUdpBridge.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include "app_dhcp.h"
#include "networking.h"
#include <hardware_init.h> #include <hardware_init.h>
#include "TmTcLwIpUdpBridge.h"
#include "app_dhcp.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "lwip/timeouts.h" #include "lwip/timeouts.h"
#include "networking.h"
UdpTcLwIpPollingTask::UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, UdpTcLwIpPollingTask::UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId,
struct netif* gnetif): struct netif* gnetif)
SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) { : SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) {}
}
UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() { UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() {}
}
ReturnValue_t UdpTcLwIpPollingTask::initialize() { ReturnValue_t UdpTcLwIpPollingTask::initialize() {
udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId); udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId);
if(udpBridge == nullptr) { if (udpBridge == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
if (netif_is_link_up(gnetif)) { if (netif_is_link_up(gnetif)) {
networking::setEthCableConnected(true); networking::setEthCableConnected(true);
} }
return RETURN_OK; return RETURN_OK;
} }
/* Poll the EMAC Interface and pass content to the network interface (lwIP) */ /* Poll the EMAC Interface and pass content to the network interface (lwIP) */
ReturnValue_t UdpTcLwIpPollingTask::performOperation(uint8_t operationCode) { ReturnValue_t UdpTcLwIpPollingTask::performOperation(uint8_t operationCode) {
/* Read a received packet from the Ethernet buffers and send it /* Read a received packet from the Ethernet buffers and send it
to the lwIP for handling */ to the lwIP for handling */
ethernetif_input(gnetif); ethernetif_input(gnetif);
/* Handle timeouts */ /* Handle timeouts */
sys_check_timeouts(); sys_check_timeouts();
#if LWIP_NETIF_LINK_CALLBACK == 1 #if LWIP_NETIF_LINK_CALLBACK == 1
networking::ethernetLinkPeriodicHandle(gnetif); networking::ethernetLinkPeriodicHandle(gnetif);
#endif #endif
if(udpBridge != nullptr) { if (udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock); MutexGuard lg(udpBridge->bridgeLock);
/* In case ethernet cable is disconnected */ /* In case ethernet cable is disconnected */
if(not networking::getEthCableConnected() and udpBridge->comLinkUp()) { if (not networking::getEthCableConnected() and udpBridge->comLinkUp()) {
udpBridge->physicalConnectStatusChange(false); udpBridge->physicalConnectStatusChange(false);
} } else if (networking::getEthCableConnected() and not udpBridge->comLinkUp()) {
else if(networking::getEthCableConnected() and not udpBridge->comLinkUp()) { udpBridge->physicalConnectStatusChange(true);
udpBridge->physicalConnectStatusChange(true);
}
} }
}
#if LWIP_DHCP == 1 #if LWIP_DHCP == 1
DHCP_Periodic_Handle(gnetif); DHCP_Periodic_Handle(gnetif);
#endif #endif
return RETURN_OK; return RETURN_OK;
} }

View File

@ -2,9 +2,8 @@
#define BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ #define BSP_STM32_RTEMS_EMACPOLLINGTASK_H_
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h> #include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <lwip/netif.h> #include <lwip/netif.h>
class TmTcLwIpUdpBridge; class TmTcLwIpUdpBridge;
@ -13,29 +12,28 @@ class TmTcLwIpUdpBridge;
* @brief Separate task to poll EMAC interface. * @brief Separate task to poll EMAC interface.
* Polled data is passed to the netif (lwIP) * Polled data is passed to the netif (lwIP)
*/ */
class UdpTcLwIpPollingTask: class UdpTcLwIpPollingTask : public SystemObject,
public SystemObject, public ExecutableObjectIF,
public ExecutableObjectIF, public HasReturnvaluesIF {
public HasReturnvaluesIF { public:
public: UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif* gnetif);
UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif* gnetif); virtual ~UdpTcLwIpPollingTask();
virtual ~UdpTcLwIpPollingTask();
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
/** /**
* Executed periodically. * Executed periodically.
* @param operationCode * @param operationCode
* @return * @return
*/ */
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
private:
static const uint8_t PERIODIC_HANDLE_TRIGGER = 5; private:
uint8_t periodicHandleCounter; static const uint8_t PERIODIC_HANDLE_TRIGGER = 5;
object_id_t bridgeId = 0; uint8_t periodicHandleCounter;
TmTcLwIpUdpBridge* udpBridge = nullptr; object_id_t bridgeId = 0;
struct netif* gnetif = nullptr; TmTcLwIpUdpBridge* udpBridge = nullptr;
struct netif* gnetif = nullptr;
}; };
#endif /* BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ */ #endif /* BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ */

View File

@ -1,13 +1,12 @@
#include "OBSWConfig.h"
#include "app_dhcp.h" #include "app_dhcp.h"
#include "app_ethernet.h"
#include "networking.h"
#include "udp_config.h"
#include "ethernetif.h"
#include "OBSWConfig.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "networking.h"
#include "stm32h7xx_nucleo.h" #include "stm32h7xx_nucleo.h"
#include "udp_config.h"
#if LWIP_DHCP == 1 #if LWIP_DHCP == 1
@ -24,57 +23,56 @@ void handle_dhcp_down(struct netif* netif);
* @param None * @param None
* @retval None * @retval None
*/ */
void DHCP_Process(struct netif *netif) void DHCP_Process(struct netif* netif) {
{ struct dhcp* dhcp = NULL;
struct dhcp* dhcp = NULL; switch (DHCP_state) {
switch (DHCP_state) {
case DHCP_START: { case DHCP_START: {
handle_dhcp_start(netif); handle_dhcp_start(netif);
break; break;
} }
case DHCP_WAIT_ADDRESS: { case DHCP_WAIT_ADDRESS: {
handle_dhcp_wait(netif, &dhcp); handle_dhcp_wait(netif, &dhcp);
break; break;
} }
case DHCP_LINK_DOWN: { case DHCP_LINK_DOWN: {
handle_dhcp_down(netif); handle_dhcp_down(netif);
break; break;
} }
default: { default: {
break; break;
}
} }
}
} }
void handle_dhcp_timeout(struct netif* netif) { void handle_dhcp_timeout(struct netif* netif) {
ip_addr_t ipaddr; ip_addr_t ipaddr;
ip_addr_t netmask; ip_addr_t netmask;
ip_addr_t gw; ip_addr_t gw;
DHCP_state = DHCP_TIMEOUT; DHCP_state = DHCP_TIMEOUT;
/* Stop DHCP */ /* Stop DHCP */
dhcp_stop(netif); dhcp_stop(netif);
/* Static address used */ /* Static address used */
networking::setLwipAddresses(&ipaddr, &netmask, &gw); networking::setLwipAddresses(&ipaddr, &netmask, &gw);
netif_set_addr(netif, &ipaddr, &netmask, &gw); netif_set_addr(netif, &ipaddr, &netmask, &gw);
printf("DHCP Timeout\n\r"); printf("DHCP Timeout\n\r");
uint8_t iptxt[20]; uint8_t iptxt[20];
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif))); sprintf((char*)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
printf("Assigning static IP address: %s\n", iptxt); printf("Assigning static IP address: %s\n", iptxt);
#if defined FSFW_OSAL_FREERTOS #if defined FSFW_OSAL_FREERTOS
ETH_HandleTypeDef* handle = getEthernetHandle(); ETH_HandleTypeDef* handle = getEthernetHandle();
handle->gState = HAL_ETH_STATE_READY; handle->gState = HAL_ETH_STATE_READY;
#endif #endif
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_On(LED1); BSP_LED_On(LED1);
BSP_LED_Off(LED2); BSP_LED_Off(LED2);
#endif #endif
#endif #endif
} }
@ -84,74 +82,67 @@ void handle_dhcp_timeout(struct netif* netif) {
* @param netif * @param netif
* @retval None * @retval None
*/ */
void DHCP_Periodic_Handle(struct netif *netif) void DHCP_Periodic_Handle(struct netif* netif) {
{ /* Fine DHCP periodic process every 500ms */
/* Fine DHCP periodic process every 500ms */ if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) { DHCPfineTimer = HAL_GetTick();
DHCPfineTimer = HAL_GetTick(); /* process DHCP state machine */
/* process DHCP state machine */ DHCP_Process(netif);
DHCP_Process(netif); }
}
} }
void handle_dhcp_start(struct netif* netif) { void handle_dhcp_start(struct netif* netif) {
printf("handle_dhcp_start: Looking for DHCP server ...\n\r"); printf("handle_dhcp_start: Looking for DHCP server ...\n\r");
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_Off(LED1); BSP_LED_Off(LED1);
BSP_LED_Off(LED2); BSP_LED_Off(LED2);
#endif #endif
#endif #endif
ip_addr_set_zero_ip4(&netif->ip_addr); ip_addr_set_zero_ip4(&netif->ip_addr);
ip_addr_set_zero_ip4(&netif->netmask); ip_addr_set_zero_ip4(&netif->netmask);
ip_addr_set_zero_ip4(&netif->gw); ip_addr_set_zero_ip4(&netif->gw);
dhcp_start(netif); dhcp_start(netif);
DHCP_state = DHCP_WAIT_ADDRESS; DHCP_state = DHCP_WAIT_ADDRESS;
} }
void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) { void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) {
if (dhcp_supplied_address(netif)) { if (dhcp_supplied_address(netif)) {
DHCP_state = DHCP_ADDRESS_ASSIGNED; DHCP_state = DHCP_ADDRESS_ASSIGNED;
printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif))); printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
printf("Listener port: %d\n\r", UDP_SERVER_PORT); printf("Listener port: %d\n\r", UDP_SERVER_PORT);
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_On(LED1); BSP_LED_On(LED1);
BSP_LED_Off(LED2); BSP_LED_Off(LED2);
#endif #endif
#endif #endif
} } else {
else { *dhcp = (struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
*dhcp = (struct dhcp*) netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
/* DHCP timeout */ /* DHCP timeout */
if ((*dhcp)->tries > MAX_DHCP_TRIES) if ((*dhcp)->tries > MAX_DHCP_TRIES) {
{ handle_dhcp_timeout(netif);
handle_dhcp_timeout(netif);
}
} }
}
} }
void handle_dhcp_down(struct netif* netif) { void handle_dhcp_down(struct netif* netif) {
DHCP_state = DHCP_OFF; DHCP_state = DHCP_OFF;
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
printf("DHCP_Process: The network cable is not connected.\n\r"); printf("DHCP_Process: The network cable is not connected.\n\r");
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_Off(LED1); BSP_LED_Off(LED1);
BSP_LED_On(LED2); BSP_LED_On(LED2);
#endif #endif
#endif #endif
/* Global boolean to track ethernet connection */ /* Global boolean to track ethernet connection */
networking::setEthCableConnected(false); networking::setEthCableConnected(false);
} }
uint8_t get_dhcp_state() { uint8_t get_dhcp_state() { return DHCP_state; }
return DHCP_state;
}
void set_dhcp_state(uint8_t new_state) { void set_dhcp_state(uint8_t new_state) { DHCP_state = new_state; }
DHCP_state = new_state;
}
#endif /* LWIP_DHCP == 1 */ #endif /* LWIP_DHCP == 1 */

View File

@ -12,12 +12,12 @@ extern "C" {
#include "lwip/netif.h" #include "lwip/netif.h"
/* DHCP process states */ /* DHCP process states */
#define DHCP_OFF (uint8_t) 0 #define DHCP_OFF (uint8_t)0
#define DHCP_START (uint8_t) 1 #define DHCP_START (uint8_t)1
#define DHCP_WAIT_ADDRESS (uint8_t) 2 #define DHCP_WAIT_ADDRESS (uint8_t)2
#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3 #define DHCP_ADDRESS_ASSIGNED (uint8_t)3
#define DHCP_TIMEOUT (uint8_t) 4 #define DHCP_TIMEOUT (uint8_t)4
#define DHCP_LINK_DOWN (uint8_t) 5 #define DHCP_LINK_DOWN (uint8_t)5
uint8_t get_dhcp_state(); uint8_t get_dhcp_state();
void set_dhcp_state(uint8_t new_state); void set_dhcp_state(uint8_t new_state);

View File

@ -1,17 +1,18 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "app_ethernet.h" #include "app_ethernet.h"
#include "ethernetif.h" #include "ethernetif.h"
#include "udp_config.h"
#include "networking.h" #include "networking.h"
#include "udp_config.h"
#if LWIP_DHCP #if LWIP_DHCP
#include "app_dhcp.h" #include "app_dhcp.h"
#endif #endif
#include <lwipopts.h>
#include <lwip/netif.h>
#include <stm32h7xx_nucleo.h>
#include <OBSWConfig.h> #include <OBSWConfig.h>
#include <lwip/netif.h>
#include <lwipopts.h>
#include <stm32h7xx_nucleo.h>
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -22,55 +23,49 @@ uint32_t ethernetLinkTimer = 0;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
void handle_status_change(struct netif* netif, bool link_up); void handle_status_change(struct netif* netif, bool link_up);
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/** /**
* @brief Notify the User about the network interface config status * @brief Notify the User about the network interface config status
* @param netif: the network interface * @param netif: the network interface
* @retval None * @retval None
*/ */
void networking::ethernetLinkStatusUpdated(struct netif *netif) void networking::ethernetLinkStatusUpdated(struct netif* netif) {
{ if (netif_is_link_up(netif)) {
if (netif_is_link_up(netif)) networking::setEthCableConnected(true);
{ handle_status_change(netif, true);
networking::setEthCableConnected(true); } else {
handle_status_change(netif, true); networking::setEthCableConnected(false);
} handle_status_change(netif, false);
else }
{
networking::setEthCableConnected(false);
handle_status_change(netif, false);
}
} }
void handle_status_change(struct netif* netif, bool link_up) { void handle_status_change(struct netif* netif, bool link_up) {
if(link_up) { if (link_up) {
#if LWIP_DHCP #if LWIP_DHCP
/* Update DHCP state machine */ /* Update DHCP state machine */
set_dhcp_state(DHCP_START); set_dhcp_state(DHCP_START);
#else #else
uint8_t iptxt[20]; uint8_t iptxt[20];
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif))); sprintf((char*)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt, printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt,
UDP_SERVER_PORT); UDP_SERVER_PORT);
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_On(LED1); BSP_LED_On(LED1);
BSP_LED_Off(LED2); BSP_LED_Off(LED2);
#endif #endif
#endif /* LWIP_DHCP */ #endif /* LWIP_DHCP */
} } else {
else { printf("Network cable disconnected\n\r");
printf("Network cable disconnected\n\r");
#if LWIP_DHCP #if LWIP_DHCP
/* Update DHCP state machine */ /* Update DHCP state machine */
set_dhcp_state(DHCP_LINK_DOWN); set_dhcp_state(DHCP_LINK_DOWN);
#else #else
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
BSP_LED_Off(LED1); BSP_LED_Off(LED1);
BSP_LED_On(LED2); BSP_LED_On(LED2);
#endif #endif
#endif /* LWIP_DHCP */ #endif /* LWIP_DHCP */
} }
} }
#if LWIP_NETIF_LINK_CALLBACK #if LWIP_NETIF_LINK_CALLBACK
@ -80,14 +75,12 @@ void handle_status_change(struct netif* netif, bool link_up) {
* @param netif * @param netif
* @retval None * @retval None
*/ */
void networking::ethernetLinkPeriodicHandle(struct netif *netif) void networking::ethernetLinkPeriodicHandle(struct netif* netif) {
{ /* Ethernet Link every 100ms */
/* Ethernet Link every 100ms */ if (HAL_GetTick() - ethernetLinkTimer >= 100) {
if (HAL_GetTick() - ethernetLinkTimer >= 100) ethernetLinkTimer = HAL_GetTick();
{ ethernet_link_check_state(netif);
ethernetLinkTimer = HAL_GetTick(); }
ethernet_link_check_state(netif);
}
} }
#endif /* LWIP_NETIF_LINK_CALLBACK */ #endif /* LWIP_NETIF_LINK_CALLBACK */

View File

@ -1,54 +1,54 @@
/** /**
****************************************************************************** ******************************************************************************
* @file LwIP/LwIP_UDP_Echo_Client/Inc/app_ethernet.h * @file LwIP/LwIP_UDP_Echo_Client/Inc/app_ethernet.h
* @author MCD Application Team * @author MCD Application Team
* @brief Header for app_ethernet.c module * @brief Header for app_ethernet.c module
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V. * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met: * modification, are permitted, provided that the following conditions are met:
* *
* 1. Redistribution of source code must retain the above copyright notice, * 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other * 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products * contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission. * derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this * 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or * software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics. * microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under * 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under * this license is void and will automatically terminate your rights under
* this license. * this license.
* *
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
****************************************************************************** ******************************************************************************
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef EXAMPLE_COMMON_APP_ETHERNET_H #ifndef EXAMPLE_COMMON_APP_ETHERNET_H
#define EXAMPLE_COMMON_APP_ETHERNET_H #define EXAMPLE_COMMON_APP_ETHERNET_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
@ -65,7 +65,7 @@ namespace networking {
void ethernetLinkStatusUpdated(struct netif *netif); void ethernetLinkStatusUpdated(struct netif *netif);
void ethernetLinkPeriodicHandle(struct netif *netif); void ethernetLinkPeriodicHandle(struct netif *netif);
} } // namespace networking
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -73,6 +73,4 @@ void ethernetLinkPeriodicHandle(struct netif *netif);
#endif /* EXAMPLE_COMMON_APP_ETHERNET_H */ #endif /* EXAMPLE_COMMON_APP_ETHERNET_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,59 +1,60 @@
/** /**
****************************************************************************** ******************************************************************************
* @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c * @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c
* @author MCD Application Team * @author MCD Application Team
* @brief This file implements Ethernet network interface drivers for lwIP * @brief This file implements Ethernet network interface drivers for lwIP
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V. * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met: * modification, are permitted, provided that the following conditions are met:
* *
* 1. Redistribution of source code must retain the above copyright notice, * 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other * 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products * contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission. * derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this * 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or * software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics. * microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under * 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under * this license is void and will automatically terminate your rights under
* this license. * this license.
* *
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
****************************************************************************** ******************************************************************************
*/ */
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "fsfw/FSFW.h"
#include "ethernetif.h" #include "ethernetif.h"
#include <string.h>
#include <lan8742.h> #include <lan8742.h>
#include <stm32h7xx_hal.h>
#include <lwip/netif.h> #include <lwip/netif.h>
#include <lwip/opt.h> #include <lwip/opt.h>
#include <lwip/timeouts.h> #include <lwip/timeouts.h>
#include <netif/etharp.h> #include <netif/etharp.h>
#include <stm32h7xx_hal.h>
#include <string.h>
#include "fsfw/FSFW.h"
#ifdef FSFW_OSAL_RTEMS #ifdef FSFW_OSAL_RTEMS
#include <rtems.h> #include <rtems.h>
@ -87,35 +88,45 @@
passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen) passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
*/ */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */ #if defined(__ICCARM__) /*!< IAR Compiler */
#pragma location=0x30040000 #pragma location = 0x30040000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30040060 #pragma location = 0x30040060
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location=0x30040200 #pragma location = 0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */ uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */ #elif defined(__CC_ARM) /* MDK ARM Compiler */
__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ __attribute__((section(".RxDecripSection")))
__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((section(".RxArraySection"))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */ __attribute__((section(".TxDecripSection")))
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((section(".RxArraySection")))
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
#elif defined ( __GNUC__ ) /* GNU Compiler */ #elif defined(__GNUC__) /* GNU Compiler */
#ifdef FSFW_OSAL_RTEMS #ifdef FSFW_OSAL_RTEMS
/* Put into special RTEMS section and align correctly */ /* Put into special RTEMS section and align correctly */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
__attribute__((section(".bsp_nocache"),
__aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Rx DMA Descriptors */
/* Put into special RTEMS section and align correctly */ /* Put into special RTEMS section and align correctly */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
__attribute__((section(".bsp_nocache"),
__aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */
/* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely placing it */ /* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely placing it */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
#elif defined FSFW_OSAL_FREERTOS #elif defined FSFW_OSAL_FREERTOS
/* Placement and alignment specified in linker script here */ /* Placement and alignment specified in linker script here */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
__attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]
__attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
#endif /* FSFW_FREERTOS */ #endif /* FSFW_FREERTOS */
#endif /* defined ( __GNUC__ ) */ #endif /* defined ( __GNUC__ ) */
@ -124,7 +135,7 @@ uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] __attribute__((section(".Rx
bool ethernet_cable_connected; bool ethernet_cable_connected;
struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT]; struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT];
uint32_t current_pbuf_idx =0; uint32_t current_pbuf_idx = 0;
ETH_HandleTypeDef EthHandle; ETH_HandleTypeDef EthHandle;
ETH_TxPacketConfig TxConfig; ETH_TxPacketConfig TxConfig;
@ -136,32 +147,28 @@ u32_t sys_now(void);
void pbuf_free_custom(struct pbuf *p); void pbuf_free_custom(struct pbuf *p);
int32_t ETH_PHY_IO_Init(void); int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit (void); int32_t ETH_PHY_IO_DeInit(void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void); int32_t ETH_PHY_IO_GetTick(void);
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg,
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick};
ETH_PHY_IO_DeInit,
ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg,
ETH_PHY_IO_GetTick};
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/******************************************************************************* /*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH) LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/ *******************************************************************************/
/** /**
* @brief In this function, the hardware should be initialized. * @brief In this function, the hardware should be initialized.
* Called from ethernetif_init(). * Called from ethernetif_init().
* *
* @param netif the already initialized lwip network interface structure * @param netif the already initialized lwip network interface structure
* for this ethernetif * for this ethernetif
*/ */
static void low_level_init(struct netif *netif) static void low_level_init(struct netif *netif) {
{
uint32_t idx = 0; uint32_t idx = 0;
uint8_t macaddress[6]= {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5}; uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2,
ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
EthHandle.Instance = ETH; EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress; EthHandle.Init.MACAddr = macaddress;
@ -177,12 +184,12 @@ static void low_level_init(struct netif *netif)
netif->hwaddr_len = ETHARP_HWADDR_LEN; netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */ /* set MAC hardware address */
netif->hwaddr[0] = 0x02; netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x00; netif->hwaddr[1] = 0x00;
netif->hwaddr[2] = 0x00; netif->hwaddr[2] = 0x00;
netif->hwaddr[3] = 0x00; netif->hwaddr[3] = 0x00;
netif->hwaddr[4] = 0x00; netif->hwaddr[4] = 0x00;
netif->hwaddr[5] = 0x00; netif->hwaddr[5] = 0x00;
/* maximum transfer unit */ /* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD; netif->mtu = ETH_MAX_PAYLOAD;
@ -191,8 +198,7 @@ static void low_level_init(struct netif *netif)
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++) for (idx = 0; idx < ETH_RX_DESC_CNT; idx++) {
{
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL); HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
/* Set Custom pbuf free function */ /* Set Custom pbuf free function */
@ -200,7 +206,7 @@ static void low_level_init(struct netif *netif)
} }
/* Set Tx packet config common parameters */ /* Set Tx packet config common parameters */
memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig)); memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
@ -212,47 +218,41 @@ static void low_level_init(struct netif *netif)
LAN8742_Init(&LAN8742); LAN8742_Init(&LAN8742);
ethernet_link_check_state(netif); ethernet_link_check_state(netif);
} }
/** /**
* @brief This function should do the actual transmission of the packet. The packet is * @brief This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf * contained in the pbuf that is passed to the function. This pbuf
* might be chained. * might be chained.
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent * @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent * an err_t value if the packet couldn't be sent
* *
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue * strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet * to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers). * dropped because of memory failure (except for the TCP timers).
*/ */
static err_t low_level_output(struct netif *netif, struct pbuf *p) static err_t low_level_output(struct netif *netif, struct pbuf *p) {
{ uint32_t i = 0, framelen = 0;
uint32_t i=0, framelen = 0;
struct pbuf *q; struct pbuf *q;
err_t errval = ERR_OK; err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
for(q = p; q != NULL; q = q->next) for (q = p; q != NULL; q = q->next) {
{ if (i >= ETH_TX_DESC_CNT) return ERR_IF;
if(i >= ETH_TX_DESC_CNT)
return ERR_IF;
Txbuffer[i].buffer = q->payload; Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len; Txbuffer[i].len = q->len;
framelen += q->len; framelen += q->len;
if(i>0) if (i > 0) {
{ Txbuffer[i - 1].next = &Txbuffer[i];
Txbuffer[i-1].next = &Txbuffer[i];
} }
if(q->next == NULL) if (q->next == NULL) {
{
Txbuffer[i].next = NULL; Txbuffer[i].next = NULL;
} }
@ -264,64 +264,57 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20); HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20);
if(ret != HAL_OK) { if (ret != HAL_OK) {
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret); printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
} }
return errval; return errval;
} }
/** /**
* @brief Should allocate a pbuf and transfer the bytes of the incoming * @brief Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf. * packet from the interface into the pbuf.
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header) * @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error * NULL on memory error
*/ */
static struct pbuf * low_level_input(struct netif *netif) static struct pbuf *low_level_input(struct netif *netif) {
{
struct pbuf *p = NULL; struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff; ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0; uint32_t framelength = 0;
if (HAL_ETH_IsRxDataAvailable(&EthHandle)) if (HAL_ETH_IsRxDataAvailable(&EthHandle)) {
{
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff); HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff);
HAL_ETH_GetRxDataLength(&EthHandle, &framelength); HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
/* Invalidate data cache for ETH Rx Buffers */ /* Invalidate data cache for ETH Rx Buffers */
SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff, (ETH_RX_DESC_CNT*ETH_RX_BUFFER_SIZE)); SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff, (ETH_RX_DESC_CNT * ETH_RX_BUFFER_SIZE));
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_POOL, &rx_pbuf[current_pbuf_idx], RxBuff.buffer, ETH_RX_BUFFER_SIZE); p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_POOL, &rx_pbuf[current_pbuf_idx],
if(current_pbuf_idx < (ETH_RX_DESC_CNT -1)) RxBuff.buffer, ETH_RX_BUFFER_SIZE);
{ if (current_pbuf_idx < (ETH_RX_DESC_CNT - 1)) {
current_pbuf_idx++; current_pbuf_idx++;
} } else {
else
{
current_pbuf_idx = 0; current_pbuf_idx = 0;
} }
return p; return p;
} } else {
else
{
return NULL; return NULL;
} }
} }
/** /**
* @brief This function is the ethernetif_input task, it is processed when a packet * @brief This function is the ethernetif_input task, it is processed when a packet
* is ready to be read from the interface. It uses the function low_level_input() * is ready to be read from the interface. It uses the function low_level_input()
* that should handle the actual reception of bytes from the network * that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and * interface. Then the type of the received packet is determined and
* the appropriate input function is called. * the appropriate input function is called.
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
*/ */
void ethernetif_input(struct netif *netif) void ethernetif_input(struct netif *netif) {
{
err_t err; err_t err;
struct pbuf *p; struct pbuf *p;
@ -334,8 +327,7 @@ void ethernetif_input(struct netif *netif)
/* entry point to the LwIP stack */ /* entry point to the LwIP stack */
err = netif->input(p, netif); err = netif->input(p, netif);
if (err != ERR_OK) if (err != ERR_OK) {
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p); pbuf_free(p);
p = NULL; p = NULL;
@ -345,19 +337,18 @@ void ethernetif_input(struct netif *netif)
} }
/** /**
* @brief Should be called at the beginning of the program to set up the * @brief Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the * network interface. It calls the function low_level_init() to do the
* actual setup of the hardware. * actual setup of the hardware.
* *
* This function should be passed as a parameter to netif_add(). * This function should be passed as a parameter to netif_add().
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized * @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated * ERR_MEM if private data couldn't be allocated
* any other err_t on error * any other err_t on error
*/ */
err_t ethernetif_init(struct netif *netif) err_t ethernetif_init(struct netif *netif) {
{
LWIP_ASSERT("netif != NULL", (netif != NULL)); LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
@ -381,14 +372,12 @@ err_t ethernetif_init(struct netif *netif)
} }
/** /**
* @brief Custom Rx pbuf free callback * @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed * @param pbuf: pbuf to be freed
* @retval None * @retval None
*/ */
void pbuf_free_custom(struct pbuf *p) void pbuf_free_custom(struct pbuf *p) {
{ if (p != NULL) {
if(p != NULL)
{
p->flags = 0; p->flags = 0;
p->next = NULL; p->next = NULL;
p->len = p->tot_len = 0; p->len = p->tot_len = 0;
@ -398,26 +387,22 @@ void pbuf_free_custom(struct pbuf *p)
} }
/** /**
* @brief Returns the current time in milliseconds * @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1 * when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None * @param None
* @retval Current Time value * @retval Current Time value
*/ */
u32_t sys_now(void) u32_t sys_now(void) { return HAL_GetTick(); }
{
return HAL_GetTick();
}
/******************************************************************************* /*******************************************************************************
Ethernet MSP Routines Ethernet MSP Routines
*******************************************************************************/ *******************************************************************************/
/** /**
* @brief Initializes the ETH MSP. * @brief Initializes the ETH MSP.
* @param heth: ETH handle * @param heth: ETH handle
* @retval None * @retval None
*/ */
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
{
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
/* Ethernett MSP init: RMII Mode */ /* Ethernett MSP init: RMII Mode */
@ -428,7 +413,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE();
/* Ethernet pins configuration ************************************************/ /* Ethernet pins configuration ************************************************/
/* /*
RMII_REF_CLK ----------------------> PA1 RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2 RMII_MDIO -------------------------> PA2
@ -459,7 +444,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PG2, PG11, PG13 and PG14 */ /* Configure PG2, PG11, PG13 and PG14 */
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
#if NO_SYS == 0 #if NO_SYS == 0
@ -478,12 +463,11 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
PHI IO Functions PHI IO Functions
*******************************************************************************/ *******************************************************************************/
/** /**
* @brief Initializes the MDIO interface GPIO and clocks. * @brief Initializes the MDIO interface GPIO and clocks.
* @param None * @param None
* @retval 0 if OK, -1 if ERROR * @retval 0 if OK, -1 if ERROR
*/ */
int32_t ETH_PHY_IO_Init(void) int32_t ETH_PHY_IO_Init(void) {
{
/* We assume that MDIO GPIO configuration is already done /* We assume that MDIO GPIO configuration is already done
in the ETH_MspInit() else it should be done here in the ETH_MspInit() else it should be done here
*/ */
@ -495,26 +479,21 @@ int32_t ETH_PHY_IO_Init(void)
} }
/** /**
* @brief De-Initializes the MDIO interface . * @brief De-Initializes the MDIO interface .
* @param None * @param None
* @retval 0 if OK, -1 if ERROR * @retval 0 if OK, -1 if ERROR
*/ */
int32_t ETH_PHY_IO_DeInit (void) int32_t ETH_PHY_IO_DeInit(void) { return 0; }
{
return 0;
}
/** /**
* @brief Read a PHY register through the MDIO interface. * @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address * @param DevAddr: PHY port address
* @param RegAddr: PHY register address * @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value * @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error * @retval 0 if OK -1 if Error
*/ */
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) {
{ if (HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK) {
if(HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK)
{
return -1; return -1;
} }
@ -522,16 +501,14 @@ int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal
} }
/** /**
* @brief Write a value to a PHY register through the MDIO interface. * @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address * @param DevAddr: PHY port address
* @param RegAddr: PHY register address * @param RegAddr: PHY register address
* @param RegVal: Value to be written * @param RegVal: Value to be written
* @retval 0 if OK -1 if Error * @retval 0 if OK -1 if Error
*/ */
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) {
{ if (HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK) {
if(HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK)
{
return -1; return -1;
} }
@ -539,62 +516,53 @@ int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
} }
/** /**
* @brief Get the time in millisecons used for internal PHY driver process. * @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value * @retval Time value
*/ */
int32_t ETH_PHY_IO_GetTick(void) int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); }
{
return HAL_GetTick();
}
/** /**
* @brief * @brief
* @retval None * @retval None
*/ */
void ethernet_link_check_state(struct netif *netif) void ethernet_link_check_state(struct netif *netif) {
{
ETH_MACConfigTypeDef MACConf; ETH_MACConfigTypeDef MACConf;
uint32_t PHYLinkState; uint32_t PHYLinkState;
uint32_t linkchanged = 0, speed = 0, duplex =0; uint32_t linkchanged = 0, speed = 0, duplex = 0;
PHYLinkState = LAN8742_GetLinkState(&LAN8742); PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) {
{
HAL_ETH_Stop(&EthHandle); HAL_ETH_Stop(&EthHandle);
netif_set_down(netif); netif_set_down(netif);
netif_set_link_down(netif); netif_set_link_down(netif);
} } else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) {
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) switch (PHYLinkState) {
{ case LAN8742_STATUS_100MBITS_FULLDUPLEX:
switch (PHYLinkState) duplex = ETH_FULLDUPLEX_MODE;
{ speed = ETH_SPEED_100M;
case LAN8742_STATUS_100MBITS_FULLDUPLEX: linkchanged = 1;
duplex = ETH_FULLDUPLEX_MODE; break;
speed = ETH_SPEED_100M; case LAN8742_STATUS_100MBITS_HALFDUPLEX:
linkchanged = 1; duplex = ETH_HALFDUPLEX_MODE;
break; speed = ETH_SPEED_100M;
case LAN8742_STATUS_100MBITS_HALFDUPLEX: linkchanged = 1;
duplex = ETH_HALFDUPLEX_MODE; break;
speed = ETH_SPEED_100M; case LAN8742_STATUS_10MBITS_FULLDUPLEX:
linkchanged = 1; duplex = ETH_FULLDUPLEX_MODE;
break; speed = ETH_SPEED_10M;
case LAN8742_STATUS_10MBITS_FULLDUPLEX: linkchanged = 1;
duplex = ETH_FULLDUPLEX_MODE; break;
speed = ETH_SPEED_10M; case LAN8742_STATUS_10MBITS_HALFDUPLEX:
linkchanged = 1; duplex = ETH_HALFDUPLEX_MODE;
break; speed = ETH_SPEED_10M;
case LAN8742_STATUS_10MBITS_HALFDUPLEX: linkchanged = 1;
duplex = ETH_HALFDUPLEX_MODE; break;
speed = ETH_SPEED_10M; default:
linkchanged = 1; break;
break;
default:
break;
} }
if(linkchanged) if (linkchanged) {
{
/* Get MAC Config MAC */ /* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&EthHandle, &MACConf); HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
MACConf.DuplexMode = duplex; MACConf.DuplexMode = duplex;
@ -607,8 +575,6 @@ void ethernet_link_check_state(struct netif *netif)
} }
} }
ETH_HandleTypeDef* getEthernetHandle() { ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; }
return &EthHandle;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,65 +1,66 @@
/** /**
****************************************************************************** ******************************************************************************
* @file LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/ethernetif.h * @file LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/ethernetif.h
* @author MCD Application Team * @author MCD Application Team
* @brief Header for ethernetif.c module * @brief Header for ethernetif.c module
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V. * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2> * All rights reserved.</center></h2>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met: * modification, are permitted, provided that the following conditions are met:
* *
* 1. Redistribution of source code must retain the above copyright notice, * 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other * 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products * contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission. * derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this * 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or * software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics. * microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under * 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under * this license is void and will automatically terminate your rights under
* this license. * this license.
* *
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
****************************************************************************** ******************************************************************************
*/ */
#ifndef __ETHERNETIF_H__ #ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__ #define __ETHERNETIF_H__
#include <stdbool.h>
#include <stm32h7xx_hal.h>
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/netif.h" #include "lwip/netif.h"
#include <stm32h7xx_hal.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ETH_RX_BUFFER_SIZE (1536UL) #define ETH_RX_BUFFER_SIZE (1536UL)
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
ETH_HandleTypeDef* getEthernetHandle(); ETH_HandleTypeDef *getEthernetHandle();
err_t ethernetif_init(struct netif *netif); err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif); void ethernetif_input(struct netif *netif);
void ethernet_link_check_state(struct netif *netif); void ethernet_link_check_state(struct netif *netif);

View File

@ -1,19 +1,15 @@
#include "udp_config.h"
#include "networking.h" #include "networking.h"
#include "udp_config.h"
bool ethernetCableConnected = false; bool ethernetCableConnected = false;
void networking::setEthCableConnected(bool status) { void networking::setEthCableConnected(bool status) { ethernetCableConnected = status; }
ethernetCableConnected = status;
}
bool networking::getEthCableConnected() { bool networking::getEthCableConnected() { return ethernetCableConnected; }
return ethernetCableConnected;
}
void networking::setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw) { void networking::setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw) {
IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1 , IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
NETMASK_ADDR2, NETMASK_ADDR3); IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
} }

View File

@ -9,6 +9,6 @@ void setEthCableConnected(bool status);
bool getEthCableConnected(); bool getEthCableConnected();
void setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw); void setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw);
} } // namespace networking
#endif /* BSP_STM32H7_RTEMS_NETWORKING_NETWORKING_H_ */ #endif /* BSP_STM32H7_RTEMS_NETWORKING_NETWORKING_H_ */

View File

@ -6,31 +6,31 @@ extern "C" {
#endif #endif
/* UDP local connection port. Client needs to bind to this port */ /* UDP local connection port. Client needs to bind to this port */
#define UDP_SERVER_PORT 7 #define UDP_SERVER_PORT 7
/*Static DEST IP ADDRESS: DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */ /*Static DEST IP ADDRESS: DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */
#define DEST_IP_ADDR0 ((uint8_t)169U) #define DEST_IP_ADDR0 ((uint8_t)169U)
#define DEST_IP_ADDR1 ((uint8_t)254U) #define DEST_IP_ADDR1 ((uint8_t)254U)
#define DEST_IP_ADDR2 ((uint8_t)39U) #define DEST_IP_ADDR2 ((uint8_t)39U)
#define DEST_IP_ADDR3 ((uint8_t)2U) #define DEST_IP_ADDR3 ((uint8_t)2U)
/*Static IP ADDRESS*/ /*Static IP ADDRESS*/
#define IP_ADDR0 169 #define IP_ADDR0 169
#define IP_ADDR1 254 #define IP_ADDR1 254
#define IP_ADDR2 1 #define IP_ADDR2 1
#define IP_ADDR3 38 #define IP_ADDR3 38
/*NETMASK*/ /*NETMASK*/
#define NETMASK_ADDR0 255 #define NETMASK_ADDR0 255
#define NETMASK_ADDR1 255 #define NETMASK_ADDR1 255
#define NETMASK_ADDR2 0 #define NETMASK_ADDR2 0
#define NETMASK_ADDR3 0 #define NETMASK_ADDR3 0
/*Gateway Address*/ /*Gateway Address*/
#define GW_ADDR0 192 #define GW_ADDR0 192
#define GW_ADDR1 168 #define GW_ADDR1 168
#define GW_ADDR2 178 #define GW_ADDR2 178
#define GW_ADDR3 1 #define GW_ADDR3 1
#ifdef __cplusplus #ifdef __cplusplus
} }