Compare commits

..

No commits in common. "main" and "mueller/master" have entirely different histories.

66 changed files with 1867 additions and 2570 deletions

View File

@ -1,8 +1,10 @@
add_subdirectory(config)
add_subdirectory(example)
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
if(TGT_BSP MATCHES "arm/stm32h743zi-nucleo")
add_subdirectory(stm32h7)
add_subdirectory(stm32h7)
endif()

View File

@ -1,45 +0,0 @@
function(set_build_type)
message(STATUS "Used build generator: ${CMAKE_GENERATOR}")
# Set a default build type if none was specified
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(DEFAULT_BUILD_TYPE "Debug")
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS
"Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified."
)
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE
STRING "Choose the type of build." FORCE
)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo"
)
endif()
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
message(STATUS
"Building Debug application with flags: ${CMAKE_C_FLAGS_DEBUG}"
)
elseif(${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo")
message(STATUS
"Building Release (Debug) application with "
"flags: ${CMAKE_C_FLAGS_RELWITHDEBINFO}"
)
elseif(${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
message(STATUS
"Building Release (Size) application with "
"flags: ${CMAKE_C_FLAGS_MINSIZEREL}"
)
else()
message(STATUS
"Building Release (Speed) application with "
"flags: ${CMAKE_C_FLAGS_RELEASE}"
)
endif()
endfunction()

View File

@ -1,42 +0,0 @@
function(get_common_build_flags TGT_NAME)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(COMMON_COMPILE_OPTS
-ffunction-sections
-fdata-sections
PARENT_SCOPE)
set(COMMON_LINK_OPTS
-Wl,--gc-sections
-Wl,-Map=${TARGET_NAME}.map
PARENT_SCOPE)
set(COMMON_WARNING_FLAGS
-Wall
-Wextra
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
-Wduplicated-cond # check for duplicate conditions
-Wduplicated-branches # check for duplicate branches
-Wlogical-op # Search for bitwise operations instead of logical
-Wnull-dereference # Search for NULL dereference
-Wundef # Warn if undefind marcos are used
-Wformat=2 # Format string problem detection
-Wformat-overflow=2 # Formatting issues in printf
-Wformat-truncation=2 # Formatting issues in printf
-Wformat-security # Search for dangerous printf operations
-Wstrict-overflow=3 # Warn if integer overflows might happen
-Warray-bounds=2 # Some array bounds violations will be found
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
-Wcast-qual # Warn if the constness is cast away
-Wstringop-overflow=4
# -Wstack-protector # Emits a few false positives for low level access
# -Wconversion # Creates many false positives -Warith-conversion # Use
# with Wconversion to find more implicit conversions -fanalyzer # Should
# be used to look through problems
PARENT_SCOPE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/permissive- /d2SSAOptimizer-)
# To avoid nameclashes with min and max macro
add_compile_definitions(NOMINMAX)
endif()
endfunction()

View File

@ -1,3 +1,7 @@
target_sources(${TARGET_NAME} PRIVATE commonPollingSequenceFactory.cpp)
target_sources(${TARGET_NAME} PRIVATE
commonPollingSequenceFactory.cpp
)
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

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

View File

@ -1,34 +0,0 @@
#pragma once
#include <cstdint>
/**
* Enumerations for used PUS service IDs.
*/
namespace pus {
enum ServiceIds : uint8_t {
PUS_SERVICE_1 = 1,
PUS_SERVICE_2 = 2,
PUS_SERVICE_3 = 3,
PUS_SERVICE_5 = 5,
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_11 = 11,
PUS_SERVICE_17 = 17,
PUS_SERVICE_20 = 20,
PUS_SERVICE_200 = 200
};
}
namespace common {
/**
* The APID is a 14 bit identifier which can be used to distinguish processes and applications
* on a spacecraft. For more details, see the related ECSS/CCSDS standards.
* For this example, we are going to use a constant APID
*/
static constexpr uint16_t COMMON_PUS_APID = 0xEF;
static constexpr uint16_t COMMON_CFDP_APID = 0xF0;
static constexpr uint16_t COMMON_CFDP_CLIENT_ENTITY_ID = 0x01;
} // namespace common

View File

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

View File

@ -4,13 +4,11 @@
#ifndef COMMON_COMMONCONFIG_H_
#define COMMON_COMMONCONFIG_H_
#include <cstdint>
#cmakedefine01 FSFW_ADD_FMT_TESTS
#include <stdint.h>
//! Specify the debug output verbose level
#define OBSW_VERBOSE_LEVEL 1
#define OBSW_TCPIP_UDP_WIRETAPPING 0
#define OBSW_PRINT_MISSED_DEADLINES 0
//! Perform internal unit testd at application startup
@ -18,7 +16,6 @@
//! Add core components for the FSFW and for TMTC communication
#define OBSW_ADD_CORE_COMPONENTS 1
#define OBSW_ADD_CFDP_COMPONENTS 1
//! Add the PUS service stack
#define OBSW_ADD_PUS_STACK 1
@ -36,8 +33,35 @@
#define OBSW_ADD_CONTROLLER_DEMO 1
#define OBSW_CONTROLLER_PRINTOUT 1
/**
* The APID is a 14 bit identifier which can be used to distinguish processes and applications
* on a spacecraft. For more details, see the related ECSS/CCSDS standards.
* For this example, we are going to use a constant APID
*/
static const uint16_t COMMON_APID = 0xEF;
#ifdef __cplusplus
#include <fsfw/events/fwSubsystemIdRanges.h>
#include <fsfw/returnvalues/FwClassIds.h>
/**
* Enumerations for used PUS service IDs.
*/
namespace pus {
enum ServiceIds: uint8_t {
PUS_SERVICE_1 = 1,
PUS_SERVICE_2 = 2,
PUS_SERVICE_3 = 3,
PUS_SERVICE_5 = 5,
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_17 = 17,
PUS_SERVICE_20 = 20,
PUS_SERVICE_200 = 200
};
}
#endif /* __cplusplus */
#endif /* COMMON_COMMONCONFIG_H_ */

View File

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

View File

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

View File

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

View File

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

View File

@ -3,4 +3,3 @@ add_subdirectory(core)
add_subdirectory(devices)
add_subdirectory(test)
add_subdirectory(utility)
add_subdirectory(cfdp)

View File

@ -1 +0,0 @@

View File

@ -1,59 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_CONFIG_H
#define FSFW_EXAMPLE_HOSTED_CONFIG_H
#include "fsfw/cfdp.h"
namespace cfdp {
extern PacketInfoListBase* PACKET_LIST_PTR;
extern LostSegmentsListBase* LOST_SEGMENTS_PTR;
class ExampleUserHandler : public UserBase {
public:
explicit ExampleUserHandler(HasFileSystemIF& vfs) : cfdp::UserBase(vfs) {}
void transactionIndication(const cfdp::TransactionId& id) override {}
void eofSentIndication(const cfdp::TransactionId& id) override {}
void transactionFinishedIndication(const cfdp::TransactionFinishedParams& params) override {
sif::info << "File transaction finished for transaction with " << params.id << std::endl;
}
void metadataRecvdIndication(const cfdp::MetadataRecvdParams& params) override {
sif::info << "Metadata received for transaction with " << params.id << std::endl;
}
void fileSegmentRecvdIndication(const cfdp::FileSegmentRecvdParams& params) override {}
void reportIndication(const cfdp::TransactionId& id, cfdp::StatusReportIF& report) override {}
void suspendedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code) override {}
void resumedIndication(const cfdp::TransactionId& id, size_t progress) override {}
void faultIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
size_t progress) override {}
void abandonedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
size_t progress) override {}
void eofRecvIndication(const cfdp::TransactionId& id) override {
sif::info << "EOF PDU received for transaction with " << id << std::endl;
}
};
class ExampleFaultHandler : public cfdp::FaultHandlerBase {
public:
void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Notice of suspension detected for transaction " << id
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Transaction " << id
<< " was abandoned, condition code : " << cfdp::getConditionCodeString(code)
<< std::endl;
}
void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
sif::warning << "Fault ignored for transaction " << id
<< ", condition code: " << cfdp::getConditionCodeString(code) << std::endl;
}
};
} // namespace cfdp
#endif // FSFW_EXAMPLE_HOSTED_CONFIG_H

View File

@ -1 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE FsfwTestController.cpp)

View File

@ -1,221 +0,0 @@
#include "FsfwTestController.h"
#include <fsfw/datapool/PoolReadGuard.h>
FsfwTestController::FsfwTestController(object_id_t objectId, object_id_t device0,
object_id_t device1, uint8_t verboseLevel)
: TestController(objectId, objects::NO_OBJECT, 5),
device0Id(device0),
device1Id(device1),
deviceDataset0(device0),
deviceDataset1(device1) {}
FsfwTestController::~FsfwTestController() = default;
ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage *message) {
return returnvalue::OK;
}
ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
return returnvalue::OK;
}
void FsfwTestController::performControlOperation() {
// We will trace variables if we received an update notification or snapshots
if (verboseLevel >= 1) {
if (not traceVariable) {
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;
}
}
}
}
ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
namespace td = testdevice;
ReturnValue_t result = TestController::initializeAfterTaskCreation();
if (result != returnvalue::OK) {
return result;
}
auto *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);
}
auto *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) { return nullptr; }
ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
return returnvalue::OK;
}
void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId,
bool *clearMessage) {
using namespace std;
if (verboseLevel >= 1) {
char const *printout = nullptr;
if (storeId == store_address_t::invalid()) {
printout = "Notification";
} else {
printout = "Snapshot";
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "FsfwTestController::handleChangedDataset: " << printout
<< " update"
"from object ID "
<< setw(8) << setfill('0') << hex << sid.objectId << " and set ID " << sid.ownerSetId
<< dec << setfill(' ') << endl;
#else
sif::printInfo(
"FsfwTestController::handleChangedPoolVariable: %s update from"
"object ID 0x%08x and set ID %lu\n",
printout, sid.objectId, sid.ownerSetId);
#endif
if (storeId == store_address_t::invalid()) {
if (sid.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec);
float floatVec[3];
floatVec[0] = deviceDataset0.testFloat3Vec.value[0];
floatVec[1] = deviceDataset0.testFloat3Vec.value[1];
floatVec[2] = deviceDataset0.testFloat3Vec.value[2];
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Current float vector (3) values: [" << floatVec[0] << ", " << floatVec[1]
<< ", " << floatVec[2] << "]" << std::endl;
#else
sif::printInfo("Current float vector (3) values: [%f, %f, %f]\n", floatVec[0], floatVec[1],
floatVec[2]);
#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_VECTOR;
}
}
void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool *clearMessage) {
using namespace std;
if (verboseLevel >= 1) {
char const *printout = nullptr;
if (storeId == store_address_t::invalid()) {
printout = "Notification";
} 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 == store_address_t::invalid()) {
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

@ -1,44 +0,0 @@
#ifndef EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_
#define EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_
#include "fsfw/controller/ExtendedControllerBase.h"
#include "fsfw_tests/integration/controller/TestController.h"
class FsfwTestController : public TestController {
public:
FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1,
uint8_t verboseLevel = 0);
virtual ~FsfwTestController();
ReturnValue_t handleCommandMessage(CommandMessage *message) override;
/**
* Periodic helper from ControllerBase, implemented by child class.
*/
void performControlOperation() override;
private:
object_id_t device0Id;
object_id_t device1Id;
testdevice::TestDataSet deviceDataset0;
testdevice::TestDataSet deviceDataset1;
uint8_t verboseLevel = 0;
bool traceVariable = false;
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;
};
#endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */

View File

@ -1 +1,4 @@
target_sources(${TARGET_NAME} PRIVATE GenericFactory.cpp)
target_sources(${TARGET_NAME}
PRIVATE
GenericFactory.cpp
)

View File

@ -1,22 +1,27 @@
#include "GenericFactory.h"
#include "common/definitions.h"
#include "definitions.h"
#include "example/cfdp/Config.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/FsfwReaderTask.h"
#include "example/utility/CfdpTmFunnel.h"
#include "example/utility/TmFunnel.h"
#include "fsfw/FSFW.h"
#include "fsfw/cfdp.h"
#include "fsfw/cfdp/CfdpDistributor.h"
#include "fsfw_tests/internal/InternalUnitTester.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/events/EventManager.h"
#include "fsfw/health/HealthTable.h"
#include "fsfw/internalerror/InternalErrorReporter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/pus/CService200ModeCommanding.h"
#include "fsfw/pus/Service11TelecommandScheduling.h"
#include "fsfw/pus/Service17Test.h"
#include "fsfw/pus/Service1TelecommandVerification.h"
#include "fsfw/pus/Service20ParameterManagement.h"
@ -25,178 +30,131 @@
#include "fsfw/pus/Service5EventReporting.h"
#include "fsfw/pus/Service8FunctionManagement.h"
#include "fsfw/pus/Service9TimeManagement.h"
#include "fsfw/tcdistribution/CcsdsDistributor.h"
#include "fsfw/tcdistribution/PusDistributor.h"
#include "fsfw/timemanager/CdsShortTimeStamper.h"
#include "fsfw/tmtcservices/VerificationReporter.h"
#include "fsfw_hal/host/HostFilesystem.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 "fsfw/tcdistribution/CCSDSDistributor.h"
#include "fsfw/tcdistribution/PUSDistributor.h"
#include "fsfw/timemanager/TimeStamper.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#if OBSW_ADD_CFDP_COMPONENTS == 1
namespace cfdp {
EntityId REMOTE_CFDP_ID(cfdp::WidthInBytes::TWO_BYTES, common::COMMON_CFDP_CLIENT_ENTITY_ID);
RemoteEntityCfg GROUND_REMOTE_CFG(REMOTE_CFDP_ID);
OneRemoteConfigProvider REMOTE_CFG_PROVIDER(GROUND_REMOTE_CFG);
HostFilesystem HOST_FS;
ExampleUserHandler USER_HANDLER(HOST_FS);
ExampleFaultHandler EXAMPLE_FAULT_HANDLER;
} // namespace cfdp
#endif
void ObjectFactory::produceGenericObjects(PusTmFunnel **pusFunnel,
const AcceptsTelemetryIF &tmtcBridge,
CcsdsDistributor **ccsdsDistrib,
StorageManagerIF &tcStore, StorageManagerIF &tmStore) {
void ObjectFactory::produceGenericObjects() {
#if OBSW_ADD_CORE_COMPONENTS == 1
/* Framework objects */
new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
auto *stamperAndReader = new CdsShortTimeStamper(objects::TIME_STAMPER);
new VerificationReporter();
*ccsdsDistrib =
new CcsdsDistributor(common::COMMON_PUS_APID, objects::CCSDS_DISTRIBUTOR, &tcStore);
new PusDistributor(common::COMMON_PUS_APID, objects::PUS_DISTRIBUTOR, *ccsdsDistrib);
*pusFunnel = new PusTmFunnel(objects::PUS_TM_FUNNEL, tmtcBridge, *stamperAndReader, tmStore);
auto *cfdpFunnel =
new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, common::COMMON_CFDP_APID, tmtcBridge, tmStore);
new TmFunnel(objects::TM_FUNNEL, **pusFunnel, *cfdpFunnel);
/* Framework objects */
new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new TimeStamper(objects::TIME_STAMPER);
new CCSDSDistributor(apid::APID, objects::CCSDS_DISTRIBUTOR);
new PUSDistributor(apid::APID, objects::PUS_DISTRIBUTOR,
objects::CCSDS_DISTRIBUTOR);
new TmFunnel(objects::TM_FUNNEL);
#endif /* OBSW_ADD_CORE_COMPONENTS == 1 */
/* PUS stack */
/* PUS stack */
#if OBSW_ADD_PUS_STACK == 1
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, common::COMMON_PUS_APID,
pus::PUS_SERVICE_1, objects::PUS_TM_FUNNEL, 5);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, common::COMMON_PUS_APID,
pus::PUS_SERVICE_2, 3, 10);
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, common::COMMON_PUS_APID,
pus::PUS_SERVICE_3);
new Service5EventReporting(PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING,
common::COMMON_PUS_APID, pus::PUS_SERVICE_5),
20, 40);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, common::COMMON_PUS_APID,
pus::PUS_SERVICE_8, 3, 10);
new Service9TimeManagement(
PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, common::COMMON_PUS_APID, pus::PUS_SERVICE_9));
new Service17Test(
PsbParams(objects::PUS_SERVICE_17_TEST, common::COMMON_PUS_APID, pus::PUS_SERVICE_17));
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, common::COMMON_PUS_APID,
pus::PUS_SERVICE_20);
#if OBSW_ADD_CORE_COMPONENTS == 1
new Service11TelecommandScheduling<cfg::OBSW_MAX_SCHEDULED_TCS>(
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, common::COMMON_PUS_APID, pus::PUS_SERVICE_11),
*ccsdsDistrib);
#endif
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, common::COMMON_PUS_APID,
pus::PUS_SERVICE_200);
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION,
apid::APID, pus::PUS_SERVICE_1, objects::TM_FUNNEL, 5);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS,
apid::APID, pus::PUS_SERVICE_2, 3, 10);
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::APID, pus::PUS_SERVICE_3);
new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING,
apid::APID, pus::PUS_SERVICE_5, 50);
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT,
apid::APID, pus::PUS_SERVICE_8, 3, 10);
new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT, apid::APID,
pus::PUS_SERVICE_9);
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::APID,
pus::PUS_SERVICE_17);
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::APID,
pus::PUS_SERVICE_20);
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT,
apid::APID, pus::PUS_SERVICE_200);
#endif /* OBSW_ADD_PUS_STACK == 1 */
#if OBSW_ADD_TASK_EXAMPLE == 1
/* Demo objects */
new FsfwExampleTask(objects::TEST_DUMMY_1);
new FsfwExampleTask(objects::TEST_DUMMY_2);
new FsfwExampleTask(objects::TEST_DUMMY_3);
/* Demo objects */
new FsfwExampleTask(objects::TEST_DUMMY_1);
new FsfwExampleTask(objects::TEST_DUMMY_2);
new FsfwExampleTask(objects::TEST_DUMMY_3);
bool enablePrintout = false;
bool enablePrintout = false;
#if OBSW_TASK_EXAMPLE_PRINTOUT == 1
enablePrintout = true;
enablePrintout = true;
#endif
new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout);
new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout);
#endif /* OBSW_ADD_TASK_EXAMPLE == 1 */
#if OBSW_ADD_DEVICE_HANDLER_DEMO == 1
#if OBSW_DEVICE_HANDLER_PRINTOUT == 1
bool enableInfoPrintout = true;
bool enableInfoPrintout = true;
#else
bool enableInfoPrintout = false;
bool enableInfoPrintout = false;
#endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */
/* Demo device handler object */
size_t expectedMaxReplyLen = 64;
CookieIF *testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0),
expectedMaxReplyLen);
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1),
expectedMaxReplyLen);
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);
/* Demo device handler object */
size_t expectedMaxReplyLen = 64;
CookieIF* testCookie = new TestCookie(
static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0), expectedMaxReplyLen);
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1),
expectedMaxReplyLen);
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);
new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0,
objects::TEST_DEVICE_HANDLER_1);
new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0,
objects::TEST_DEVICE_HANDLER_1);
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
/* Demo controller object */
/* Demo controller object */
#if OBSW_ADD_CONTROLLER_DEMO == 1
#if OBSW_CONTROLLER_PRINTOUT == 1
#endif
new TestController(objects::TEST_CONTROLLER, objects::NO_OBJECT);
new TestController(objects::TEST_CONTROLLER, objects::TEST_DEVICE_HANDLER_0,
objects::TEST_DEVICE_HANDLER_1);
#endif /* OBSW_ADD_CONTROLLER_DEMO == 1 */
#if OBSW_PERFORM_INTERNAL_UNITTEST == 1
InternalUnitTester::TestConfig testCfg;
testCfg.testArrayPrinter = false;
InternalUnitTester::TestConfig testCfg;
testCfg.testArrayPrinter = false;
#if defined FSFW_OSAL_HOST
// Not implemented yet for hosted OSAL (requires C++20)
testCfg.testSemaphores = false;
// Not implemented yet for hosted OSAL (requires C++20)
testCfg.testSemaphores = false;
#endif
InternalUnitTester unittester;
unittester.performTests(testCfg);
InternalUnitTester unittester;
unittester.performTests(testCfg);
#endif /* OBSW_PERFORM_INTERNAL_UNITTEST == 1 */
#if OBSW_ADD_CFDP_COMPONENTS == 1
using namespace cfdp;
MessageQueueIF *cfdpMsgQueue = QueueFactory::instance()->createMessageQueue(32);
CfdpDistribCfg cfg(objects::CFDP_DISTRIBUTOR, tcStore, cfdpMsgQueue);
new CfdpDistributor(cfg);
auto *msgQueue = QueueFactory::instance()->createMessageQueue(32);
UnsignedByteField<uint16_t> remoteEntityId(common::COMMON_CFDP_CLIENT_ENTITY_ID);
cfdp::EntityId remoteId(remoteEntityId);
cfdp::RemoteEntityCfg remoteCfg(remoteId);
remoteCfg.defaultChecksum = cfdp::ChecksumType::CRC_32;
FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, *cfdpFunnel, tcStore, tmStore,
*msgQueue);
cfdp::IndicationCfg indicationCfg;
UnsignedByteField<uint16_t> apid(common::COMMON_CFDP_APID);
cfdp::EntityId localId(apid);
GROUND_REMOTE_CFG.defaultChecksum = cfdp::ChecksumType::CRC_32;
if (PACKET_LIST_PTR == nullptr or LOST_SEGMENTS_PTR == nullptr) {
sif::error << "CFDP: No packet list or lost segments container set" << std::endl;
}
CfdpHandlerCfg cfdpCfg(localId, indicationCfg, USER_HANDLER, EXAMPLE_FAULT_HANDLER,
*PACKET_LIST_PTR, *LOST_SEGMENTS_PTR, REMOTE_CFG_PROVIDER);
auto *cfdpHandler = new CfdpHandler(params, cfdpCfg);
CcsdsDistributorIF::DestInfo info("CFDP Destination", common::COMMON_CFDP_APID,
cfdpHandler->getRequestQueue(), true);
(*ccsdsDistrib)->registerApplication(info);
#endif
}
void Factory::setStaticFrameworkObjectIds() {
MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_DISTRIBUTOR;
PusServiceBase::PACKET_DESTINATION = objects::PUS_TM_FUNNEL;
TmFunnel::downlinkDestination = objects::DOWNLINK_DESTINATION;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::PUS_TM_FUNNEL;
PusServiceBase::packetSource = objects::PUS_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION;
}

View File

@ -3,24 +3,15 @@
#include <fsfw/objectmanager/SystemObjectIF.h>
#include "OBSWConfig.h"
#include "example/utility/PusTmFunnel.h"
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
class TmFunnel;
class CcsdsDistributor;
namespace ObjectFactory {
/**
* @brief Produce hardware independant objects. Called by bsp specific
* object factory.
*/
void produceGenericObjects(PusTmFunnel** pusFunnel, const AcceptsTelemetryIF& tmtcBridge,
CcsdsDistributor** ccsdsDistributor, StorageManagerIF& tcStore,
StorageManagerIF& tmStore);
void produceGenericObjects();
}
} // namespace ObjectFactory
#endif /* MISSION_CORE_GENERICFACTORY_H_ */

View File

@ -1 +0,0 @@

View File

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

View File

@ -1,6 +1,5 @@
target_sources(${TARGET_NAME} PRIVATE FsfwReaderTask.cpp FsfwExampleTask.cpp
MutexExample.cpp FsfwTestTask.cpp)
if(FSFW_ADD_FMT_TESTS)
target_sources(${TARGET_NAME} PRIVATE testFmt.cpp)
endif()
target_sources(${TARGET_NAME} PRIVATE
FsfwReaderTask.cpp
FsfwExampleTask.cpp
MutexExample.cpp
)

View File

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

View File

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

View File

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

View File

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

View File

@ -1,21 +0,0 @@
#include "FsfwTestTask.h"
#include <commonConfig.h>
#if FSFW_ADD_FMT_TESTS == 1
#include "testFmt.h"
#endif
FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent)
: TestTask(objectId), periodicEvent(periodicEvent) {
#if FSFW_ADD_FMT_TESTS == 1
fmtTests();
#endif
}
ReturnValue_t FsfwTestTask::performPeriodicAction() {
if (periodicEvent) {
triggerEvent(TEST_EVENT, 0x1234, 0x4321);
}
return returnvalue::OK;
}

View File

@ -1,20 +0,0 @@
#ifndef 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"
class FsfwTestTask : public TestTask {
public:
FsfwTestTask(object_id_t objectId, bool periodicEvent);
ReturnValue_t performPeriodicAction() override;
private:
bool periodicEvent = false;
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_ */

View File

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

View File

@ -1,8 +1,8 @@
#ifndef EXAMPLE_COMMON_MUTEXEXAMPLE_H_
#define EXAMPLE_COMMON_MUTEXEXAMPLE_H_
#ifndef MISSION_DEMO_MUTEXEXAMPLE_H_
#define MISSION_DEMO_MUTEXEXAMPLE_H_
namespace MutexExample {
void example();
void example();
};
#endif /* EXAMPLE_COMMON_MUTEXEXAMPLE_H_ */
#endif /* MISSION_DEMO_MUTEXEXAMPLE_H_ */

View File

@ -1,14 +0,0 @@
#include "testFmt.h"
void fmtTests() {
sif::fdebug(__FILENAME__, __LINE__, "Hello {} {}", "World\n");
sif::fdebug_t(__FILENAME__, __LINE__, "Hallo\n");
FSFW_LOGD("{}", "Hallo\n");
// MY_LOG("{}", "test\n");
// sif::finfo_t("Hallo\n");
// sif::finfo("Hallo\n");
// sif::fwarning("Hello\n");
// sif::fwarning_t("Hello\n");
// sif::ferror("Hello\n");
// sif::ferror_t("Hello\n");
}

View File

@ -1,162 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_TESTFMT_H
#define FSFW_EXAMPLE_HOSTED_TESTFMT_H
#include <fmt/chrono.h>
#include <fmt/color.h>
#include <fmt/compile.h>
#include <fmt/core.h>
#include <array>
#include <cstdint>
#include "fsfw/ipc/MutexFactory.h"
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/timemanager/Clock.h"
#define __FILENAME_REL__ (((const char *)__FILE__ + SOURCE_PATH_SIZE))
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
void fmtTests();
namespace sif {
static std::array<char, 524> PRINT_BUF = {};
static const char INFO_PREFIX[] = "INFO";
static const char DEBUG_PREFIX[] = "DEBUG";
static const char WARNING_PREFIX[] = "WARNING";
static const char ERROR_PREFIX[] = "ERROR";
enum class LogLevel : unsigned int { DEBUG = 0, INFO = 1, WARNING = 2, ERROR = 3 };
static const char *PREFIX_ARR[4] = {DEBUG_PREFIX, INFO_PREFIX, WARNING_PREFIX, ERROR_PREFIX};
static const std::array<fmt::color, 4> LOG_COLOR_ARR = {
fmt::color::deep_sky_blue, fmt::color::forest_green, fmt::color::orange_red, fmt::color::red};
static MutexIF *PRINT_MUTEX = MutexFactory::instance()->createMutex();
static size_t writeTypePrefix(LogLevel level) {
auto idx = static_cast<unsigned int>(level);
const auto result =
fmt::format_to_n(PRINT_BUF.begin(), PRINT_BUF.size() - 1,
fmt::runtime(fmt::format(fg(LOG_COLOR_ARR[idx]), PREFIX_ARR[idx])));
return result.size;
}
template <typename... T>
size_t logTraced(LogLevel level, const char *file, unsigned int line, bool timed,
fmt::format_string<T...> fmt, T &&...args) noexcept {
try {
MutexGuard mg(PRINT_MUTEX);
size_t bufPos = writeTypePrefix(level);
auto currentIter = PRINT_BUF.begin() + bufPos;
if (timed) {
Clock::TimeOfDay_t logTime;
Clock::getDateAndTime(&logTime);
const auto result = fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos,
" | {}[l.{}] | {:02}:{:02}:{:02}.{:03} | {}", file, line,
logTime.hour, logTime.minute, logTime.second,
logTime.usecond / 1000, fmt::format(fmt, args...));
*result.out = '\0';
bufPos += result.size;
} else {
const auto result =
fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos, " | {}[l.{}] | {}", file,
line, fmt::format(fmt, args...));
*result.out = '\0';
bufPos += result.size;
}
fmt::print(fmt::runtime(PRINT_BUF.data()));
return bufPos;
} catch (const fmt::v8::format_error &e) {
fmt::print("Printing failed with error: {}\n", e.what());
return 0;
}
}
template <typename... T>
size_t log(LogLevel level, bool timed, fmt::format_string<T...> fmt, T &&...args) noexcept {
try {
MutexGuard mg(PRINT_MUTEX);
size_t bufPos = writeTypePrefix(level);
auto currentIter = PRINT_BUF.begin() + bufPos;
if (timed) {
Clock::TimeOfDay_t logTime;
Clock::getDateAndTime(&logTime);
const auto result = fmt::format_to_n(
currentIter, PRINT_BUF.size() - bufPos, " | {:02}:{:02}:{:02}.{:03} | {}", logTime.hour,
logTime.minute, logTime.second, logTime.usecond / 1000, fmt::format(fmt, args...));
bufPos += result.size;
}
fmt::print(fmt::runtime(PRINT_BUF.data()));
return bufPos;
} catch (const fmt::v8::format_error &e) {
fmt::print("Printing failed with error: {}\n", e.what());
return 0;
}
}
template <typename... T>
void fdebug(const char *file, unsigned int line, fmt::format_string<T...> fmt,
T &&...args) noexcept {
logTraced(LogLevel::DEBUG, file, line, false, fmt, args...);
}
template <typename... T>
void fdebug_t(const char *file, unsigned int line, fmt::format_string<T...> fmt,
T &&...args) noexcept {
logTraced(LogLevel::DEBUG, file, line, true, fmt, args...);
}
template <typename... T>
void finfo_t(fmt::format_string<T...> fmt, T &&...args) {
log(LogLevel::INFO, true, fmt, args...);
}
template <typename... T>
void finfo(fmt::format_string<T...> fmt, T &&...args) {
log(LogLevel::INFO, false, fmt, args...);
}
template <typename... T>
void fwarning(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
logTraced(LogLevel::WARNING, file, line, false, fmt, args...);
}
template <typename... T>
void fwarning_t(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
logTraced(LogLevel::WARNING, file, line, true, fmt, args...);
}
template <typename... T>
void ferror(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
logTraced(LogLevel::ERROR, file, line, false, fmt, args...);
}
template <typename... T>
void ferror_t(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
logTraced(LogLevel::ERROR, file, line, true, fmt, args...);
}
} // namespace sif
#define FSFW_LOGI(format, ...) finfo(FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGIT(format, ...) finfo_t(FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGD(format, ...) sif::fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGDT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGW(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGWT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGE(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#define FSFW_LOGET(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
#endif // FSFW_EXAMPLE_HOSTED_TESTFMT_H

View File

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

View File

@ -1,2 +1,4 @@
target_sources(${TARGET_NAME} PRIVATE utility.cpp TmFunnel.cpp PusTmFunnel.cpp
CfdpTmFunnel.cpp)
target_sources(${TARGET_NAME} PRIVATE
utility.cpp
TmFunnel.cpp
)

View File

@ -1,84 +0,0 @@
#include "CfdpTmFunnel.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore)
: SystemObject(objectId), cfdpInCcsdsApid(cfdpInCcsdsApid), tmStore(tmStore) {
msgQueue = QueueFactory::instance()->createMessageQueue(5);
msgQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue());
}
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
MessageQueueId_t CfdpTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
return msgQueue->getId();
}
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
TmTcMessage currentMessage;
ReturnValue_t status = msgQueue->receiveMessage(&currentMessage);
while (status == returnvalue::OK) {
status = handlePacket(currentMessage);
if (status != returnvalue::OK) {
sif::warning << "CfdpTmFunnel packet handling failed" << std::endl;
break;
}
status = msgQueue->receiveMessage(&currentMessage);
}
if (status == MessageQueueIF::EMPTY) {
return returnvalue::OK;
}
return status;
}
ReturnValue_t CfdpTmFunnel::initialize() { return returnvalue::OK; }
ReturnValue_t CfdpTmFunnel::handlePacket(TmTcMessage& msg) {
const uint8_t* cfdpPacket = nullptr;
size_t cfdpPacketLen = 0;
ReturnValue_t result = tmStore.getData(msg.getStorageId(), &cfdpPacket, &cfdpPacketLen);
if (result != returnvalue::OK) {
return result;
}
auto spacePacketHeader =
SpacePacketCreator(ccsds::PacketType::TM, false, cfdpInCcsdsApid,
ccsds::SequenceFlags::UNSEGMENTED, sourceSequenceCount++, 0);
sourceSequenceCount = sourceSequenceCount & ccsds::LIMIT_SEQUENCE_COUNT;
spacePacketHeader.setCcsdsLenFromTotalDataFieldLen(cfdpPacketLen);
uint8_t* newPacketData = nullptr;
store_address_t newStoreId{};
result =
tmStore.getFreeElement(&newStoreId, spacePacketHeader.getFullPacketLen(), &newPacketData);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "CfdpTmFunnel::handlePacket: Error getting TM store element of size "
<< spacePacketHeader.getFullPacketLen() << std::endl;
#endif
return result;
}
size_t serSize = 0;
result =
spacePacketHeader.serializeBe(&newPacketData, &serSize, spacePacketHeader.getFullPacketLen());
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CfdpTmFunnel::handlePacket: Error serializing packet" << std::endl;
#endif
return result;
}
std::memcpy(newPacketData, cfdpPacket, cfdpPacketLen);
// Delete old packet
tmStore.deleteData(msg.getStorageId());
msg.setStorageId(newStoreId);
result = msgQueue->sendToDefault(&msg);
if (result != returnvalue::OK) {
tmStore.deleteData(msg.getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CfdpTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
#endif
}
return result;
}

View File

@ -1,27 +0,0 @@
#ifndef FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
#define FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
class CfdpTmFunnel : public AcceptsTelemetryIF, public SystemObject {
public:
CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize() override;
private:
ReturnValue_t handlePacket(TmTcMessage& msg);
uint16_t sourceSequenceCount = 0;
uint16_t cfdpInCcsdsApid;
MessageQueueIF* msgQueue;
StorageManagerIF& tmStore;
};
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H

View File

@ -1,9 +1,10 @@
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tmtcpacket/pus/tc.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <mission/utility/PusPacketCreator.h>
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_
class PusPacketCreator {
public:
static void createPusPacketAndPrint();
public:
static void createPusPacketAndPrint();
};
#endif /* MISSION_UTILITY_PUSPACKETCREATOR_H_ */

View File

@ -1,68 +0,0 @@
#include "PusTmFunnel.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager.h"
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
PusTmFunnel::PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination,
TimeReaderIF &timeReader, StorageManagerIF &tmStore, uint32_t messageDepth)
: SystemObject(objectId), timeReader(timeReader), tmStore(tmStore) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
tmQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue());
}
PusTmFunnel::~PusTmFunnel() = default;
MessageQueueId_t PusTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
return tmQueue->getId();
}
ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
TmTcMessage currentMessage;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
while (status == returnvalue::OK) {
status = handlePacket(currentMessage);
if (status != returnvalue::OK) {
sif::warning << "TmFunnel packet handling failed" << std::endl;
break;
}
status = tmQueue->receiveMessage(&currentMessage);
}
if (status == MessageQueueIF::EMPTY) {
return returnvalue::OK;
}
return status;
}
ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
uint8_t *packetData = nullptr;
size_t size = 0;
ReturnValue_t result = tmStore.modifyData(message.getStorageId(), &packetData, &size);
if (result != returnvalue::OK) {
return result;
}
PusTmZeroCopyWriter packet(timeReader, packetData, size);
result = packet.parseDataWithoutCrcCheck();
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PusTmFunnel::handlePacket: Error parsing received PUS packet" << std::endl;
#endif
return result;
}
packet.setSequenceCount(sourceSequenceCount++);
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
packet.updateErrorControl();
result = tmQueue->sendToDefault(&message);
if (result != returnvalue::OK) {
tmStore.deleteData(message.getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
#endif
}
return result;
}
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }

View File

@ -1,39 +0,0 @@
#ifndef FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
#define FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <fsfw/tmtcservices/TmTcMessage.h>
#include "fsfw/timemanager/TimeReaderIF.h"
/**
* @brief TM Recipient.
* @details
* Main telemetry receiver. All generated telemetry is funneled into
* this object.
* @ingroup utility
* @author J. Meier
*/
class PusTmFunnel : public AcceptsTelemetryIF, public SystemObject {
public:
explicit PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination,
TimeReaderIF &timeReader, StorageManagerIF &tmStore,
uint32_t messageDepth = 20);
[[nodiscard]] const char *getName() const override;
~PusTmFunnel() override;
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
ReturnValue_t performOperation(uint8_t operationCode);
private:
uint16_t sourceSequenceCount = 0;
TimeReaderIF &timeReader;
StorageManagerIF &tmStore;
MessageQueueIF *tmQueue = nullptr;
ReturnValue_t handlePacket(TmTcMessage &message);
};
#endif // FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H

View File

@ -6,16 +6,17 @@
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
sif::error << "InitMission: Adding object " << objName << "(" << std::setw(8) << std::setfill('0')
<< std::hex << objectId << std::dec << ") failed." << std::endl;
sif::error << "InitMission: Adding object " << objName << "("
<< std::setw(8) << std::setfill('0') << std::hex << objectId
<< std::dec << ") failed." << std::endl;
#else
sif::printError("InitMission: Adding object %s (0x%08x) failed.\n", objName,
static_cast<unsigned int>(objectId));
sif::printError("InitMission: Adding object %s (0x%08x) failed.\n",
objName, static_cast<unsigned int>(objectId));
#endif
}
} // namespace task
}
#endif /* MISSION_UTILITY_TASKCREATION_H_ */

View File

@ -1,16 +1,120 @@
#include "TmFunnel.h"
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tmtcpacket/pus/tm.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
TmFunnel::TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel)
: SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel) {}
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT;
object_id_t TmFunnel::storageDestination = objects::NO_OBJECT;
TmFunnel::~TmFunnel() = default;
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
pusFunnel.performOperation(operationCode);
cfdpFunnel.performOperation(operationCode);
return returnvalue::OK;
TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth):
SystemObject(objectId), messageDepth(messageDepth) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
storageQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
}
ReturnValue_t TmFunnel::initialize() { return returnvalue::OK; }
TmFunnel::~TmFunnel() {
}
MessageQueueId_t TmFunnel::getReportReceptionQueue(uint8_t virtualChannel) {
return tmQueue->getId();
}
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
TmTcMessage currentMessage;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
while(status == HasReturnvaluesIF::RETURN_OK)
{
status = handlePacket(&currentMessage);
if(status != HasReturnvaluesIF::RETURN_OK){
break;
}
status = tmQueue->receiveMessage(&currentMessage);
}
if (status == MessageQueueIF::EMPTY) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
return status;
}
}
ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
uint8_t* packetData = nullptr;
size_t size = 0;
ReturnValue_t result = tmPool->modifyData(message->getStorageId(),
&packetData, &size);
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;
}
ReturnValue_t TmFunnel::initialize() {
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if(tmPool == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::initialize: TM store not set." << std::endl;
sif::error << "Make sure the tm store is set up properly and implements StorageManagerIF" <<
std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
AcceptsTelemetryIF* tmTarget = ObjectManager::instance()->
get<AcceptsTelemetryIF>(downlinkDestination);
if(tmTarget == nullptr){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::initialize: Downlink Destination not set." << std::endl;
sif::error << "Make sure the downlink destination object is set up properly and implements "
"AcceptsTelemetryIF" << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
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());
}
return SystemObject::initialize();
}

View File

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

View File

@ -5,21 +5,16 @@
* Authors:
*
* 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
* 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
*
* 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. This should include Gregorian calendar leap days, in
* particular the 29ths of February, 100 and 400 years modulo leaps.
* 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.
* 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!
*
*/
@ -27,66 +22,76 @@
#define COMPILE_TIME_H_
// Some definitions for calculation
#define SEC_PER_MIN 60UL
#define SEC_PER_HOUR 3600UL
#define SEC_PER_DAY 86400UL
#define SEC_PER_YEAR (SEC_PER_DAY * 365)
#define SEC_PER_MIN 60UL
#define SEC_PER_HOUR 3600UL
#define SEC_PER_DAY 86400UL
#define SEC_PER_YEAR (SEC_PER_DAY*365)
// 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_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_4(str, i) (CONV_STR2DEC_3(str, i) * 10 + str[i + 3] - '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_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')
// 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 \
: str[i] == 'F' && str[i + 1] == 'e' && str[i + 2] == 'b' ? 2 \
: str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'r' ? 3 \
: str[i] == 'A' && str[i + 1] == 'p' && str[i + 2] == 'r' ? 4 \
: str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'y' ? 5 \
: str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'n' ? 6 \
: str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'l' ? 7 \
: str[i] == 'A' && str[i + 1] == 'u' && str[i + 2] == 'g' ? 8 \
: str[i] == 'S' && str[i + 1] == 'e' && str[i + 2] == 'p' ? 9 \
: str[i] == 'O' && str[i + 1] == 'c' && str[i + 2] == 't' ? 10 \
: 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)
#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \
str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \
str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \
str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \
str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \
str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \
str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \
str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \
str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \
str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \
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__
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
// Days in February
#define _UNIX_TIMESTAMP_FDAY(year) \
(((year) % 400) == 0UL ? 29UL \
: (((year) % 100) == 0UL ? 28UL : (((year) % 4) == 0UL ? 29UL : 28UL)))
(((year) % 400) == 0UL ? 29UL : \
(((year) % 100) == 0UL ? 28UL : \
(((year) % 4) == 0UL ? 29UL : \
28UL)))
// Days in the year
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
(/* January */ day /* February */ + (month >= 2 ? 31UL : 0UL) /* March */ + \
(month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) /* April */ + \
(month >= 4 ? 31UL : 0UL) /* May */ + (month >= 5 ? 30UL : 0UL) /* June */ + \
(month >= 6 ? 31UL : 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))
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
( \
/* January */ day \
/* February */ + (month >= 2 ? 31UL : 0UL) \
/* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \
/* April */ + (month >= 4 ? 31UL : 0UL) \
/* May */ + (month >= 5 ? 30UL : 0UL) \
/* June */ + (month >= 6 ? 31UL : 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
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
(/* time */ second + minute * SEC_PER_MIN + hour * SEC_PER_HOUR + \
/* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * 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)
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
( /* time */ second \
+ minute * SEC_PER_MIN \
+ hour * SEC_PER_HOUR \
+ /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * 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
#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

View File

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

View File

@ -3,8 +3,9 @@
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_ */

View File

@ -1,44 +0,0 @@
#!/bin/bash
counter=0
common_example_dir="example_common"
while [ ${counter} -lt 5 ]
do
if [ ! -d ${common_example_dir} ];then
break
fi
counter=$((counter=counter + 1))
cd ..
done
if [ "${counter}" -ge 5 ];then
echo "${common_example_dir} not found in upper directories!"
exit 1
fi
folder_list=(
"./bsp_hosted"
"./example_common"
)
cmake_fmt="cmake-format"
file_selectors="-iname CMakeLists.txt"
if command -v ${cmake_fmt} &> /dev/null; then
echo "Auto-formatting all CMakeLists.txt files"
${cmake_fmt} -i CMakeLists.txt
for dir in ${folder_list[@]}; do
find ${dir} ${file_selectors} | xargs ${cmake_fmt} -i
done
else
echo "No ${cmake_fmt} tool found, not formatting CMake files"
fi
cpp_format="clang-format"
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
if command -v ${cpp_format} &> /dev/null; then
for dir in ${folder_list[@]}; do
echo "Auto-formatting C/C++ files in ${dir} recursively"
find ${dir} ${file_selectors} | xargs ${cpp_format} --style=file -i
done
else
echo "No ${cpp_format} tool found, not formatting C++/C files"
fi

View File

@ -1,7 +1,9 @@
target_sources(${TARGET_NAME} PRIVATE STM32TestTask.cpp)
target_sources(${TARGET_NAME} PRIVATE
STM32TestTask.cpp
)
option(STM32_ADD_NETWORKING_CODE "Add networking code requiring lwIP" ON)
if(STM32_ADD_NETWORKING_CODE)
add_subdirectory(networking)
endif()
add_subdirectory(networking)
endif()

View File

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

View File

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

View File

@ -1,8 +1,14 @@
# These are part of the RTEMS BSP for RTEMS
if(FSFW_OSAL MATCHES freertos)
target_sources(${TARGET_NAME} PRIVATE ethernetif.c)
target_sources(${TARGET_NAME} PRIVATE
ethernetif.c
)
endif()
target_sources(
${TARGET_NAME} PRIVATE UdpTcLwIpPollingTask.cpp TmTcLwIpUdpBridge.cpp
networking.cpp app_dhcp.cpp app_ethernet.cpp)
target_sources(${TARGET_NAME} PRIVATE
UdpTcLwIpPollingTask.cpp
TmTcLwIpUdpBridge.cpp
networking.cpp
app_dhcp.cpp
app_ethernet.cpp
)

View File

@ -1,189 +1,204 @@
#include "TmTcLwIpUdpBridge.h"
#include "udp_config.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include <OBSWConfig.h>
#include <fsfw/ipc/MutexGuard.h>
#include <fsfw/serialize/EndianConverter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/serialize/EndianConverter.h>
#include "app_ethernet.h"
#include "udp_config.h"
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(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() = default;
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {}
ReturnValue_t TmTcLwIpUdpBridge::initialize() {
TmTcBridge::initialize();
bridgeLock = MutexFactory::instance()->createMutex();
if (bridgeLock == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ReturnValue_t result = udp_server_init();
return result;
TmTcBridge::initialize();
bridgeLock = MutexFactory::instance()->createMutex();
if(bridgeLock == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ReturnValue_t result = udp_server_init();
return result;
}
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init() {
err_t err;
/* Create a new UDP control block */
TmTcLwIpUdpBridge::upcb = udp_new();
if (TmTcLwIpUdpBridge::upcb) {
sif::printInfo("Opening UDP server on port %d\n", UDP_SERVER_PORT);
/* Bind the upcb to the UDP_PORT port */
/* 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);
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) {
err_t err;
/* Create a new UDP control block */
TmTcLwIpUdpBridge::upcb = udp_new();
if (TmTcLwIpUdpBridge::upcb)
{
/* Bind the upcb to the UDP_PORT port */
/* 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);
if (err == ERR_OK) {
/* Set a receive callback for the upcb */
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, (void *)this);
return RETURN_OK;
if(err == ERR_OK)
{
/* Set a receive callback for the upcb */
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback,
(void*) this);
return RETURN_OK;
}
else
{
udp_remove(TmTcLwIpUdpBridge::upcb);
return RETURN_FAILED;
}
} else {
udp_remove(TmTcLwIpUdpBridge::upcb);
return RETURN_FAILED;
return RETURN_FAILED;
}
} else {
return RETURN_FAILED;
}
}
ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
TmTcBridge::performOperation();
TmTcBridge::performOperation();
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
if (connectFlag) {
uint32_t ipAddress = ((ip4_addr *)&lastAdd)->addr;
int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
int ipAddress3 = (ipAddress & 0xFF00) >> 8;
int ipAddress4 = ipAddress & 0xFF;
#if TCPIP_RECV_WIRETAPPING == 1
if(connectFlag) {
uint32_t ipAddress = ((ip4_addr*) &lastAdd)->addr;
int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
int ipAddress3 = (ipAddress & 0xFF00) >> 8;
int ipAddress4 = ipAddress & 0xFF;
#if OBSW_VERBOSE_LEVEL == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec << ipAddress4 << "."
<< ipAddress3 << "." << ipAddress2 << "." << ipAddress1 << std::endl;
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
sif::info << "TmTcLwIpUdpBridge: Client IP Port " << (int)portSwapped << std::endl;
sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec
<< ipAddress4 << "." << ipAddress3 << "." << ipAddress2 << "."
<< ipAddress1 << std::endl;
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
sif::info << "TmTcLwIpUdpBridge: Client IP Port "
<< (int)portSwapped << std::endl;
#else
sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n", ipAddress4, ipAddress3,
ipAddress2, ipAddress1);
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped);
sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n",
ipAddress4, ipAddress3, ipAddress2, ipAddress1);
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped);
#endif
#endif
connectFlag = false;
}
connectFlag = false;
}
#endif
return RETURN_OK;
return RETURN_OK;
}
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
/* copy data to pbuf */
err_t err = pbuf_take(p_tx, (const char *)data, dataLen);
if (err != ERR_OK) {
pbuf_free(p_tx);
return err;
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t * data, size_t dataLen) {
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
/* copy data to pbuf */
err_t err = pbuf_take(p_tx, (char*) data, dataLen);
if(err!=ERR_OK){
pbuf_free(p_tx);
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);
}
/* Connect to the remote client */
err = udp_connect(TmTcLwIpUdpBridge::upcb, &lastAdd, lastPort);
if (err != ERR_OK) {
pbuf_free(p_tx);
return err;
else{
return RETURN_FAILED;
}
/* Tell the client that we have accepted it */
err = udp_send(TmTcLwIpUdpBridge::upcb, p_tx);
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);
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) {
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*/
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
if (p_tx != nullptr) {
if (udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock);
udpBridge->upcb = upcb_;
udpBridge->lastAdd = *addr;
udpBridge->lastPort = port;
if (not udpBridge->comLinkUp()) {
udpBridge->registerCommConnect();
#if OBSW_TCPIP_UDP_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 OBSW_TCPIP_UDP_WIRETAPPING == 1
udpBridge->printData(reinterpret_cast<uint8_t *>(p->payload), p->len);
#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 */
bool TmTcLwIpUdpBridge::comLinkUp() const { return communicationLinkUp; }
bool TmTcLwIpUdpBridge::comLinkUp() const {
return communicationLinkUp;
}
/* Caller must ensure thread-safety */
void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) {
if (connect) {
/* Physical connection does not mean there is a recipient to send packets
too. This will be done by the receive callback! */
physicalConnection = true;
} else {
physicalConnection = false;
/* If there is no physical connection, we can't send anything back */
registerCommDisconnect();
}
if(connect) {
/* Physical connection does not mean there is a recipient to send packets too.
This will be done by the receive callback! */
physicalConnection = true;
}
else {
physicalConnection = false;
/* If there is no physical connection, we can't send anything back */
registerCommDisconnect();
}
}

View File

@ -1,78 +1,79 @@
#ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#include <lwip/ip_addr.h>
#include <lwip/udp.h>
#include <fsfw/tmtcservices/TmTcBridge.h>
#include "commonConfig.h"
#include "fsfw/tmtcservices/TmTcBridge.h"
#include <lwip/udp.h>
#include <lwip/ip_addr.h>
#define TCPIP_RECV_WIRETAPPING 0
/**
* 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 {
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();
public:
TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
object_id_t tcStoreId);
~TmTcLwIpUdpBridge() override;
virtual ReturnValue_t initialize() override;
ReturnValue_t udp_server_init();
ReturnValue_t initialize() override;
ReturnValue_t udp_server_init();
/**
* In addition to default implementation, ethernet link status is checked.
* @param operationCode
* @return
*/
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/**
* In addition to default implementation, ethernet link status is checked.
* @param operationCode
* @return
*/
ReturnValue_t performOperation(uint8_t operationCode) override;
/** TM Send implementation uses udp_send function from lwIP stack
* @param data
* @param dataLen
* @return
*/
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
/** TM Send implementation uses udp_send function from lwIP stack
* @param data
* @param dataLen
* @return
*/
ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override;
/**
* @brief This function is called when an UDP datagram has been
* received on the port UDP_PORT.
* @param arg
* @param upcb_
* @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);
/**
* @brief This function is called when an UDP datagram has been
* received on the port UDP_PORT.
* @param arg
* @param upcb_
* @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);
/**
* Check whether the communication link is up.
* Caller must ensure thread-safety by using the bridge lock.
* @return
*/
bool comLinkUp() const;
/**
* Check whether the communication link is up.
* Caller must ensure thread-safety by using the bridge lock.
* @return
*/
[[nodiscard]] bool comLinkUp() const;
private:
struct udp_pcb *upcb = nullptr;
ip_addr_t lastAdd;
u16_t lastPort = 0;
bool physicalConnection = false;
MutexIF* bridgeLock = nullptr;
private:
struct udp_pcb *upcb = nullptr;
ip_addr_t lastAdd{};
u16_t lastPort = 0;
bool physicalConnection = false;
MutexIF *bridgeLock = nullptr;
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
bool connectFlag = false;
#if TCPIP_RECV_WIRETAPPING == 1
bool connectFlag = false;
#endif
/**
* Used to notify bridge about change in the physical ethernet connection.
* 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 by using the bridge lock.
*/
void physicalConnectStatusChange(bool connect);
/**
* Used to notify bridge about change in the physical ethernet connection.
* 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
* by using the bridge lock.
*/
void physicalConnectStatusChange(bool connect);
};
#endif /* BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,61 +1,59 @@
/**
******************************************************************************
* @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c
* @author MCD Application Team
* @brief This file implements Ethernet network interface drivers for lwIP
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
******************************************************************************
* @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c
* @author MCD Application Team
* @brief This file implements Ethernet network interface drivers for lwIP
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "fsfw/FSFW.h"
#include "ethernetif.h"
#include <stdbool.h>
#include <string.h>
#include "fsfw/FSFW.h"
#include "lan8742.h"
#include "lwip/netif.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "netif/etharp.h"
#include "stm32h7xx_hal.h"
#include <lan8742.h>
#include <stm32h7xx_hal.h>
#include <lwip/netif.h>
#include <lwip/opt.h>
#include <lwip/timeouts.h>
#include <netif/etharp.h>
#ifdef FSFW_OSAL_RTEMS
#include <rtems.h>
@ -67,166 +65,142 @@
#define IFNAME0 's'
#define IFNAME1 't'
#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
#define ETH_RX_BUFFER_SIZE 1536U
#define ETH_RX_BUFFER_CNT 12U
#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT)*2U)
#define DMA_DESCRIPTOR_ALIGNMENT 0x20
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*
/*
@Note: This interface is implemented to operate in zero-copy mode only:
- Rx buffers are allocated statically and passed directly to the LwIP
stack they will return back to DMA after been processed by the stack.
- Tx Buffers will be allocated from LwIP stack memory heap,
- Rx buffers are allocated statically and passed directly to the LwIP stack
they will return back to DMA after been processed by the stack.
- Tx Buffers will be allocated from LwIP stack memory heap,
then passed to ETH HAL driver.
@Notes:
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
@Notes:
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_RX_DESC_CNT in stm32xxxx_hal_conf.h
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_TX_DESC_CNT in stm32xxxx_hal_conf.h
2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
*/
typedef enum { RX_ALLOC_OK = 0x00, RX_ALLOC_ERROR = 0x01 } RxAllocStatusTypeDef;
typedef struct {
struct pbuf_custom pbuf_custom;
uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
} RxBuff_t;
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma location=0x30040000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30040060
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location=0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
#pragma location = 0x30000000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location = 0x30000200
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#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(".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 */
__attribute__((section(".RxDecripSection")))
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((section(".TxDecripSection")))
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#elif defined(__GNUC__) /* GNU Compiler */
#elif defined ( __GNUC__ ) /* GNU Compiler */
#ifdef FSFW_OSAL_RTEMS
/* 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 */
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 */
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 */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
#elif defined FSFW_OSAL_FREERTOS
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
__attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
__attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
#endif /* FSFW_OSAL_RTEMS */
/* Placement and alignment specified in linker script here */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
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 /* defined ( __GNUC__ ) */
/* Memory Pool Declaration */
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
#if defined(__ICCARM__) /*!< IAR Compiler */
#pragma location = 0x30000400
extern u8_t memp_memory_RX_POOL_base[];
#elif defined(__CC_ARM) /* MDK ARM Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
#elif defined(__GNUC__) /* GNU Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
#endif
/* Global boolean to track ethernet connection */
bool ethernet_cable_connected;
/* Variable Definitions */
static uint8_t RxAllocStatus;
struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT];
uint32_t current_pbuf_idx =0;
/* Global Ethernet handle*/
ETH_HandleTypeDef EthHandle;
ETH_TxPacketConfig TxConfig;
ETH_TxPacketConfig TxConfig;
lan8742_Object_t LAN8742;
/* Private function prototypes -----------------------------------------------*/
u32_t sys_now(void);
extern void Error_Handler(void);
void pbuf_free_custom(struct pbuf *p);
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_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void);
lan8742_Object_t LAN8742;
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick};
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
ETH_PHY_IO_DeInit,
ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg,
ETH_PHY_IO_GetTick};
/* Private functions ---------------------------------------------------------*/
void pbuf_free_custom(struct pbuf *p);
/*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH)
LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/
/**
* @brief In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif) {
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;
* @brief In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
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};
EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress;
EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
EthHandle.Init.RxDesc = DMARxDscrTab;
EthHandle.Init.TxDesc = DMATxDscrTab;
EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
HAL_ETH_Init(&EthHandle);
/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
netif->hwaddr[0] = ETH_MAC_ADDR0;
netif->hwaddr[1] = ETH_MAC_ADDR1;
netif->hwaddr[2] = ETH_MAC_ADDR2;
netif->hwaddr[3] = ETH_MAC_ADDR3;
netif->hwaddr[4] = ETH_MAC_ADDR4;
netif->hwaddr[5] = ETH_MAC_ADDR5;
netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x00;
netif->hwaddr[2] = 0x00;
netif->hwaddr[3] = 0x00;
netif->hwaddr[4] = 0x00;
netif->hwaddr[5] = 0x00;
/* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
/* Initialize the RX POOL */
LWIP_MEMPOOL_INIT(RX_POOL);
for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
{
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
/* Set Custom pbuf free function */
rx_pbuf[idx].custom_free_function = pbuf_free_custom;
}
/* 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.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
@ -238,114 +212,152 @@ static void low_level_init(struct netif *netif) {
LAN8742_Init(&LAN8742);
ethernet_link_check_state(netif);
}
/**
* @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
* might be chained.
*
* @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)
* @return ERR_OK if the packet could 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
* 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
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
uint32_t i = 0U;
struct pbuf *q = NULL;
* @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
* might be chained.
*
* @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)
* @return ERR_OK if the packet could 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
* 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
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i=0, framelen = 0;
struct pbuf *q;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};
memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
for (q = p; q != NULL; q = q->next) {
if (i >= ETH_TX_DESC_CNT) return ERR_IF;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
for(q = p; q != NULL; q = q->next)
{
if(i >= ETH_TX_DESC_CNT)
return ERR_IF;
Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len;
if (i > 0) {
Txbuffer[i - 1].next = &Txbuffer[i];
framelen += q->len;
if(i>0)
{
Txbuffer[i-1].next = &Txbuffer[i];
}
if (q->next == NULL) {
if(q->next == NULL)
{
Txbuffer[i].next = NULL;
}
i++;
}
TxConfig.Length = p->tot_len;
TxConfig.Length = framelen;
TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
if (ret != HAL_OK) {
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20);
if(ret != HAL_OK) {
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
}
return errval;
}
/**
* @brief Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf *low_level_input(struct netif *netif) {
* @brief Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0;
if (RxAllocStatus == RX_ALLOC_OK) {
HAL_ETH_ReadData(&EthHandle, (void **)&p);
}
return p;
}
/**
* @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() that should handle the actual reception of bytes from the
* network interface. Then the type of the received packet is determined and the
* appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input(struct netif *netif) {
struct pbuf *p = NULL;
do {
p = low_level_input(netif);
if (p != NULL) {
if (netif->input(p, netif) != ERR_OK) {
pbuf_free(p);
}
if (HAL_ETH_IsRxDataAvailable(&EthHandle))
{
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff);
HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
/* Invalidate data cache for ETH Rx Buffers */
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);
if(current_pbuf_idx < (ETH_RX_DESC_CNT -1))
{
current_pbuf_idx++;
}
else
{
current_pbuf_idx = 0;
}
} while (p != NULL);
return p;
}
else
{
return NULL;
}
}
/**
* @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
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif) {
* @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()
* that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input(struct netif *netif)
{
err_t err;
struct pbuf *p;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p == NULL) return;
/* entry point to the LwIP stack */
err = netif->input(p, netif);
if (err != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
p = NULL;
}
HAL_ETH_BuildRxDescriptors(&EthHandle);
}
/**
* @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
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
@ -355,7 +367,6 @@ err_t ethernetif_init(struct netif *netif) {
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
@ -370,49 +381,54 @@ err_t ethernetif_init(struct netif *netif) {
}
/**
* @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed
* @retval None
*/
void pbuf_free_custom(struct pbuf *p) {
struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
/* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
* call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
if (RxAllocStatus == RX_ALLOC_ERROR) {
RxAllocStatus = RX_ALLOC_OK;
* @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed
* @retval None
*/
void pbuf_free_custom(struct pbuf *p)
{
if(p != NULL)
{
p->flags = 0;
p->next = NULL;
p->len = p->tot_len = 0;
p->ref = 0;
p->payload = NULL;
}
}
/**
* @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None
* @retval Current Time value
*/
u32_t sys_now(void) { return HAL_GetTick(); }
* @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None
* @retval Current Time value
*/
u32_t sys_now(void)
{
return HAL_GetTick();
}
/*******************************************************************************
Ethernet MSP Routines
*******************************************************************************/
/**
* @brief Initializes the ETH MSP.
* @param heth: ETH handle
* @retval None
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
* @brief Initializes the ETH MSP.
* @param heth: ETH handle
* @retval None
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Ethernett MSP init: RMII Mode */
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* Ethernet pins configuration
* ************************************************/
/* Ethernet pins configuration ************************************************/
/*
RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2
@ -429,29 +445,29 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
/* Configure PA1, PA2 and PA7 */
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PB13 */
GPIO_InitStructure.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PG2, PG11, PG13 and PG14 */
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
#if NO_SYS == 0
/* Enable the Ethernet global Interrupt */
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
#endif
/* Enable Ethernet clocks */
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
@ -462,167 +478,137 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
PHI IO Functions
*******************************************************************************/
/**
* @brief Initializes the MDIO interface GPIO and clocks.
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_Init(void) {
/* We assume that MDIO GPIO configuration is already done
in the ETH_MspInit() else it should be done here
* @brief Initializes the MDIO interface GPIO and clocks.
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_Init(void)
{
/* We assume that MDIO GPIO configuration is already done
in the ETH_MspInit() else it should be done here
*/
/* Configure the MDIO Clock */
HAL_ETH_SetMDIOClockRange(&EthHandle);
return 0;
}
/**
* @brief De-Initializes the MDIO interface .
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_DeInit(void) { return 0; }
* @brief De-Initializes the MDIO interface .
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_DeInit (void)
{
return 0;
}
/**
* @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error
*/
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) {
* @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error
*/
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)
{
return -1;
}
return 0;
}
/**
* @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param RegVal: Value to be written
* @retval 0 if OK -1 if Error
*/
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) {
* @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param RegVal: Value to be written
* @retval 0 if OK -1 if Error
*/
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)
{
return -1;
}
return 0;
}
/**
* @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value
*/
int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); }
* @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value
*/
int32_t ETH_PHY_IO_GetTick(void)
{
return HAL_GetTick();
}
/**
* @brief
* @retval None
*/
void ethernet_link_check_state(struct netif *netif) {
ETH_MACConfigTypeDef MACConf = {0};
int32_t PHYLinkState = 0U;
uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
* @brief
* @retval None
*/
void ethernet_link_check_state(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf;
uint32_t PHYLinkState;
uint32_t linkchanged = 0, speed = 0, duplex =0;
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) {
HAL_ETH_Stop_IT(&EthHandle);
if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
{
HAL_ETH_Stop(&EthHandle);
netif_set_down(netif);
netif_set_link_down(netif);
} else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) {
switch (PHYLinkState) {
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
default:
break;
}
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
{
switch (PHYLinkState)
{
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
default:
break;
}
if (linkchanged) {
if(linkchanged)
{
/* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
MACConf.DuplexMode = duplex;
MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
HAL_ETH_Start_IT(&EthHandle);
HAL_ETH_Start(&EthHandle);
netif_set_up(netif);
netif_set_link_up(netif);
}
}
}
void HAL_ETH_RxAllocateCallback(uint8_t **buff) {
struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
if (p) {
/* Get the buff from the struct pbuf address. */
*buff = (uint8_t *)p + offsetof(RxBuff_t, buff);
p->custom_free_function = pbuf_free_custom;
/* Initialize the struct pbuf.
* This must be performed whenever a buffer's allocated because it may be
* changed by lwIP or the app, e.g., pbuf_free decrements ref. */
pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
} else {
RxAllocStatus = RX_ALLOC_ERROR;
*buff = NULL;
}
ETH_HandleTypeDef* getEthernetHandle() {
return &EthHandle;
}
void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) {
struct pbuf **ppStart = (struct pbuf **)pStart;
struct pbuf **ppEnd = (struct pbuf **)pEnd;
struct pbuf *p = NULL;
/* Get the struct pbuf from the buff address. */
p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
p->next = NULL;
p->tot_len = 0;
p->len = Length;
/* Chain the buffer. */
if (!*ppStart) {
/* The first buffer of the packet. */
*ppStart = p;
} else {
/* Chain the buffer to the end of the packet. */
(*ppEnd)->next = p;
}
*ppEnd = p;
/* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its
* tot_len set to its own length, plus the length of all the following pbufs in the chain. */
for (p = *ppStart; p != NULL; p = p->next) {
p->tot_len += Length;
}
/* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length);
}
void HAL_ETH_TxFreeCallback(uint32_t *buff) { pbuf_free((struct pbuf *)buff); }
ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; }
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

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

View File

@ -1,15 +1,19 @@
#include "networking.h"
#include "udp_config.h"
#include "networking.h"
bool ethernetCableConnected = false;
void networking::setEthCableConnected(bool status) { ethernetCableConnected = status; }
bool networking::getEthCableConnected() { return ethernetCableConnected; }
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(netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
void networking::setEthCableConnected(bool status) {
ethernetCableConnected = status;
}
bool networking::getEthCableConnected() {
return ethernetCableConnected;
}
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(netmask, NETMASK_ADDR0, NETMASK_ADDR1 ,
NETMASK_ADDR2, NETMASK_ADDR3);
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
}

View File

@ -7,8 +7,8 @@ namespace networking {
void setEthCableConnected(bool status);
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_ */

View File

@ -6,32 +6,31 @@ extern "C" {
#endif
/* 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 */
#define DEST_IP_ADDR0 ((uint8_t)169U)
#define DEST_IP_ADDR1 ((uint8_t)254U)
#define DEST_IP_ADDR2 ((uint8_t)39U)
#define DEST_IP_ADDR3 ((uint8_t)2U)
/*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_ADDR1 ((uint8_t)254U)
#define DEST_IP_ADDR2 ((uint8_t)39U)
#define DEST_IP_ADDR3 ((uint8_t)2U)
/*Static IP ADDRESS*/
#define IP_ADDR0 169
#define IP_ADDR1 254
#define IP_ADDR2 1
#define IP_ADDR3 38
#define IP_ADDR0 169
#define IP_ADDR1 254
#define IP_ADDR2 1
#define IP_ADDR3 38
/*NETMASK*/
#define NETMASK_ADDR0 255
#define NETMASK_ADDR1 255
#define NETMASK_ADDR2 0
#define NETMASK_ADDR3 0
#define NETMASK_ADDR0 255
#define NETMASK_ADDR1 255
#define NETMASK_ADDR2 0
#define NETMASK_ADDR3 0
/*Gateway Address*/
#define GW_ADDR0 192
#define GW_ADDR1 168
#define GW_ADDR2 178
#define GW_ADDR3 1
#define GW_ADDR0 192
#define GW_ADDR1 168
#define GW_ADDR2 178
#define GW_ADDR3 1
#ifdef __cplusplus
}