46 Commits

Author SHA1 Message Date
5b2af728fd set def destination and remove info printoutt 2022-10-17 17:28:46 +02:00
730f1564bc delete old packet 2022-10-17 17:24:32 +02:00
0d106fe4d6 completed CFDP TM funnel impl 2022-10-17 16:58:43 +02:00
4d49d3c1a4 continue CFDP tm funnel impl 2022-10-17 16:49:07 +02:00
88bbde520b pus TM funnel initialize not needed anymore 2022-10-17 16:37:35 +02:00
e0a383f0af continue cfdp funnel impl 2022-10-17 16:35:04 +02:00
7bb9ffc3f7 split up funnel into PUS and CFDP funnel 2022-10-17 16:27:15 +02:00
6bcd0ce05f move some code 2022-09-16 18:36:18 +02:00
d959489cf3 move some extern declarations 2022-09-16 17:04:39 +02:00
86797bb6db run afmt 2022-09-16 17:03:18 +02:00
c6276fca11 add cfdp components to generic factory 2022-09-16 17:02:35 +02:00
29593e3142 afmt 2022-09-15 16:50:26 +02:00
6b914a21fd add common CFDP source entity ID 2022-09-14 14:00:54 +02:00
22585773e7 bugfix in fsfw 2022-09-13 15:31:34 +02:00
e94ef79978 remove include 2022-09-08 17:50:49 +02:00
0818366217 create and schedule CFDP components 2022-09-08 17:39:16 +02:00
a36d951209 add CFDP_DISTRIB and CFDP_HANDLER obj IDs 2022-09-08 16:26:23 +02:00
bf36e7f8f9 run afmt 2022-09-07 18:20:55 +02:00
4ae9f5c746 retval refactoring 2022-09-07 17:40:06 +02:00
2b6a046983 Merge branch 'mueller/tmtc-refactoring' into mueller/cfdp-routers 2022-08-16 17:24:45 +02:00
3f83109513 clean up a bit 2022-08-16 17:18:27 +02:00
9354b1801a ctor argument not required anymore 2022-08-16 17:13:05 +02:00
5792aff5e3 run afmt 2022-08-08 12:32:06 +02:00
d2b15ee4fa updated TMTC router components 2022-08-01 11:11:30 +02:00
85f689debc pass ref instead of ptr 2022-07-28 15:24:32 +02:00
a523f4ab91 ping works now 2022-07-27 17:57:22 +02:00
3acc72470d some clang-tidy imorovements 2022-07-27 17:00:57 +02:00
c483202852 create verification reporter explicitely 2022-07-27 14:39:56 +02:00
43060b3be7 changes for updated TMTC API 2022-07-27 11:33:40 +02:00
a76b0ae56c tmtc refactoring 2022-07-25 10:18:38 +02:00
c564fa37fd common cmake files moved to example_common 2022-05-29 18:41:33 +02:00
ff569dd02c bugfixes & use new lwip mempool for FreeRTOS lwip 2022-05-29 17:34:43 +02:00
d34effb278 run auto-formatter 2022-05-22 15:30:08 +02:00
b53aed9cf9 made script more generic 2022-05-22 15:27:54 +02:00
be6e94bf87 added afmt script 2022-05-22 15:25:13 +02:00
8203995deb renamed objects header 2022-05-20 09:16:59 +02:00
4896003e3f afmt 2022-05-20 08:58:42 +02:00
4bb9e9c996 max num scheduled TCS in cmake config now 2022-05-20 08:58:23 +02:00
f17612bd0e auto-fmt 2022-05-20 08:43:12 +02:00
6b81955c85 new definitions file 2022-05-20 08:42:41 +02:00
21e9987636 afmt cmakelists.txt 2022-05-20 08:38:57 +02:00
6814d0cf2b apply auto-formatter 2022-05-20 08:36:12 +02:00
e1aa39f5e4 i guess no way around exceptions.. 2022-05-08 17:11:43 +02:00
ca501272d8 some refactoring 2022-05-08 02:11:57 +02:00
6984404979 add fmt tests 2022-05-08 02:06:29 +02:00
9d70db97f8 bump subversion 2022-05-05 20:57:30 +02:00
55 changed files with 1111 additions and 520 deletions

View File

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

45
cmake/BuildType.cmake Normal file
View File

@@ -0,0 +1,45 @@
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()

42
cmake/common.cmake Normal file
View File

@@ -0,0 +1,42 @@
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,7 +1,3 @@
target_sources(${TARGET_NAME} PRIVATE target_sources(${TARGET_NAME} PRIVATE commonPollingSequenceFactory.cpp)
commonPollingSequenceFactory.cpp
)
target_include_directories(${TARGET_NAME} PRIVATE target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

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

View File

@@ -0,0 +1,34 @@
#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,11 +4,13 @@
#ifndef COMMON_COMMONCONFIG_H_ #ifndef COMMON_COMMONCONFIG_H_
#define COMMON_COMMONCONFIG_H_ #define COMMON_COMMONCONFIG_H_
#include <stdint.h> #include <cstdint>
#cmakedefine01 FSFW_ADD_FMT_TESTS
//! Specify the debug output verbose level //! Specify the debug output verbose level
#define OBSW_VERBOSE_LEVEL 1 #define OBSW_VERBOSE_LEVEL 1
#define OBSW_TCPIP_UDP_WIRETAPPING 0
#define OBSW_PRINT_MISSED_DEADLINES 0 #define OBSW_PRINT_MISSED_DEADLINES 0
//! Perform internal unit testd at application startup //! Perform internal unit testd at application startup
@@ -16,6 +18,7 @@
//! Add core components for the FSFW and for TMTC communication //! Add core components for the FSFW and for TMTC communication
#define OBSW_ADD_CORE_COMPONENTS 1 #define OBSW_ADD_CORE_COMPONENTS 1
#define OBSW_ADD_CFDP_COMPONENTS 1
//! Add the PUS service stack //! Add the PUS service stack
#define OBSW_ADD_PUS_STACK 1 #define OBSW_ADD_PUS_STACK 1
@@ -33,35 +36,8 @@
#define OBSW_ADD_CONTROLLER_DEMO 1 #define OBSW_ADD_CONTROLLER_DEMO 1
#define OBSW_CONTROLLER_PRINTOUT 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 #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 /* __cplusplus */
#endif /* COMMON_COMMONCONFIG_H_ */ #endif /* COMMON_COMMONCONFIG_H_ */

View File

@@ -25,6 +25,10 @@ enum commonObjects : object_id_t {
CCSDS_DISTRIBUTOR = 0x63000000, CCSDS_DISTRIBUTOR = 0x63000000,
PUS_DISTRIBUTOR = 0x63000001, PUS_DISTRIBUTOR = 0x63000001,
TM_FUNNEL = 0x63000002, TM_FUNNEL = 0x63000002,
CFDP_DISTRIBUTOR = 0x63000003,
CFDP_HANDLER = 0x63000004,
PUS_TM_FUNNEL = 0x63000005,
CFDP_TM_FUNNEL = 0x64000006,
/* 0x74 ('t') for test and example objects */ /* 0x74 ('t') for test and example objects */
TEST_TASK = 0x7400CAFE, TEST_TASK = 0x7400CAFE,

View File

@@ -1,12 +1,11 @@
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h> #include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include "example/test/FsfwExampleTask.h" #include "example/test/FsfwExampleTask.h"
#include "objects/systemObjectList.h" #include "objects/systemObjectList.h"
#include "pollingsequence/pollingSequenceFactory.h" #include "pollingsequence/pollingSequenceFactory.h"
ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF* thisSequence) { ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF *thisSequence) {
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM); thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
@@ -24,19 +23,19 @@ ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF* thisSequence) {
thisSequence->addSlot(objects::TEST_DUMMY_2, 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_3, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == returnvalue::OK) {
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} else { } else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl; sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl;
#else #else
sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n"); sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::OK;
} }
} }
ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF* thisSequence) { ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF *thisSequence) {
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION);
@@ -54,14 +53,14 @@ ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF* thisSequence) {
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == returnvalue::OK) {
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} else { } else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl; sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl;
#else #else
sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n"); sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::OK;
} }
} }

View File

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

View File

@@ -0,0 +1 @@

59
example/cfdp/Config.h Normal file
View File

@@ -0,0 +1,59 @@
#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,3 +1 @@
target_sources(${TARGET_NAME} PRIVATE target_sources(${TARGET_NAME} PRIVATE FsfwTestController.cpp)
FsfwTestController.cpp
)

View File

@@ -10,15 +10,15 @@ FsfwTestController::FsfwTestController(object_id_t objectId, object_id_t device0
deviceDataset0(device0), deviceDataset0(device0),
deviceDataset1(device1) {} deviceDataset1(device1) {}
FsfwTestController::~FsfwTestController() {} FsfwTestController::~FsfwTestController() = default;
ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage* message) { ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage *message) {
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) { LocalDataPoolManager &poolManager) {
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
void FsfwTestController::performControlOperation() { void FsfwTestController::performControlOperation() {
@@ -64,10 +64,10 @@ void FsfwTestController::performControlOperation() {
ReturnValue_t FsfwTestController::initializeAfterTaskCreation() { ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
namespace td = testdevice; namespace td = testdevice;
ReturnValue_t result = TestController::initializeAfterTaskCreation(); ReturnValue_t result = TestController::initializeAfterTaskCreation();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
return result; return result;
} }
HasLocalDataPoolIF* device0 = auto *device0 =
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId()); ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
if (device0 == nullptr) { if (device0 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -81,7 +81,7 @@ ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
ProvidesDataPoolSubscriptionIF* subscriptionIF = device0->getSubscriptionInterface(); ProvidesDataPoolSubscriptionIF *subscriptionIF = device0->getSubscriptionInterface();
if (subscriptionIF != nullptr) { if (subscriptionIF != nullptr) {
/* For DEVICE_0, we only subscribe for notifications */ /* For DEVICE_0, we only subscribe for notifications */
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(), subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(),
@@ -90,7 +90,7 @@ ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
getCommandQueue(), false); getCommandQueue(), false);
} }
HasLocalDataPoolIF* device1 = auto *device1 =
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId()); ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
if (device1 == nullptr) { if (device1 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -115,20 +115,20 @@ ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
return result; return result;
} }
LocalPoolDataSetBase* FsfwTestController::getDataSetHandle(sid_t sid) { return nullptr; } LocalPoolDataSetBase *FsfwTestController::getDataSetHandle(sid_t sid) { return nullptr; }
ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode, ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) { uint32_t *msToReachTheMode) {
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId, void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId,
bool* clearMessage) { bool *clearMessage) {
using namespace std; using namespace std;
if (verboseLevel >= 1) { if (verboseLevel >= 1) {
char const* printout = nullptr; char const *printout = nullptr;
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == store_address_t::invalid()) {
printout = "Notification"; printout = "Notification";
} else { } else {
printout = "Snapshot"; printout = "Snapshot";
@@ -146,7 +146,7 @@ void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId
printout, sid.objectId, sid.ownerSetId); printout, sid.objectId, sid.ownerSetId);
#endif #endif
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == store_address_t::invalid()) {
if (sid.objectId == device0Id) { if (sid.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec); PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec);
float floatVec[3]; float floatVec[3];
@@ -173,12 +173,12 @@ void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId
} }
void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId, void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) { bool *clearMessage) {
using namespace std; using namespace std;
if (verboseLevel >= 1) { if (verboseLevel >= 1) {
char const* printout = nullptr; char const *printout = nullptr;
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == store_address_t::invalid()) {
printout = "Notification"; printout = "Notification";
} else { } else {
printout = "Snapshot"; printout = "Snapshot";
@@ -192,12 +192,13 @@ void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_add
<< globPoolId.localPoolId << dec << setfill(' ') << endl; << globPoolId.localPoolId << dec << setfill(' ') << endl;
#else #else
sif::printInfo( sif::printInfo(
"TestController::handleChangedPoolVariable: %s update from object ID 0x%08x and " "TestController::handleChangedPoolVariable: %s update from "
"object ID 0x%08x and "
"local pool ID %lu\n", "local pool ID %lu\n",
printout, globPoolId.objectId, globPoolId.localPoolId); printout, globPoolId.objectId, globPoolId.localPoolId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == store_address_t::invalid()) {
if (globPoolId.objectId == device0Id) { if (globPoolId.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testUint8Var); PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1

View File

@@ -9,7 +9,7 @@ class FsfwTestController : public TestController {
FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1, FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1,
uint8_t verboseLevel = 0); uint8_t verboseLevel = 0);
virtual ~FsfwTestController(); virtual ~FsfwTestController();
ReturnValue_t handleCommandMessage(CommandMessage* message) override; ReturnValue_t handleCommandMessage(CommandMessage *message) override;
/** /**
* Periodic helper from ControllerBase, implemented by child class. * Periodic helper from ControllerBase, implemented by child class.
@@ -31,14 +31,14 @@ class FsfwTestController : public TestController {
TraceTypes currentTraceType = TraceTypes::NONE; TraceTypes currentTraceType = TraceTypes::NONE;
ReturnValue_t initializeAfterTaskCreation() override; ReturnValue_t initializeAfterTaskCreation() override;
void handleChangedDataset(sid_t sid, store_address_t storeId, bool* clearMessage) override; void handleChangedDataset(sid_t sid, store_address_t storeId, bool *clearMessage) override;
void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId, void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
bool* clearMessage) override; bool *clearMessage) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) override; LocalDataPoolManager &poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override; uint32_t *msToReachTheMode) override;
}; };
#endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */ #endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */

View File

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

View File

@@ -1,15 +1,22 @@
#include "GenericFactory.h" #include "GenericFactory.h"
#include "OBSWConfig.h" #include "common/definitions.h"
#include "definitions.h"
#include "example/cfdp/Config.h"
#include "example/test/FsfwExampleTask.h" #include "example/test/FsfwExampleTask.h"
#include "example/test/FsfwReaderTask.h" #include "example/test/FsfwReaderTask.h"
#include "example/utility/CfdpTmFunnel.h"
#include "example/utility/TmFunnel.h" #include "example/utility/TmFunnel.h"
#include "fsfw/FSFW.h" #include "fsfw/FSFW.h"
#include "fsfw/cfdp.h"
#include "fsfw/cfdp/CfdpDistributor.h"
#include "fsfw/devicehandlers/CookieIF.h" #include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/events/EventManager.h" #include "fsfw/events/EventManager.h"
#include "fsfw/health/HealthTable.h" #include "fsfw/health/HealthTable.h"
#include "fsfw/internalerror/InternalErrorReporter.h" #include "fsfw/internalerror/InternalErrorReporter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/pus/CService200ModeCommanding.h" #include "fsfw/pus/CService200ModeCommanding.h"
#include "fsfw/pus/Service11TelecommandScheduling.h"
#include "fsfw/pus/Service17Test.h" #include "fsfw/pus/Service17Test.h"
#include "fsfw/pus/Service1TelecommandVerification.h" #include "fsfw/pus/Service1TelecommandVerification.h"
#include "fsfw/pus/Service20ParameterManagement.h" #include "fsfw/pus/Service20ParameterManagement.h"
@@ -18,10 +25,11 @@
#include "fsfw/pus/Service5EventReporting.h" #include "fsfw/pus/Service5EventReporting.h"
#include "fsfw/pus/Service8FunctionManagement.h" #include "fsfw/pus/Service8FunctionManagement.h"
#include "fsfw/pus/Service9TimeManagement.h" #include "fsfw/pus/Service9TimeManagement.h"
#include "fsfw/tcdistribution/CCSDSDistributor.h" #include "fsfw/tcdistribution/CcsdsDistributor.h"
#include "fsfw/tcdistribution/PUSDistributor.h" #include "fsfw/tcdistribution/PusDistributor.h"
#include "fsfw/timemanager/TimeStamper.h" #include "fsfw/timemanager/CdsShortTimeStamper.h"
#include "fsfw/tmtcpacket/pus/tm.h" #include "fsfw/tmtcservices/VerificationReporter.h"
#include "fsfw_hal/host/HostFilesystem.h"
#include "fsfw_tests/integration/assemblies/TestAssembly.h" #include "fsfw_tests/integration/assemblies/TestAssembly.h"
#include "fsfw_tests/integration/controller/TestController.h" #include "fsfw_tests/integration/controller/TestController.h"
#include "fsfw_tests/integration/devices/TestCookie.h" #include "fsfw_tests/integration/devices/TestCookie.h"
@@ -29,37 +37,63 @@
#include "fsfw_tests/integration/devices/TestEchoComIF.h" #include "fsfw_tests/integration/devices/TestEchoComIF.h"
#include "fsfw_tests/internal/InternalUnitTester.h" #include "fsfw_tests/internal/InternalUnitTester.h"
#include "objects/systemObjectList.h" #include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
void ObjectFactory::produceGenericObjects() { #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) {
#if OBSW_ADD_CORE_COMPONENTS == 1 #if OBSW_ADD_CORE_COMPONENTS == 1
/* Framework objects */ /* Framework objects */
new EventManager(objects::EVENT_MANAGER); new EventManager(objects::EVENT_MANAGER);
new HealthTable(objects::HEALTH_TABLE); new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new TimeStamper(objects::TIME_STAMPER); auto *stamperAndReader = new CdsShortTimeStamper(objects::TIME_STAMPER);
new CCSDSDistributor(apid::APID, objects::CCSDS_DISTRIBUTOR); new VerificationReporter();
new PUSDistributor(apid::APID, objects::PUS_DISTRIBUTOR, objects::CCSDS_DISTRIBUTOR); *ccsdsDistrib =
new TmFunnel(objects::TM_FUNNEL); 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);
#endif /* OBSW_ADD_CORE_COMPONENTS == 1 */ #endif /* OBSW_ADD_CORE_COMPONENTS == 1 */
/* PUS stack */ /* PUS stack */
#if OBSW_ADD_PUS_STACK == 1 #if OBSW_ADD_PUS_STACK == 1
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, apid::APID, new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, common::COMMON_PUS_APID,
pus::PUS_SERVICE_1, objects::TM_FUNNEL, 5); pus::PUS_SERVICE_1, objects::PUS_TM_FUNNEL, 5);
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, apid::APID, pus::PUS_SERVICE_2, 3, new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, common::COMMON_PUS_APID,
10); pus::PUS_SERVICE_2, 3, 10);
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::APID, pus::PUS_SERVICE_3); new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, common::COMMON_PUS_APID,
new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING, apid::APID, pus::PUS_SERVICE_5, pus::PUS_SERVICE_3);
50); new Service5EventReporting(PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING,
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, apid::APID, 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); pus::PUS_SERVICE_8, 3, 10);
new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT, apid::APID, pus::PUS_SERVICE_9); new Service9TimeManagement(
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::APID, pus::PUS_SERVICE_17); PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, common::COMMON_PUS_APID, pus::PUS_SERVICE_9));
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::APID, 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); pus::PUS_SERVICE_20);
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::APID, #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); pus::PUS_SERVICE_200);
#endif /* OBSW_ADD_PUS_STACK == 1 */ #endif /* OBSW_ADD_PUS_STACK == 1 */
@@ -86,7 +120,7 @@ void ObjectFactory::produceGenericObjects() {
/* Demo device handler object */ /* Demo device handler object */
size_t expectedMaxReplyLen = 64; size_t expectedMaxReplyLen = 64;
CookieIF* testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0), CookieIF *testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0),
expectedMaxReplyLen); expectedMaxReplyLen);
new TestEchoComIF(objects::TEST_ECHO_COM_IF); new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie, new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
@@ -120,6 +154,34 @@ void ObjectFactory::produceGenericObjects() {
InternalUnitTester unittester; InternalUnitTester unittester;
unittester.performTests(testCfg); unittester.performTests(testCfg);
#endif /* OBSW_PERFORM_INTERNAL_UNITTEST == 1 */ #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() { void Factory::setStaticFrameworkObjectIds() {
@@ -130,17 +192,11 @@ void Factory::setStaticFrameworkObjectIds() {
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER; MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
TmFunnel::downlinkDestination = objects::DOWNLINK_DESTINATION; PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_DISTRIBUTOR;
// No storage object for now. PusServiceBase::PACKET_DESTINATION = objects::PUS_TM_FUNNEL;
TmFunnel::storageDestination = objects::NO_OBJECT;
PusServiceBase::packetSource = objects::PUS_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR; CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL; CommandingServiceBase::defaultPacketDestination = objects::PUS_TM_FUNNEL;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
} }

View File

@@ -3,13 +3,23 @@
#include <fsfw/objectmanager/SystemObjectIF.h> #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 { namespace ObjectFactory {
/** /**
* @brief Produce hardware independant objects. Called by bsp specific * @brief Produce hardware independant objects. Called by bsp specific
* object factory. * object factory.
*/ */
void produceGenericObjects(); void produceGenericObjects(PusTmFunnel** pusFunnel, const AcceptsTelemetryIF& tmtcBridge,
CcsdsDistributor** ccsdsDistributor, StorageManagerIF& tcStore,
StorageManagerIF& tmStore);
} // namespace ObjectFactory } // namespace ObjectFactory

View File

@@ -0,0 +1 @@

View File

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

View File

@@ -7,7 +7,7 @@
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "commonSystemObjects.h" #include "commonObjects.h"
#include "objects/systemObjectList.h" #include "objects/systemObjectList.h"
FsfwExampleTask::FsfwExampleTask(object_id_t objectId) FsfwExampleTask::FsfwExampleTask(object_id_t objectId)
@@ -27,13 +27,13 @@ ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) {
// TODO: Move this to new test controller? // TODO: Move this to new test controller?
ReturnValue_t result = performMonitoringDemo(); ReturnValue_t result = performMonitoringDemo();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
return result; return result;
} }
if (operationCode == OpCodes::SEND_RAND_NUM) { if (operationCode == OpCodes::SEND_RAND_NUM) {
result = performSendOperation(); result = performSendOperation();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
return result; return result;
} }
} }
@@ -80,17 +80,18 @@ object_id_t FsfwExampleTask::getSender() {
ReturnValue_t FsfwExampleTask::initialize() { ReturnValue_t FsfwExampleTask::initialize() {
// Get the dataset of the sender. Will be cached for later checks. // Get the dataset of the sender. Will be cached for later checks.
object_id_t sender = getSender(); object_id_t sender = getSender();
HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender); auto *senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
if (senderIF == nullptr) { if (senderIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl; sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl;
#else #else
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n"); sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::FAILED;
} }
// we need a private copy of the previous dataset.. or we use the shared dataset. // we need a private copy of the previous dataset.. or we use the shared
// dataset.
senderSet = new FsfwDemoSet(senderIF); senderSet = new FsfwDemoSet(senderIF);
if (senderSet == nullptr) { if (senderSet == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -98,7 +99,7 @@ ReturnValue_t FsfwExampleTask::initialize() {
#else #else
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n"); sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::FAILED;
} }
return poolManager.initialize(commandQueue); return poolManager.initialize(commandQueue);
} }
@@ -111,22 +112,22 @@ object_id_t FsfwExampleTask::getObjectId() const { return SystemObject::getObjec
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, ReturnValue_t FsfwExampleTask::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) { LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0})); localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0})); localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0}));
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
ReturnValue_t FsfwExampleTask::performMonitoringDemo() { ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
ReturnValue_t result = demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20); ReturnValue_t result = demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
/* Configuration error */ /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl; sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl;
@@ -143,12 +144,12 @@ ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
demoSet.variableLimit.commit(20); demoSet.variableLimit.commit(20);
monitor.check(); monitor.check();
} }
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
ReturnValue_t FsfwExampleTask::performSendOperation() { ReturnValue_t FsfwExampleTask::performSendOperation() {
object_id_t nextRecipient = getNextRecipient(); object_id_t nextRecipient = getNextRecipient();
FsfwExampleTask* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient); auto *target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
if (target == nullptr) { if (target == nullptr) {
/* Configuration error */ /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -156,7 +157,7 @@ ReturnValue_t FsfwExampleTask::performSendOperation() {
#else #else
sif::printError("DummyObject::performOperation: Next recipient does not exist!\n"); sif::printError("DummyObject::performOperation: Next recipient does not exist!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::FAILED;
} }
uint32_t randomNumber = rand() % 100; uint32_t randomNumber = rand() % 100;
@@ -166,7 +167,7 @@ ReturnValue_t FsfwExampleTask::performSendOperation() {
/* Send message using own message queue */ /* Send message using own message queue */
ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message); ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) { if (result != returnvalue::OK && result != MessageQueueIF::FULL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl; sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
#else #else
@@ -177,7 +178,7 @@ ReturnValue_t FsfwExampleTask::performSendOperation() {
/* Send message without via MessageQueueSenderIF */ /* Send message without via MessageQueueSenderIF */
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message, result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
commandQueue->getId()); commandQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) { if (result != returnvalue::OK && result != MessageQueueIF::FULL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl; sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
#else #else
@@ -192,11 +193,11 @@ ReturnValue_t FsfwExampleTask::performSendOperation() {
} }
ReturnValue_t FsfwExampleTask::performReceiveOperation() { ReturnValue_t FsfwExampleTask::performReceiveOperation() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = returnvalue::OK;
while (result != MessageQueueIF::EMPTY) { while (result != MessageQueueIF::EMPTY) {
CommandMessage receivedMessage; CommandMessage receivedMessage;
result = commandQueue->receiveMessage(&receivedMessage); result = commandQueue->receiveMessage(&receivedMessage);
if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::EMPTY) { if (result != returnvalue::OK && result != MessageQueueIF::EMPTY) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Receive failed with " << result << std::endl; sif::debug << "Receive failed with " << result << std::endl;
#endif #endif
@@ -212,11 +213,11 @@ ReturnValue_t FsfwExampleTask::performReceiveOperation() {
#endif #endif
if (senderSet == nullptr) { if (senderSet == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return returnvalue::FAILED;
} }
result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, 20); result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, 20);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
return result; return result;
} }
if (senderSet->variableRead.value != receivedMessage.getParameter()) { if (senderSet->variableRead.value != receivedMessage.getParameter()) {
@@ -235,4 +236,4 @@ ReturnValue_t FsfwExampleTask::performReceiveOperation() {
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

@@ -72,7 +72,7 @@ class FsfwExampleTask : public ExecutableObjectIF, public SystemObject, public H
* task interface handle can be cached to access task specific properties. * task interface handle can be cached to access task specific properties.
* @param task * @param task
*/ */
void setTaskIF(PeriodicTaskIF* task) override; void setTaskIF(PeriodicTaskIF *task) override;
object_id_t getObjectId() const override; object_id_t getObjectId() const override;
@@ -80,19 +80,19 @@ class FsfwExampleTask : public ExecutableObjectIF, public SystemObject, public H
private: private:
LocalDataPoolManager poolManager; LocalDataPoolManager poolManager;
FsfwDemoSet* senderSet = nullptr; FsfwDemoSet *senderSet = nullptr;
FsfwDemoSet demoSet; FsfwDemoSet demoSet;
AbsLimitMonitor<int32_t> monitor; AbsLimitMonitor<int32_t> monitor;
PeriodicTaskIF* task = nullptr; PeriodicTaskIF *task = nullptr;
MessageQueueIF* commandQueue = nullptr; MessageQueueIF *commandQueue = nullptr;
/* HasLocalDatapoolIF overrides */ /* HasLocalDatapoolIF overrides */
MessageQueueId_t getCommandQueue() const override; MessageQueueId_t getCommandQueue() const override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
uint32_t getPeriodicOperationFrequency() const override; uint32_t getPeriodicOperationFrequency() const override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) override; LocalDataPoolManager &poolManager) override;
LocalDataPoolManager* getHkManagerHandle() override; LocalDataPoolManager *getHkManagerHandle() override;
object_id_t getNextRecipient(); object_id_t getNextRecipient();
object_id_t getSender(); object_id_t getSender();

View File

@@ -13,16 +13,17 @@ FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout)
readSet(this->getObjectId(), gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE), 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_2, FsfwDemoSet::PoolIds::VARIABLE),
gp_id_t(objects::TEST_DUMMY_3, 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 */ /* Special protection for set reading because each variable is read from a
* different pool */
readSet.setReadCommitProtectionBehaviour(true); readSet.setReadCommitProtectionBehaviour(true);
} }
FsfwReaderTask::~FsfwReaderTask() {} FsfwReaderTask::~FsfwReaderTask() = default;
ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() { ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() {
/* Give other task some time to set up local data pools. */ /* Give other task some time to set up local data pools. */
TaskFactory::delayTask(20); TaskFactory::delayTask(20);
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }
ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) { ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
@@ -50,5 +51,5 @@ ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
if (variable1 and variable2 and variable3) { if (variable1 and variable2 and variable3) {
}; };
#endif #endif
return HasReturnvaluesIF::RETURN_OK; return returnvalue::OK;
} }

View File

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

View File

@@ -4,11 +4,11 @@
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
void MutexExample::example() { void MutexExample::example() {
MutexIF* mutex = MutexFactory::instance()->createMutex(); MutexIF *mutex = MutexFactory::instance()->createMutex();
MutexIF* mutex2 = MutexFactory::instance()->createMutex(); MutexIF *mutex2 = MutexFactory::instance()->createMutex();
ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, 2 * 60 * 1000); ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, 2 * 60 * 1000);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
#else #else
@@ -17,7 +17,7 @@ void MutexExample::example() {
} }
result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING); result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
#else #else
@@ -26,7 +26,7 @@ void MutexExample::example() {
} }
result = mutex->unlockMutex(); result = mutex->unlockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
#else #else
@@ -35,7 +35,7 @@ void MutexExample::example() {
} }
result = mutex2->unlockMutex(); result = mutex2->unlockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
#else #else

14
example/test/testFmt.cpp Normal file
View File

@@ -0,0 +1,14 @@
#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");
}

162
example/test/testFmt.h Normal file
View File

@@ -0,0 +1,162 @@
#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

@@ -17,7 +17,7 @@ class FsfwDemoSet : public StaticLocalDataSet<3> {
enum PoolIds { VARIABLE, VARIABLE_LIMIT }; enum PoolIds { VARIABLE, VARIABLE_LIMIT };
FsfwDemoSet(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, DEMO_SET_ID) {} FsfwDemoSet(HasLocalDataPoolIF *hkOwner) : StaticLocalDataSet(hkOwner, DEMO_SET_ID) {}
lp_var_t<uint32_t> variableRead = 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>(sid.objectId, PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ);

View File

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

View File

@@ -0,0 +1,84 @@
#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

@@ -0,0 +1,27 @@
#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

@@ -0,0 +1,68 @@
#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

@@ -0,0 +1,39 @@
#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,7 +6,7 @@
namespace task { namespace task {
void printInitError(const char* objName, object_id_t objectId) { void printInitError(const char *objName, object_id_t objectId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "InitMission: Adding object " << objName << "(" << std::setw(8) << std::setfill('0') sif::error << "InitMission: Adding object " << objName << "(" << std::setw(8) << std::setfill('0')
<< std::hex << objectId << std::dec << ") failed." << std::endl; << std::hex << objectId << std::dec << ") failed." << std::endl;

View File

@@ -1,114 +1,16 @@
#include "TmFunnel.h" #include "TmFunnel.h"
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tmtcpacket/pus/tm.h>
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT; TmFunnel::TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel)
object_id_t TmFunnel::storageDestination = objects::NO_OBJECT; : SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel) {}
TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth) TmFunnel::~TmFunnel() = default;
: SystemObject(objectId), messageDepth(messageDepth) {
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
MessageQueueMessage::MAX_MESSAGE_SIZE);
storageQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, MessageQueueMessage::MAX_MESSAGE_SIZE);
}
TmFunnel::~TmFunnel() {}
MessageQueueId_t TmFunnel::getReportReceptionQueue(uint8_t virtualChannel) {
return tmQueue->getId();
}
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) { ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
TmTcMessage currentMessage; pusFunnel.performOperation(operationCode);
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage); cfdpFunnel.performOperation(operationCode);
while (status == HasReturnvaluesIF::RETURN_OK) { return returnvalue::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) { ReturnValue_t TmFunnel::initialize() { return returnvalue::OK; }
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

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

View File

@@ -13,11 +13,13 @@
* *
* Assembled by Jean Rabault * Assembled by Jean Rabault
* *
* UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds
* compilation from macros using the compiler defined __TIME__ macro. This should include Gregorian * since 1st Jan 1970) of compilation from macros using the compiler defined
* calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps. * __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!
* *
*/ */

View File

@@ -4,7 +4,7 @@
#include <OBSWVersion.h> #include <OBSWVersion.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
void utility::commonInitPrint(const char* const os, const char* const board) { void utility::commonInitPrint(const char *const os, const char *const board) {
if (os == nullptr or board == nullptr) { if (os == nullptr or board == nullptr) {
return; return;
} }

View File

@@ -3,7 +3,7 @@
namespace utility { namespace utility {
void commonInitPrint(const char* const os, const char* const board); void commonInitPrint(const char *const os, const char *const board);
} }

44
scripts/auto-formatter.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/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,9 +1,7 @@
target_sources(${TARGET_NAME} PRIVATE target_sources(${TARGET_NAME} PRIVATE STM32TestTask.cpp)
STM32TestTask.cpp
)
option(STM32_ADD_NETWORKING_CODE "Add networking code requiring lwIP" ON) option(STM32_ADD_NETWORKING_CODE "Add networking code requiring lwIP" ON)
if(STM32_ADD_NETWORKING_CODE) if(STM32_ADD_NETWORKING_CODE)
add_subdirectory(networking) add_subdirectory(networking)
endif() endif()

View File

@@ -10,9 +10,17 @@ STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout, bool bli
BSP_LED_Init(LED3); BSP_LED_Init(LED3);
} }
ReturnValue_t STM32TestTask::initialize() {
if (testSpi) {
spiComIF = new SpiComIF(objects::SPI_COM_IF);
spiTest = new SpiTest(*spiComIF);
}
return TestTask::initialize();
}
ReturnValue_t STM32TestTask::performPeriodicAction() { ReturnValue_t STM32TestTask::performPeriodicAction() {
if (blinkyLed) { if (blinkyLed) {
#if OBSW_ETHERNET_USE_LEDS == 0 #if OBSW_ETHERNET_USE_LED1_LED2 == 0
BSP_LED_Toggle(LED1); BSP_LED_Toggle(LED1);
BSP_LED_Toggle(LED2); BSP_LED_Toggle(LED2);
#endif #endif
@@ -23,11 +31,3 @@ ReturnValue_t STM32TestTask::performPeriodicAction() {
} }
return TestTask::performPeriodicAction(); 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

@@ -12,11 +12,11 @@ class STM32TestTask : public TestTask {
ReturnValue_t performPeriodicAction() override; ReturnValue_t performPeriodicAction() override;
private: private:
SpiComIF* spiComIF = nullptr; SpiComIF *spiComIF = nullptr;
SpiTest* spiTest = nullptr; SpiTest *spiTest = nullptr;
bool blinkyLed = false; bool blinkyLed = false;
bool testSpi = true; bool testSpi = false;
}; };
#endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */ #endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */

View File

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

View File

@@ -1,12 +1,10 @@
#include "TmTcLwIpUdpBridge.h" #include "TmTcLwIpUdpBridge.h"
#include <OBSWConfig.h>
#include <fsfw/ipc/MutexGuard.h> #include <fsfw/ipc/MutexGuard.h>
#include <fsfw/serialize/EndianConverter.h> #include <fsfw/serialize/EndianConverter.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
#include "app_ethernet.h" #include "app_ethernet.h"
#include "ethernetif.h"
#include "udp_config.h" #include "udp_config.h"
TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor,
@@ -15,7 +13,7 @@ TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPack
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY; TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
} }
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {} TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() = default;
ReturnValue_t TmTcLwIpUdpBridge::initialize() { ReturnValue_t TmTcLwIpUdpBridge::initialize() {
TmTcBridge::initialize(); TmTcBridge::initialize();
@@ -27,18 +25,19 @@ ReturnValue_t TmTcLwIpUdpBridge::initialize() {
return result; return result;
} }
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) { ReturnValue_t TmTcLwIpUdpBridge::udp_server_init() {
err_t err; err_t err;
/* Create a new UDP control block */ /* Create a new UDP control block */
TmTcLwIpUdpBridge::upcb = udp_new(); TmTcLwIpUdpBridge::upcb = udp_new();
if (TmTcLwIpUdpBridge::upcb) { if (TmTcLwIpUdpBridge::upcb) {
sif::printInfo("Opening UDP server on port %d\n", UDP_SERVER_PORT);
/* Bind the upcb to the UDP_PORT port */ /* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT); err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
if (err == ERR_OK) { if (err == ERR_OK) {
/* Set a receive callback for the upcb */ /* Set a receive callback for the upcb */
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, (void*)this); udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, (void *)this);
return RETURN_OK; return RETURN_OK;
} else { } else {
udp_remove(TmTcLwIpUdpBridge::upcb); udp_remove(TmTcLwIpUdpBridge::upcb);
@@ -52,9 +51,9 @@ ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) {
ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) { ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
TmTcBridge::performOperation(); TmTcBridge::performOperation();
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
if (connectFlag) { if (connectFlag) {
uint32_t ipAddress = ((ip4_addr*)&lastAdd)->addr; uint32_t ipAddress = ((ip4_addr *)&lastAdd)->addr;
int ipAddress1 = (ipAddress & 0xFF000000) >> 24; int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
int ipAddress2 = (ipAddress & 0xFF0000) >> 16; int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
int ipAddress3 = (ipAddress & 0xFF00) >> 8; int ipAddress3 = (ipAddress & 0xFF00) >> 8;
@@ -79,11 +78,11 @@ ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
return RETURN_OK; return RETURN_OK;
} }
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t* data, size_t dataLen) { ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
struct pbuf* p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM); struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) { if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
/* copy data to pbuf */ /* copy data to pbuf */
err_t err = pbuf_take(p_tx, (char*)data, dataLen); err_t err = pbuf_take(p_tx, (const char *)data, dataLen);
if (err != ERR_OK) { if (err != ERR_OK) {
pbuf_free(p_tx); pbuf_free(p_tx);
return err; return err;
@@ -109,23 +108,24 @@ ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t* data, size_t dataLen) {
return RETURN_OK; return RETURN_OK;
} }
void TmTcLwIpUdpBridge::udp_server_receive_callback(void* arg, struct udp_pcb* upcb_, void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg, struct udp_pcb *upcb_,
struct pbuf* p, const ip_addr_t* addr, struct pbuf *p, const ip_addr_t *addr,
u16_t port) { u16_t port) {
struct pbuf* p_tx = nullptr; auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge *>(arg);
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge*>(arg);
if (udpBridge == nullptr) { if (udpBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!" sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!"
<< std::endl; << std::endl;
#else #else
sif::printWarning("TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!\n"); sif::printWarning(
"TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid "
"UDP bridge!\n");
#endif #endif
} }
/* allocate pbuf from RAM*/ /* allocate pbuf from RAM*/
p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM); struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
if (p_tx != NULL) { if (p_tx != nullptr) {
if (udpBridge != nullptr) { if (udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock); MutexGuard lg(udpBridge->bridgeLock);
udpBridge->upcb = upcb_; udpBridge->upcb = upcb_;
@@ -133,25 +133,25 @@ void TmTcLwIpUdpBridge::udp_server_receive_callback(void* arg, struct udp_pcb* u
udpBridge->lastPort = port; udpBridge->lastPort = port;
if (not udpBridge->comLinkUp()) { if (not udpBridge->comLinkUp()) {
udpBridge->registerCommConnect(); udpBridge->registerCommConnect();
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
udpBridge->connectFlag = true; udpBridge->connectFlag = true;
#endif #endif
/* This should have already been done, but we will still do it */ /* This should have already been done, but we will still do it */
udpBridge->physicalConnectStatusChange(true); udpBridge->physicalConnectStatusChange(true);
} }
} }
pbuf_take(p_tx, (char*)p->payload, p->len); pbuf_take(p_tx, (char *)p->payload, p->len);
/* send the received data to the uart port */ /* send the received data to the uart port */
char* data = reinterpret_cast<char*>(p_tx->payload); char *data = reinterpret_cast<char *>(p_tx->payload);
*(data + p_tx->len) = '\0'; *(data + p_tx->len) = '\0';
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
udpBridge->printData(p, data); udpBridge->printData(reinterpret_cast<uint8_t *>(p->payload), p->len);
#endif #endif
store_address_t storeId; store_address_t storeId;
ReturnValue_t returnValue = ReturnValue_t returnValue =
udpBridge->tcStore->addData(&storeId, reinterpret_cast<uint8_t*>(p->payload), p->len); udpBridge->tcStore->addData(&storeId, reinterpret_cast<uint8_t *>(p->payload), p->len);
if (returnValue != RETURN_OK) { if (returnValue != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UDP Server: Data storage failed" << std::endl; sif::warning << "UDP Server: Data storage failed" << std::endl;
@@ -178,8 +178,8 @@ bool TmTcLwIpUdpBridge::comLinkUp() const { return communicationLinkUp; }
/* Caller must ensure thread-safety */ /* Caller must ensure thread-safety */
void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) { void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) {
if (connect) { if (connect) {
/* Physical connection does not mean there is a recipient to send packets too. /* Physical connection does not mean there is a recipient to send packets
This will be done by the receive callback! */ too. This will be done by the receive callback! */
physicalConnection = true; physicalConnection = true;
} else { } else {
physicalConnection = false; physicalConnection = false;

View File

@@ -1,14 +1,15 @@
#ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ #ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ #define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#include <fsfw/tmtcservices/TmTcBridge.h>
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include <lwip/udp.h> #include <lwip/udp.h>
#define TCPIP_RECV_WIRETAPPING 0 #include "commonConfig.h"
#include "fsfw/tmtcservices/TmTcBridge.h"
/** /**
* This bridge is used to forward TMTC packets received via LwIP UDP to the internal software bus. * This bridge is used to forward TMTC packets received via LwIP UDP to the
* internal software bus.
*/ */
class TmTcLwIpUdpBridge : public TmTcBridge { class TmTcLwIpUdpBridge : public TmTcBridge {
friend class UdpTcLwIpPollingTask; friend class UdpTcLwIpPollingTask;
@@ -16,9 +17,9 @@ class TmTcLwIpUdpBridge : public TmTcBridge {
public: public:
TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, object_id_t tmStoreId, TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
object_id_t tcStoreId); object_id_t tcStoreId);
virtual ~TmTcLwIpUdpBridge(); ~TmTcLwIpUdpBridge() override;
virtual ReturnValue_t initialize() override; ReturnValue_t initialize() override;
ReturnValue_t udp_server_init(); ReturnValue_t udp_server_init();
/** /**
@@ -26,14 +27,14 @@ class TmTcLwIpUdpBridge : public TmTcBridge {
* @param operationCode * @param operationCode
* @return * @return
*/ */
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t performOperation(uint8_t operationCode) override;
/** TM Send implementation uses udp_send function from lwIP stack /** TM Send implementation uses udp_send function from lwIP stack
* @param data * @param data
* @param dataLen * @param dataLen
* @return * @return
*/ */
virtual ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override; ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override;
/** /**
* @brief This function is called when an UDP datagram has been * @brief This function is called when an UDP datagram has been
@@ -52,24 +53,24 @@ class TmTcLwIpUdpBridge : public TmTcBridge {
* Caller must ensure thread-safety by using the bridge lock. * Caller must ensure thread-safety by using the bridge lock.
* @return * @return
*/ */
bool comLinkUp() const; [[nodiscard]] bool comLinkUp() const;
private: private:
struct udp_pcb *upcb = nullptr; struct udp_pcb *upcb = nullptr;
ip_addr_t lastAdd; ip_addr_t lastAdd{};
u16_t lastPort = 0; u16_t lastPort = 0;
bool physicalConnection = false; bool physicalConnection = false;
MutexIF *bridgeLock = nullptr; MutexIF *bridgeLock = nullptr;
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
bool connectFlag = false; bool connectFlag = false;
#endif #endif
/** /**
* Used to notify bridge about change in the physical ethernet connection. * Used to notify bridge about change in the physical ethernet connection.
* Connection does not mean that replies are possible (recipient not set yet), but * Connection does not mean that replies are possible (recipient not set yet),
* disconnect means that we can't send anything. Caller must ensure thread-safety * but disconnect means that we can't send anything. Caller must ensure
* by using the bridge lock. * thread-safety by using the bridge lock.
*/ */
void physicalConnectStatusChange(bool connect); void physicalConnectStatusChange(bool connect);
}; };

View File

@@ -1,7 +1,5 @@
#include "UdpTcLwIpPollingTask.h" #include "UdpTcLwIpPollingTask.h"
#include <hardware_init.h>
#include "TmTcLwIpUdpBridge.h" #include "TmTcLwIpUdpBridge.h"
#include "app_dhcp.h" #include "app_dhcp.h"
#include "app_ethernet.h" #include "app_ethernet.h"
@@ -13,10 +11,10 @@
#include "networking.h" #include "networking.h"
UdpTcLwIpPollingTask::UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, UdpTcLwIpPollingTask::UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId,
struct netif* gnetif) struct netif *gnetif)
: SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) {} : SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) {}
UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() {} UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() = default;
ReturnValue_t UdpTcLwIpPollingTask::initialize() { ReturnValue_t UdpTcLwIpPollingTask::initialize() {
udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId); udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId);

View File

@@ -1,5 +1,4 @@
#ifndef BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ #pragma once
#define BSP_STM32_RTEMS_EMACPOLLINGTASK_H_
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h> #include <fsfw/returnvalues/HasReturnvaluesIF.h>
@@ -16,24 +15,22 @@ class UdpTcLwIpPollingTask : public SystemObject,
public ExecutableObjectIF, public ExecutableObjectIF,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif* gnetif); UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif *gnetif);
virtual ~UdpTcLwIpPollingTask(); ~UdpTcLwIpPollingTask() override;
virtual ReturnValue_t initialize() override; ReturnValue_t initialize() override;
/** /**
* Executed periodically. * Executed periodically.
* @param operationCode * @param operationCode
* @return * @return
*/ */
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t performOperation(uint8_t operationCode) override;
private: private:
static const uint8_t PERIODIC_HANDLE_TRIGGER = 5; static const uint8_t PERIODIC_HANDLE_TRIGGER = 5;
uint8_t periodicHandleCounter; uint8_t periodicHandleCounter;
object_id_t bridgeId = 0; object_id_t bridgeId = 0;
TmTcLwIpUdpBridge* udpBridge = nullptr; TmTcLwIpUdpBridge *udpBridge = nullptr;
struct netif* gnetif = nullptr; struct netif *gnetif = nullptr;
}; };
#endif /* BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ */

View File

@@ -1,8 +1,6 @@
#include "app_dhcp.h" #include "app_dhcp.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "networking.h" #include "networking.h"
#include "stm32h7xx_nucleo.h" #include "stm32h7xx_nucleo.h"
@@ -13,18 +11,18 @@
uint8_t DHCP_state = DHCP_OFF; uint8_t DHCP_state = DHCP_OFF;
uint32_t DHCPfineTimer = 0; uint32_t DHCPfineTimer = 0;
void handle_dhcp_timeout(struct netif* netif); void handle_dhcp_timeout(struct netif *netif);
void handle_dhcp_start(struct netif* netif); void handle_dhcp_start(struct netif *netif);
void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp); void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp);
void handle_dhcp_down(struct netif* netif); void handle_dhcp_down(struct netif *netif);
/** /**
* @brief DHCP_Process_Handle * @brief DHCP_Process_Handle
* @param None * @param None
* @retval None * @retval None
*/ */
void DHCP_Process(struct netif* netif) { void DHCP_Process(struct netif *netif) {
struct dhcp* dhcp = NULL; struct dhcp *dhcp = nullptr;
switch (DHCP_state) { switch (DHCP_state) {
case DHCP_START: { case DHCP_START: {
handle_dhcp_start(netif); handle_dhcp_start(netif);
@@ -45,7 +43,7 @@ void DHCP_Process(struct netif* netif) {
} }
} }
void handle_dhcp_timeout(struct netif* netif) { void handle_dhcp_timeout(struct netif *netif) {
ip_addr_t ipaddr; ip_addr_t ipaddr;
ip_addr_t netmask; ip_addr_t netmask;
ip_addr_t gw; ip_addr_t gw;
@@ -61,11 +59,11 @@ void handle_dhcp_timeout(struct netif* netif) {
printf("DHCP Timeout\n\r"); printf("DHCP Timeout\n\r");
uint8_t iptxt[20]; uint8_t iptxt[20];
sprintf((char*)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif))); sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
printf("Assigning static IP address: %s\n", iptxt); printf("Assigning static IP address: %s\n", iptxt);
#if defined FSFW_OSAL_FREERTOS #if defined FSFW_OSAL_FREERTOS
ETH_HandleTypeDef* handle = getEthernetHandle(); ETH_HandleTypeDef *handle = getEthernetHandle();
handle->gState = HAL_ETH_STATE_READY; handle->gState = HAL_ETH_STATE_READY;
#endif #endif
@@ -82,7 +80,7 @@ void handle_dhcp_timeout(struct netif* netif) {
* @param netif * @param netif
* @retval None * @retval None
*/ */
void DHCP_Periodic_Handle(struct netif* netif) { void DHCP_Periodic_Handle(struct netif *netif) {
/* Fine DHCP periodic process every 500ms */ /* Fine DHCP periodic process every 500ms */
if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) { if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
DHCPfineTimer = HAL_GetTick(); DHCPfineTimer = HAL_GetTick();
@@ -91,7 +89,7 @@ void DHCP_Periodic_Handle(struct netif* netif) {
} }
} }
void handle_dhcp_start(struct netif* netif) { void handle_dhcp_start(struct netif *netif) {
printf("handle_dhcp_start: Looking for DHCP server ...\n\r"); printf("handle_dhcp_start: Looking for DHCP server ...\n\r");
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
@@ -106,7 +104,7 @@ void handle_dhcp_start(struct netif* netif) {
DHCP_state = DHCP_WAIT_ADDRESS; DHCP_state = DHCP_WAIT_ADDRESS;
} }
void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) { void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp) {
if (dhcp_supplied_address(netif)) { if (dhcp_supplied_address(netif)) {
DHCP_state = DHCP_ADDRESS_ASSIGNED; DHCP_state = DHCP_ADDRESS_ASSIGNED;
printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif))); printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
@@ -118,7 +116,8 @@ void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) {
#endif #endif
#endif #endif
} else { } else {
*dhcp = (struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); *dhcp =
static_cast<struct dhcp *>(netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP));
/* DHCP timeout */ /* DHCP timeout */
if ((*dhcp)->tries > MAX_DHCP_TRIES) { if ((*dhcp)->tries > MAX_DHCP_TRIES) {
@@ -127,7 +126,8 @@ void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) {
} }
} }
void handle_dhcp_down(struct netif* netif) { void handle_dhcp_down(struct netif *netif) {
static_cast<void>(netif);
DHCP_state = DHCP_OFF; DHCP_state = DHCP_OFF;
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
printf("DHCP_Process: The network cable is not connected.\n\r"); printf("DHCP_Process: The network cable is not connected.\n\r");

View File

@@ -21,7 +21,7 @@
uint32_t ethernetLinkTimer = 0; uint32_t ethernetLinkTimer = 0;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
void handle_status_change(struct netif* netif, bool link_up); void handle_status_change(struct netif *netif, bool link_up);
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/** /**
@@ -29,7 +29,7 @@ void handle_status_change(struct netif* netif, bool link_up);
* @param netif: the network interface * @param netif: the network interface
* @retval None * @retval None
*/ */
void networking::ethernetLinkStatusUpdated(struct netif* netif) { void networking::ethernetLinkStatusUpdated(struct netif *netif) {
if (netif_is_link_up(netif)) { if (netif_is_link_up(netif)) {
networking::setEthCableConnected(true); networking::setEthCableConnected(true);
handle_status_change(netif, true); handle_status_change(netif, true);
@@ -39,14 +39,14 @@ void networking::ethernetLinkStatusUpdated(struct netif* netif) {
} }
} }
void handle_status_change(struct netif* netif, bool link_up) { void handle_status_change(struct netif *netif, bool link_up) {
if (link_up) { if (link_up) {
#if LWIP_DHCP #if LWIP_DHCP
/* Update DHCP state machine */ /* Update DHCP state machine */
set_dhcp_state(DHCP_START); set_dhcp_state(DHCP_START);
#else #else
uint8_t iptxt[20]; uint8_t iptxt[20];
sprintf((char*)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif))); sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt, printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt,
UDP_SERVER_PORT); UDP_SERVER_PORT);
#if OBSW_ETHERNET_USE_LED1_LED2 == 1 #if OBSW_ETHERNET_USE_LED1_LED2 == 1
@@ -75,7 +75,7 @@ void handle_status_change(struct netif* netif, bool link_up) {
* @param netif * @param netif
* @retval None * @retval None
*/ */
void networking::ethernetLinkPeriodicHandle(struct netif* netif) { void networking::ethernetLinkPeriodicHandle(struct netif *netif) {
/* Ethernet Link every 100ms */ /* Ethernet Link every 100ms */
if (HAL_GetTick() - ethernetLinkTimer >= 100) { if (HAL_GetTick() - ethernetLinkTimer >= 100) {
ethernetLinkTimer = HAL_GetTick(); ethernetLinkTimer = HAL_GetTick();

View File

@@ -46,15 +46,16 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "ethernetif.h" #include "ethernetif.h"
#include <lan8742.h> #include <stdbool.h>
#include <lwip/netif.h>
#include <lwip/opt.h>
#include <lwip/timeouts.h>
#include <netif/etharp.h>
#include <stm32h7xx_hal.h>
#include <string.h> #include <string.h>
#include "fsfw/FSFW.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"
#ifdef FSFW_OSAL_RTEMS #ifdef FSFW_OSAL_RTEMS
#include <rtems.h> #include <rtems.h>
@@ -66,14 +67,20 @@
#define IFNAME0 's' #define IFNAME0 's'
#define IFNAME1 't' #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 #define DMA_DESCRIPTOR_ALIGNMENT 0x20
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
/* /*
@Note: This interface is implemented to operate in zero-copy mode only: @Note: This interface is implemented to operate in zero-copy mode only:
- Rx buffers are allocated statically and passed directly to the LwIP stack - Rx buffers are allocated statically and passed directly to the LwIP
they will return back to DMA after been processed by the stack. stack they will return back to DMA after been processed by the stack.
- Tx Buffers will be allocated from LwIP stack memory heap, - Tx Buffers will be allocated from LwIP stack memory heap,
then passed to ETH HAL driver. then passed to ETH HAL driver.
@@ -87,15 +94,19 @@
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must 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) 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 #pragma location = 0x30000000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location = 0x30040060 #pragma location = 0x30000200
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location = 0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
#elif defined(__CC_ARM) /* MDK ARM Compiler */ #elif defined(__CC_ARM) /* MDK ARM Compiler */
@@ -103,8 +114,6 @@ __attribute__((section(".RxDecripSection")))
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((section(".TxDecripSection"))) __attribute__((section(".TxDecripSection")))
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((section(".RxArraySection")))
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
#elif defined(__GNUC__) /* GNU Compiler */ #elif defined(__GNUC__) /* GNU Compiler */
@@ -117,44 +126,60 @@ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
__attribute__((section(".bsp_nocache"), __attribute__((section(".bsp_nocache"),
__aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */ __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */
/* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely placing it */ /* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely
* placing it */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
#elif defined FSFW_OSAL_FREERTOS #elif defined FSFW_OSAL_FREERTOS
/* Placement and alignment specified in linker script here */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
__attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
__attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ __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_OSAL_RTEMS */
#endif /* FSFW_FREERTOS */
#endif /* defined ( __GNUC__ ) */ #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 */ /* Global boolean to track ethernet connection */
bool ethernet_cable_connected; bool ethernet_cable_connected;
struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT]; /* Variable Definitions */
uint32_t current_pbuf_idx = 0; static uint8_t RxAllocStatus;
/* Global Ethernet handle*/
ETH_HandleTypeDef EthHandle; ETH_HandleTypeDef EthHandle;
ETH_TxPacketConfig TxConfig; ETH_TxPacketConfig TxConfig;
lan8742_Object_t LAN8742;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
u32_t sys_now(void); u32_t sys_now(void);
void pbuf_free_custom(struct pbuf *p); extern void Error_Handler(void);
int32_t ETH_PHY_IO_Init(void); int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit(void); int32_t ETH_PHY_IO_DeInit(void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void); int32_t ETH_PHY_IO_GetTick(void);
lan8742_Object_t LAN8742;
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg, lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick}; ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick};
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
void pbuf_free_custom(struct pbuf *p);
/******************************************************************************* /*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH) LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/ *******************************************************************************/
@@ -166,7 +191,6 @@ lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_
* for this ethernetif * for this ethernetif
*/ */
static void low_level_init(struct netif *netif) { static void low_level_init(struct netif *netif) {
uint32_t idx = 0;
uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2,
ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5}; ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
@@ -181,15 +205,15 @@ static void low_level_init(struct netif *netif) {
HAL_ETH_Init(&EthHandle); HAL_ETH_Init(&EthHandle);
/* set MAC hardware address length */ /* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN; netif->hwaddr_len = ETH_HWADDR_LEN;
/* set MAC hardware address */ /* set MAC hardware address */
netif->hwaddr[0] = 0x02; netif->hwaddr[0] = ETH_MAC_ADDR0;
netif->hwaddr[1] = 0x00; netif->hwaddr[1] = ETH_MAC_ADDR1;
netif->hwaddr[2] = 0x00; netif->hwaddr[2] = ETH_MAC_ADDR2;
netif->hwaddr[3] = 0x00; netif->hwaddr[3] = ETH_MAC_ADDR3;
netif->hwaddr[4] = 0x00; netif->hwaddr[4] = ETH_MAC_ADDR4;
netif->hwaddr[5] = 0x00; netif->hwaddr[5] = ETH_MAC_ADDR5;
/* maximum transfer unit */ /* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD; netif->mtu = ETH_MAX_PAYLOAD;
@@ -198,12 +222,8 @@ static void low_level_init(struct netif *netif) {
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
for (idx = 0; idx < ETH_RX_DESC_CNT; idx++) { /* Initialize the RX POOL */
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL); LWIP_MEMPOOL_INIT(RX_POOL);
/* Set Custom pbuf free function */
rx_pbuf[idx].custom_free_function = pbuf_free_custom;
}
/* Set Tx packet config common parameters */ /* Set Tx packet config common parameters */
memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig)); memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
@@ -221,12 +241,13 @@ static void low_level_init(struct netif *netif) {
} }
/** /**
* @brief This function should do the actual transmission of the packet. The packet is * @brief This function should do the actual transmission of the packet. The
* contained in the pbuf that is passed to the function. This pbuf * packet is contained in the pbuf that is passed to the function. This pbuf
* might be chained. * might be chained.
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) * @param p the MAC packet to send (e.g. IP packet including MAC addresses and
* type)
* @return ERR_OK if the packet could be sent * @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent * an err_t value if the packet couldn't be sent
* *
@@ -236,17 +257,18 @@ static void low_level_init(struct netif *netif) {
* dropped because of memory failure (except for the TCP timers). * dropped because of memory failure (except for the TCP timers).
*/ */
static err_t low_level_output(struct netif *netif, struct pbuf *p) { static err_t low_level_output(struct netif *netif, struct pbuf *p) {
uint32_t i = 0, framelen = 0; uint32_t i = 0U;
struct pbuf *q; struct pbuf *q = NULL;
err_t errval = ERR_OK; err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; 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) { for (q = p; q != NULL; q = q->next) {
if (i >= ETH_TX_DESC_CNT) return ERR_IF; if (i >= ETH_TX_DESC_CNT) return ERR_IF;
Txbuffer[i].buffer = q->payload; Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len; Txbuffer[i].len = q->len;
framelen += q->len;
if (i > 0) { if (i > 0) {
Txbuffer[i - 1].next = &Txbuffer[i]; Txbuffer[i - 1].next = &Txbuffer[i];
@@ -259,15 +281,14 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) {
i++; i++;
} }
TxConfig.Length = framelen; TxConfig.Length = p->tot_len;
TxConfig.TxBuffer = Txbuffer; TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20); HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
if (ret != HAL_OK) { if (ret != HAL_OK) {
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret); printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
} }
return errval; return errval;
} }
@@ -281,59 +302,35 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) {
*/ */
static struct pbuf *low_level_input(struct netif *netif) { static struct pbuf *low_level_input(struct netif *netif) {
struct pbuf *p = NULL; struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0;
if (HAL_ETH_IsRxDataAvailable(&EthHandle)) { if (RxAllocStatus == RX_ALLOC_OK) {
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff); HAL_ETH_ReadData(&EthHandle, (void **)&p);
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;
}
return p;
} else {
return NULL;
} }
return p;
} }
/** /**
* @brief This function is the ethernetif_input task, it is processed when a packet * @brief This function is the ethernetif_input task, it is processed when a
* is ready to be read from the interface. It uses the function low_level_input() * packet is ready to be read from the interface. It uses the function
* that should handle the actual reception of bytes from the network * low_level_input() that should handle the actual reception of bytes from the
* interface. Then the type of the received packet is determined and * network interface. Then the type of the received packet is determined and the
* the appropriate input function is called. * appropriate input function is called.
* *
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
*/ */
void ethernetif_input(struct netif *netif) { void ethernetif_input(struct netif *netif) {
err_t err; struct pbuf *p = NULL;
struct pbuf *p;
/* move received packet into a new pbuf */ do {
p = low_level_input(netif); p = low_level_input(netif);
if (p != NULL) {
if (netif->input(p, netif) != ERR_OK) {
pbuf_free(p);
}
}
/* no packet could be read, silently ignore this */ } while (p != NULL);
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);
} }
/** /**
@@ -358,6 +355,7 @@ err_t ethernetif_init(struct netif *netif) {
netif->name[0] = IFNAME0; netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1; netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call. /* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output() * 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 * from it if you have to do some checks before sending (e.g. if link
@@ -377,12 +375,12 @@ err_t ethernetif_init(struct netif *netif) {
* @retval None * @retval None
*/ */
void pbuf_free_custom(struct pbuf *p) { void pbuf_free_custom(struct pbuf *p) {
if (p != NULL) { struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
p->flags = 0; LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
p->next = NULL; /* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
p->len = p->tot_len = 0; * call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
p->ref = 0; if (RxAllocStatus == RX_ALLOC_ERROR) {
p->payload = NULL; RxAllocStatus = RX_ALLOC_OK;
} }
} }
@@ -413,7 +411,8 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE();
/* Ethernet pins configuration ************************************************/ /* Ethernet pins configuration
* ************************************************/
/* /*
RMII_REF_CLK ----------------------> PA1 RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2 RMII_MDIO -------------------------> PA2
@@ -526,14 +525,14 @@ int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); }
* @retval None * @retval None
*/ */
void ethernet_link_check_state(struct netif *netif) { void ethernet_link_check_state(struct netif *netif) {
ETH_MACConfigTypeDef MACConf; ETH_MACConfigTypeDef MACConf = {0};
uint32_t PHYLinkState; int32_t PHYLinkState = 0U;
uint32_t linkchanged = 0, speed = 0, duplex = 0; uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
PHYLinkState = LAN8742_GetLinkState(&LAN8742); PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) { if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) {
HAL_ETH_Stop(&EthHandle); HAL_ETH_Stop_IT(&EthHandle);
netif_set_down(netif); netif_set_down(netif);
netif_set_link_down(netif); netif_set_link_down(netif);
} else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) { } else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) {
@@ -568,13 +567,62 @@ void ethernet_link_check_state(struct netif *netif) {
MACConf.DuplexMode = duplex; MACConf.DuplexMode = duplex;
MACConf.Speed = speed; MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&EthHandle, &MACConf); HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
HAL_ETH_Start(&EthHandle); HAL_ETH_Start_IT(&EthHandle);
netif_set_up(netif); netif_set_up(netif);
netif_set_link_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;
}
}
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; } ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; }
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -46,7 +46,6 @@
#ifndef __ETHERNETIF_H__ #ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__ #define __ETHERNETIF_H__
#include <stdbool.h>
#include <stm32h7xx_hal.h> #include <stm32h7xx_hal.h>
#include "lwip/err.h" #include "lwip/err.h"
@@ -56,8 +55,6 @@
extern "C" { extern "C" {
#endif #endif
#define ETH_RX_BUFFER_SIZE (1536UL)
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
ETH_HandleTypeDef *getEthernetHandle(); ETH_HandleTypeDef *getEthernetHandle();
@@ -67,7 +64,6 @@ void ethernet_link_check_state(struct netif *netif);
extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];
extern ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_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 #ifdef __cplusplus
} }

View File

@@ -8,7 +8,7 @@ void networking::setEthCableConnected(bool status) { ethernetCableConnected = st
bool networking::getEthCableConnected() { return ethernetCableConnected; } bool networking::getEthCableConnected() { return ethernetCableConnected; }
void networking::setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw) { void networking::setLwipAddresses(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);

View File

@@ -7,7 +7,7 @@ namespace networking {
void setEthCableConnected(bool status); void setEthCableConnected(bool status);
bool getEthCableConnected(); bool getEthCableConnected();
void setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw); void setLwipAddresses(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw);
} // namespace networking } // namespace networking

View File

@@ -8,7 +8,8 @@ extern "C" {
/* UDP local connection port. Client needs to bind to this port */ /* UDP local connection port. Client needs to bind to this port */
#define UDP_SERVER_PORT 7 #define UDP_SERVER_PORT 7
/*Static DEST IP ADDRESS: DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */ /*Static DEST IP ADDRESS:
* DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */
#define DEST_IP_ADDR0 ((uint8_t)169U) #define DEST_IP_ADDR0 ((uint8_t)169U)
#define DEST_IP_ADDR1 ((uint8_t)254U) #define DEST_IP_ADDR1 ((uint8_t)254U)
#define DEST_IP_ADDR2 ((uint8_t)39U) #define DEST_IP_ADDR2 ((uint8_t)39U)