Compare commits
No commits in common. "main" and "mueller/example-to-test" have entirely different histories.
main
...
mueller/ex
@ -1,8 +1,10 @@
|
||||
add_subdirectory(config)
|
||||
add_subdirectory(example)
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if(TGT_BSP MATCHES "arm/stm32h743zi-nucleo")
|
||||
add_subdirectory(stm32h7)
|
||||
add_subdirectory(stm32h7)
|
||||
endif()
|
||||
|
@ -1,45 +0,0 @@
|
||||
function(set_build_type)
|
||||
|
||||
message(STATUS "Used build generator: ${CMAKE_GENERATOR}")
|
||||
|
||||
# Set a default build type if none was specified
|
||||
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
set(DEFAULT_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS
|
||||
"Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified."
|
||||
)
|
||||
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE
|
||||
STRING "Choose the type of build." FORCE
|
||||
)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Release" "MinSizeRel" "RelWithDebInfo"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
message(STATUS
|
||||
"Building Debug application with flags: ${CMAKE_C_FLAGS_DEBUG}"
|
||||
)
|
||||
elseif(${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo")
|
||||
message(STATUS
|
||||
"Building Release (Debug) application with "
|
||||
"flags: ${CMAKE_C_FLAGS_RELWITHDEBINFO}"
|
||||
)
|
||||
elseif(${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
|
||||
message(STATUS
|
||||
"Building Release (Size) application with "
|
||||
"flags: ${CMAKE_C_FLAGS_MINSIZEREL}"
|
||||
)
|
||||
else()
|
||||
message(STATUS
|
||||
"Building Release (Speed) application with "
|
||||
"flags: ${CMAKE_C_FLAGS_RELEASE}"
|
||||
)
|
||||
endif()
|
||||
|
||||
endfunction()
|
@ -1,42 +0,0 @@
|
||||
function(get_common_build_flags TGT_NAME)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(COMMON_COMPILE_OPTS
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
PARENT_SCOPE)
|
||||
set(COMMON_LINK_OPTS
|
||||
-Wl,--gc-sections
|
||||
-Wl,-Map=${TARGET_NAME}.map
|
||||
PARENT_SCOPE)
|
||||
set(COMMON_WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
-Wduplicated-cond # check for duplicate conditions
|
||||
-Wduplicated-branches # check for duplicate branches
|
||||
-Wlogical-op # Search for bitwise operations instead of logical
|
||||
-Wnull-dereference # Search for NULL dereference
|
||||
-Wundef # Warn if undefind marcos are used
|
||||
-Wformat=2 # Format string problem detection
|
||||
-Wformat-overflow=2 # Formatting issues in printf
|
||||
-Wformat-truncation=2 # Formatting issues in printf
|
||||
-Wformat-security # Search for dangerous printf operations
|
||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||
-Warray-bounds=2 # Some array bounds violations will be found
|
||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||
-Wcast-qual # Warn if the constness is cast away
|
||||
-Wstringop-overflow=4
|
||||
# -Wstack-protector # Emits a few false positives for low level access
|
||||
# -Wconversion # Creates many false positives -Warith-conversion # Use
|
||||
# with Wconversion to find more implicit conversions -fanalyzer # Should
|
||||
# be used to look through problems
|
||||
PARENT_SCOPE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
add_compile_options(/permissive- /d2SSAOptimizer-)
|
||||
# To avoid nameclashes with min and max macro
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif()
|
||||
|
||||
endfunction()
|
@ -1,3 +1,7 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE commonPollingSequenceFactory.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
commonPollingSequenceFactory.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef COMMON_OBSWVERSION_H_
|
||||
#define COMMON_OBSWVERSION_H_
|
||||
|
||||
#define FSFW_EXAMPLE_VERSION 1
|
||||
#define FSFW_EXAMPLE_SUBVERSION 5
|
||||
#define FSFW_EXAMPLE_REVISION 0
|
||||
#define FSFW_EXAMPLE_VERSION 1
|
||||
#define FSFW_EXAMPLE_SUBVERSION 4
|
||||
#define FSFW_EXAMPLE_REVISION 0
|
||||
|
||||
#endif /* COMMON_OBSWVERSION_H_ */
|
||||
|
@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* Enumerations for used PUS service IDs.
|
||||
*/
|
||||
namespace pus {
|
||||
enum ServiceIds : uint8_t {
|
||||
PUS_SERVICE_1 = 1,
|
||||
PUS_SERVICE_2 = 2,
|
||||
PUS_SERVICE_3 = 3,
|
||||
PUS_SERVICE_5 = 5,
|
||||
PUS_SERVICE_8 = 8,
|
||||
PUS_SERVICE_9 = 9,
|
||||
PUS_SERVICE_11 = 11,
|
||||
PUS_SERVICE_17 = 17,
|
||||
PUS_SERVICE_20 = 20,
|
||||
PUS_SERVICE_200 = 200
|
||||
};
|
||||
}
|
||||
|
||||
namespace common {
|
||||
|
||||
/**
|
||||
* The APID is a 14 bit identifier which can be used to distinguish processes and applications
|
||||
* on a spacecraft. For more details, see the related ECSS/CCSDS standards.
|
||||
* For this example, we are going to use a constant APID
|
||||
*/
|
||||
static constexpr uint16_t COMMON_PUS_APID = 0xEF;
|
||||
static constexpr uint16_t COMMON_CFDP_APID = 0xF0;
|
||||
static constexpr uint16_t COMMON_CFDP_CLIENT_ENTITY_ID = 0x01;
|
||||
|
||||
} // namespace common
|
@ -4,10 +4,10 @@
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
|
||||
namespace CLASS_ID {
|
||||
enum commonClassIds : uint8_t {
|
||||
COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT,
|
||||
DUMMY_HANDLER, // DDH
|
||||
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
||||
enum commonClassIds: uint8_t {
|
||||
COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT,
|
||||
DUMMY_HANDLER, //DDH
|
||||
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,11 @@
|
||||
#ifndef COMMON_COMMONCONFIG_H_
|
||||
#define COMMON_COMMONCONFIG_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#cmakedefine01 FSFW_ADD_FMT_TESTS
|
||||
#include <stdint.h>
|
||||
|
||||
//! Specify the debug output verbose level
|
||||
#define OBSW_VERBOSE_LEVEL 1
|
||||
#define OBSW_TCPIP_UDP_WIRETAPPING 0
|
||||
|
||||
#define OBSW_PRINT_MISSED_DEADLINES 0
|
||||
|
||||
//! Perform internal unit testd at application startup
|
||||
@ -18,7 +16,6 @@
|
||||
|
||||
//! Add core components for the FSFW and for TMTC communication
|
||||
#define OBSW_ADD_CORE_COMPONENTS 1
|
||||
#define OBSW_ADD_CFDP_COMPONENTS 1
|
||||
|
||||
//! Add the PUS service stack
|
||||
#define OBSW_ADD_PUS_STACK 1
|
||||
@ -36,8 +33,35 @@
|
||||
#define OBSW_ADD_CONTROLLER_DEMO 1
|
||||
#define OBSW_CONTROLLER_PRINTOUT 1
|
||||
|
||||
/**
|
||||
* The APID is a 14 bit identifier which can be used to distinguish processes and applications
|
||||
* on a spacecraft. For more details, see the related ECSS/CCSDS standards.
|
||||
* For this example, we are going to use a constant APID
|
||||
*/
|
||||
static const uint16_t COMMON_APID = 0xEF;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <fsfw/events/fwSubsystemIdRanges.h>
|
||||
#include <fsfw/returnvalues/FwClassIds.h>
|
||||
|
||||
/**
|
||||
* Enumerations for used PUS service IDs.
|
||||
*/
|
||||
namespace pus {
|
||||
enum ServiceIds: uint8_t {
|
||||
PUS_SERVICE_1 = 1,
|
||||
PUS_SERVICE_2 = 2,
|
||||
PUS_SERVICE_3 = 3,
|
||||
PUS_SERVICE_5 = 5,
|
||||
PUS_SERVICE_8 = 8,
|
||||
PUS_SERVICE_9 = 9,
|
||||
PUS_SERVICE_17 = 17,
|
||||
PUS_SERVICE_20 = 20,
|
||||
PUS_SERVICE_200 = 200
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* COMMON_COMMONCONFIG_H_ */
|
||||
|
@ -1,43 +0,0 @@
|
||||
#ifndef COMMON_COMMONSYSTEMOBJECTS_H_
|
||||
#define COMMON_COMMONSYSTEMOBJECTS_H_
|
||||
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace objects {
|
||||
enum commonObjects : object_id_t {
|
||||
|
||||
/* 0x41 ('A') for Assemblies */
|
||||
TEST_ASSEMBLY = 0x4100CAFE,
|
||||
|
||||
/* 0x43 ('C') for Controllers */
|
||||
TEST_CONTROLLER = 0x4301CAFE,
|
||||
|
||||
/* 0x44 ('D') for Device Handlers */
|
||||
TEST_DEVICE_HANDLER_0 = 0x4401AFFE,
|
||||
TEST_DEVICE_HANDLER_1 = 0x4402AFFE,
|
||||
|
||||
/* 0x49 ('I') for Communication Interfaces */
|
||||
TEST_ECHO_COM_IF = 0x4900AFFE,
|
||||
|
||||
/* 0x63 ('C') for core objects */
|
||||
CCSDS_DISTRIBUTOR = 0x63000000,
|
||||
PUS_DISTRIBUTOR = 0x63000001,
|
||||
TM_FUNNEL = 0x63000002,
|
||||
CFDP_DISTRIBUTOR = 0x63000003,
|
||||
CFDP_HANDLER = 0x63000004,
|
||||
PUS_TM_FUNNEL = 0x63000005,
|
||||
CFDP_TM_FUNNEL = 0x64000006,
|
||||
|
||||
/* 0x74 ('t') for test and example objects */
|
||||
TEST_TASK = 0x7400CAFE,
|
||||
TEST_DUMMY_1 = 0x74000001,
|
||||
TEST_DUMMY_2 = 0x74000002,
|
||||
TEST_DUMMY_3 = 0x74000003,
|
||||
TEST_DUMMY_4 = 0x74000004,
|
||||
TEST_DUMMY_5 = 0x74000005,
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* COMMON_COMMONSYSTEMOBJECTS_H_ */
|
@ -1,66 +1,83 @@
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||
#include "pollingsequence/pollingSequenceFactory.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
|
||||
#include "example/test/FsfwExampleTask.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
#include "pollingsequence/pollingSequenceFactory.h"
|
||||
|
||||
ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0, FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF* thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.5, FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0,
|
||||
FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0,
|
||||
FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0,
|
||||
FsfwExampleTask::OpCodes::SEND_RAND_NUM);
|
||||
|
||||
if (thisSequence->checkSequence() == returnvalue::OK) {
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.2,
|
||||
FsfwExampleTask::OpCodes::RECEIVE_RAND_NUM);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_1, length * 0.5,
|
||||
FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_2, length * 0.5,
|
||||
FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
thisSequence->addSlot(objects::TEST_DUMMY_3, length * 0.5,
|
||||
FsfwExampleTask::OpCodes::DELAY_SHORT);
|
||||
|
||||
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl;
|
||||
sif::error << "pst::pollingSequenceInitFunction: Initialization errors!" << std::endl;
|
||||
#else
|
||||
sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n");
|
||||
sif::printError("pst::pollingSequenceInitFunction: Initialization errors!\n");
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.3 * length, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.3 * length, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.3, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.3, DeviceHandlerIF::SEND_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.45 * length, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.45 * length, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.45 * length,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.45 * length,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.6 * length, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.6 * length, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.6 * length, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.6 * length, DeviceHandlerIF::SEND_READ);
|
||||
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_0, 0.8 * length, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::TEST_DEVICE_HANDLER_1, 0.8 * length, DeviceHandlerIF::GET_READ);
|
||||
|
||||
if (thisSequence->checkSequence() == returnvalue::OK) {
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl;
|
||||
sif::error << "pst::pollingSequenceTestFunction: Initialization errors!" << std::endl;
|
||||
#else
|
||||
sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n");
|
||||
sif::printError("pst::pollingSequenceTestFunction: Initialization errors!\n");
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -7,11 +7,12 @@
|
||||
* The subsystem IDs will be part of the event IDs used throughout the FSFW.
|
||||
*/
|
||||
namespace SUBSYSTEM_ID {
|
||||
enum commonSubsystemId : uint8_t {
|
||||
COMMON_SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
|
||||
TEST_TASK_ID = 105,
|
||||
COMMON_SUBSYSTEM_ID_END
|
||||
enum commonSubsystemId: uint8_t {
|
||||
COMMON_SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
|
||||
TEST_TASK_ID = 105,
|
||||
COMMON_SUBSYSTEM_ID_END
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif /* COMMON_CONFIG_COMMONSUBSYSTEMIDS_H_ */
|
||||
|
40
config/commonSystemObjects.h
Normal file
40
config/commonSystemObjects.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef COMMON_COMMONSYSTEMOBJECTS_H_
|
||||
#define COMMON_COMMONSYSTEMOBJECTS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
namespace objects {
|
||||
enum commonObjects: object_id_t {
|
||||
|
||||
/* 0x41 ('A') for Assemblies */
|
||||
TEST_ASSEMBLY = 0x4100CAFE,
|
||||
|
||||
/* 0x43 ('C') for Controllers */
|
||||
TEST_CONTROLLER = 0x4301CAFE,
|
||||
|
||||
/* 0x44 ('D') for Device Handlers */
|
||||
TEST_DEVICE_HANDLER_0 = 0x4401AFFE,
|
||||
TEST_DEVICE_HANDLER_1 = 0x4402AFFE,
|
||||
|
||||
/* 0x49 ('I') for Communication Interfaces */
|
||||
TEST_ECHO_COM_IF = 0x4900AFFE,
|
||||
|
||||
/* 0x63 ('C') for core objects */
|
||||
CCSDS_DISTRIBUTOR = 0x63000000,
|
||||
PUS_DISTRIBUTOR = 0x63000001,
|
||||
TM_FUNNEL = 0x63000002,
|
||||
|
||||
/* 0x74 ('t') for test and example objects */
|
||||
TEST_TASK = 0x7400CAFE,
|
||||
TEST_DUMMY_1 = 0x74000001,
|
||||
TEST_DUMMY_2 = 0x74000002,
|
||||
TEST_DUMMY_3= 0x74000003,
|
||||
TEST_DUMMY_4 = 0x74000004,
|
||||
TEST_DUMMY_5 = 0x74000005,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* COMMON_COMMONSYSTEMOBJECTS_H_ */
|
@ -3,4 +3,3 @@ add_subdirectory(core)
|
||||
add_subdirectory(devices)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(utility)
|
||||
add_subdirectory(cfdp)
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,59 +0,0 @@
|
||||
#ifndef FSFW_EXAMPLE_HOSTED_CONFIG_H
|
||||
#define FSFW_EXAMPLE_HOSTED_CONFIG_H
|
||||
|
||||
#include "fsfw/cfdp.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
extern PacketInfoListBase* PACKET_LIST_PTR;
|
||||
extern LostSegmentsListBase* LOST_SEGMENTS_PTR;
|
||||
|
||||
class ExampleUserHandler : public UserBase {
|
||||
public:
|
||||
explicit ExampleUserHandler(HasFileSystemIF& vfs) : cfdp::UserBase(vfs) {}
|
||||
|
||||
void transactionIndication(const cfdp::TransactionId& id) override {}
|
||||
void eofSentIndication(const cfdp::TransactionId& id) override {}
|
||||
void transactionFinishedIndication(const cfdp::TransactionFinishedParams& params) override {
|
||||
sif::info << "File transaction finished for transaction with " << params.id << std::endl;
|
||||
}
|
||||
void metadataRecvdIndication(const cfdp::MetadataRecvdParams& params) override {
|
||||
sif::info << "Metadata received for transaction with " << params.id << std::endl;
|
||||
}
|
||||
void fileSegmentRecvdIndication(const cfdp::FileSegmentRecvdParams& params) override {}
|
||||
void reportIndication(const cfdp::TransactionId& id, cfdp::StatusReportIF& report) override {}
|
||||
void suspendedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code) override {}
|
||||
void resumedIndication(const cfdp::TransactionId& id, size_t progress) override {}
|
||||
void faultIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
|
||||
size_t progress) override {}
|
||||
void abandonedIndication(const cfdp::TransactionId& id, cfdp::ConditionCode code,
|
||||
size_t progress) override {}
|
||||
void eofRecvIndication(const cfdp::TransactionId& id) override {
|
||||
sif::info << "EOF PDU received for transaction with " << id << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class ExampleFaultHandler : public cfdp::FaultHandlerBase {
|
||||
public:
|
||||
void noticeOfSuspensionCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
|
||||
sif::warning << "Notice of suspension detected for transaction " << id
|
||||
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
|
||||
}
|
||||
void noticeOfCancellationCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
|
||||
sif::warning << "Notice of suspension detected for transaction " << id
|
||||
<< " with condition code: " << cfdp::getConditionCodeString(code) << std::endl;
|
||||
}
|
||||
void abandonCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
|
||||
sif::warning << "Transaction " << id
|
||||
<< " was abandoned, condition code : " << cfdp::getConditionCodeString(code)
|
||||
<< std::endl;
|
||||
}
|
||||
void ignoreCb(cfdp::TransactionId& id, cfdp::ConditionCode code) override {
|
||||
sif::warning << "Fault ignored for transaction " << id
|
||||
<< ", condition code: " << cfdp::getConditionCodeString(code) << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_EXAMPLE_HOSTED_CONFIG_H
|
@ -1 +0,0 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE FsfwTestController.cpp)
|
@ -1,221 +0,0 @@
|
||||
#include "FsfwTestController.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
|
||||
FsfwTestController::FsfwTestController(object_id_t objectId, object_id_t device0,
|
||||
object_id_t device1, uint8_t verboseLevel)
|
||||
: TestController(objectId, objects::NO_OBJECT, 5),
|
||||
device0Id(device0),
|
||||
device1Id(device1),
|
||||
deviceDataset0(device0),
|
||||
deviceDataset1(device1) {}
|
||||
|
||||
FsfwTestController::~FsfwTestController() = default;
|
||||
|
||||
ReturnValue_t FsfwTestController::handleCommandMessage(CommandMessage *message) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwTestController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void FsfwTestController::performControlOperation() {
|
||||
// We will trace variables if we received an update notification or snapshots
|
||||
if (verboseLevel >= 1) {
|
||||
if (not traceVariable) {
|
||||
return;
|
||||
}
|
||||
switch (currentTraceType) {
|
||||
case (NONE): {
|
||||
break;
|
||||
}
|
||||
case (TRACE_DEV_0_UINT8): {
|
||||
if (traceCounter == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Tracing finished" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Tracing finished\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
traceVariable = false;
|
||||
traceCounter = traceCycles;
|
||||
currentTraceType = TraceTypes::NONE;
|
||||
break;
|
||||
}
|
||||
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Tracing device 0 variable 0 (UINT8), current value: "
|
||||
<< static_cast<int>(deviceDataset0.testUint8Var.value) << std::endl;
|
||||
#else
|
||||
sif::printInfo("Tracing device 0 variable 0 (UINT8), current value: %d\n",
|
||||
deviceDataset0.testUint8Var.value);
|
||||
#endif
|
||||
traceCounter--;
|
||||
break;
|
||||
}
|
||||
case (TRACE_DEV_0_VECTOR): {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
|
||||
namespace td = testdevice;
|
||||
ReturnValue_t result = TestController::initializeAfterTaskCreation();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
auto *device0 =
|
||||
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
|
||||
if (device0 == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 0 "
|
||||
"handle invalid!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"TestController::initializeAfterTaskCreation: Test device handler 0 "
|
||||
"handle invalid!");
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
ProvidesDataPoolSubscriptionIF *subscriptionIF = device0->getSubscriptionInterface();
|
||||
if (subscriptionIF != nullptr) {
|
||||
/* For DEVICE_0, we only subscribe for notifications */
|
||||
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(),
|
||||
false);
|
||||
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID, getObjectId(),
|
||||
getCommandQueue(), false);
|
||||
}
|
||||
|
||||
auto *device1 =
|
||||
ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
|
||||
if (device1 == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TestController::initializeAfterTaskCreation: Test device handler 1 "
|
||||
"handle invalid!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"TestController::initializeAfterTaskCreation: Test device handler 1 "
|
||||
"handle invalid!");
|
||||
#endif
|
||||
}
|
||||
|
||||
subscriptionIF = device1->getSubscriptionInterface();
|
||||
if (subscriptionIF != nullptr) {
|
||||
/* For DEVICE_1, we will subscribe for snapshots */
|
||||
subscriptionIF->subscribeForSetUpdateMessage(td::TEST_SET_ID, getObjectId(), getCommandQueue(),
|
||||
true);
|
||||
subscriptionIF->subscribeForVariableUpdateMessage(td::PoolIds::TEST_UINT8_ID, getObjectId(),
|
||||
getCommandQueue(), true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *FsfwTestController::getDataSetHandle(sid_t sid) { return nullptr; }
|
||||
|
||||
ReturnValue_t FsfwTestController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void FsfwTestController::handleChangedDataset(sid_t sid, store_address_t storeId,
|
||||
bool *clearMessage) {
|
||||
using namespace std;
|
||||
|
||||
if (verboseLevel >= 1) {
|
||||
char const *printout = nullptr;
|
||||
if (storeId == store_address_t::invalid()) {
|
||||
printout = "Notification";
|
||||
} else {
|
||||
printout = "Snapshot";
|
||||
}
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "FsfwTestController::handleChangedDataset: " << printout
|
||||
<< " update"
|
||||
"from object ID "
|
||||
<< setw(8) << setfill('0') << hex << sid.objectId << " and set ID " << sid.ownerSetId
|
||||
<< dec << setfill(' ') << endl;
|
||||
#else
|
||||
sif::printInfo(
|
||||
"FsfwTestController::handleChangedPoolVariable: %s update from"
|
||||
"object ID 0x%08x and set ID %lu\n",
|
||||
printout, sid.objectId, sid.ownerSetId);
|
||||
#endif
|
||||
|
||||
if (storeId == store_address_t::invalid()) {
|
||||
if (sid.objectId == device0Id) {
|
||||
PoolReadGuard readHelper(&deviceDataset0.testFloat3Vec);
|
||||
float floatVec[3];
|
||||
floatVec[0] = deviceDataset0.testFloat3Vec.value[0];
|
||||
floatVec[1] = deviceDataset0.testFloat3Vec.value[1];
|
||||
floatVec[2] = deviceDataset0.testFloat3Vec.value[2];
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Current float vector (3) values: [" << floatVec[0] << ", " << floatVec[1]
|
||||
<< ", " << floatVec[2] << "]" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Current float vector (3) values: [%f, %f, %f]\n", floatVec[0], floatVec[1],
|
||||
floatVec[2]);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We will trace the variables for snapshots and update notifications */
|
||||
if (not traceVariable) {
|
||||
traceVariable = true;
|
||||
traceCounter = traceCycles;
|
||||
currentTraceType = TraceTypes::TRACE_DEV_0_VECTOR;
|
||||
}
|
||||
}
|
||||
|
||||
void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
|
||||
bool *clearMessage) {
|
||||
using namespace std;
|
||||
|
||||
if (verboseLevel >= 1) {
|
||||
char const *printout = nullptr;
|
||||
if (storeId == store_address_t::invalid()) {
|
||||
printout = "Notification";
|
||||
} else {
|
||||
printout = "Snapshot";
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "TestController::handleChangedPoolVariable: " << printout
|
||||
<< " update from object "
|
||||
"ID 0x"
|
||||
<< setw(8) << setfill('0') << hex << globPoolId.objectId << " and local pool ID "
|
||||
<< globPoolId.localPoolId << dec << setfill(' ') << endl;
|
||||
#else
|
||||
sif::printInfo(
|
||||
"TestController::handleChangedPoolVariable: %s update from "
|
||||
"object ID 0x%08x and "
|
||||
"local pool ID %lu\n",
|
||||
printout, globPoolId.objectId, globPoolId.localPoolId);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
|
||||
if (storeId == store_address_t::invalid()) {
|
||||
if (globPoolId.objectId == device0Id) {
|
||||
PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Current test variable 0 (UINT8) value: "
|
||||
<< static_cast<int>(deviceDataset0.testUint8Var.value) << std::endl;
|
||||
#else
|
||||
sif::printInfo("Current test variable 0 (UINT8) value %d\n",
|
||||
deviceDataset0.testUint8Var.value);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We will trace the variables for snapshots and update notifications */
|
||||
if (not traceVariable) {
|
||||
traceVariable = true;
|
||||
traceCounter = traceCycles;
|
||||
currentTraceType = TraceTypes::TRACE_DEV_0_UINT8;
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#ifndef EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_
|
||||
#define EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_
|
||||
|
||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||
#include "fsfw_tests/integration/controller/TestController.h"
|
||||
|
||||
class FsfwTestController : public TestController {
|
||||
public:
|
||||
FsfwTestController(object_id_t objectId, object_id_t device0, object_id_t device1,
|
||||
uint8_t verboseLevel = 0);
|
||||
virtual ~FsfwTestController();
|
||||
ReturnValue_t handleCommandMessage(CommandMessage *message) override;
|
||||
|
||||
/**
|
||||
* Periodic helper from ControllerBase, implemented by child class.
|
||||
*/
|
||||
void performControlOperation() override;
|
||||
|
||||
private:
|
||||
object_id_t device0Id;
|
||||
object_id_t device1Id;
|
||||
testdevice::TestDataSet deviceDataset0;
|
||||
testdevice::TestDataSet deviceDataset1;
|
||||
|
||||
uint8_t verboseLevel = 0;
|
||||
bool traceVariable = false;
|
||||
uint8_t traceCycles = 5;
|
||||
uint8_t traceCounter = traceCycles;
|
||||
|
||||
enum TraceTypes { NONE, TRACE_DEV_0_UINT8, TRACE_DEV_0_VECTOR };
|
||||
TraceTypes currentTraceType = TraceTypes::NONE;
|
||||
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
void handleChangedDataset(sid_t sid, store_address_t storeId, bool *clearMessage) override;
|
||||
void handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
|
||||
bool *clearMessage) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override;
|
||||
};
|
||||
|
||||
#endif /* EXAMPLE_COMMON_EXAMPLE_CONTROLLER_FSFWTESTCONTROLLER_H_ */
|
@ -1 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE GenericFactory.cpp)
|
||||
target_sources(${TARGET_NAME}
|
||||
PRIVATE
|
||||
GenericFactory.cpp
|
||||
)
|
||||
|
@ -1,22 +1,27 @@
|
||||
#include "GenericFactory.h"
|
||||
|
||||
#include "common/definitions.h"
|
||||
#include "definitions.h"
|
||||
#include "example/cfdp/Config.h"
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "tmtc/apid.h"
|
||||
#include "tmtc/pusIds.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
|
||||
#include "example/utility/TmFunnel.h"
|
||||
#include "example/test/FsfwExampleTask.h"
|
||||
#include "example/test/FsfwReaderTask.h"
|
||||
#include "example/utility/CfdpTmFunnel.h"
|
||||
#include "example/utility/TmFunnel.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/cfdp.h"
|
||||
#include "fsfw/cfdp/CfdpDistributor.h"
|
||||
|
||||
#include "fsfw_tests/internal/InternalUnitTester.h"
|
||||
#include "fsfw_tests/integration/assemblies/TestAssembly.h"
|
||||
#include "fsfw_tests/integration/devices/TestCookie.h"
|
||||
#include "fsfw_tests/integration/devices/TestDeviceHandler.h"
|
||||
#include "fsfw_tests/integration/devices/TestEchoComIF.h"
|
||||
#include "fsfw_tests/integration/controller/TestController.h"
|
||||
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/events/EventManager.h"
|
||||
#include "fsfw/health/HealthTable.h"
|
||||
#include "fsfw/internalerror/InternalErrorReporter.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/pus/CService200ModeCommanding.h"
|
||||
#include "fsfw/pus/Service11TelecommandScheduling.h"
|
||||
#include "fsfw/pus/Service17Test.h"
|
||||
#include "fsfw/pus/Service1TelecommandVerification.h"
|
||||
#include "fsfw/pus/Service20ParameterManagement.h"
|
||||
@ -25,178 +30,130 @@
|
||||
#include "fsfw/pus/Service5EventReporting.h"
|
||||
#include "fsfw/pus/Service8FunctionManagement.h"
|
||||
#include "fsfw/pus/Service9TimeManagement.h"
|
||||
#include "fsfw/tcdistribution/CcsdsDistributor.h"
|
||||
#include "fsfw/tcdistribution/PusDistributor.h"
|
||||
#include "fsfw/timemanager/CdsShortTimeStamper.h"
|
||||
#include "fsfw/tmtcservices/VerificationReporter.h"
|
||||
#include "fsfw_hal/host/HostFilesystem.h"
|
||||
#include "fsfw_tests/integration/assemblies/TestAssembly.h"
|
||||
#include "fsfw_tests/integration/controller/TestController.h"
|
||||
#include "fsfw_tests/integration/devices/TestCookie.h"
|
||||
#include "fsfw_tests/integration/devices/TestDeviceHandler.h"
|
||||
#include "fsfw_tests/integration/devices/TestEchoComIF.h"
|
||||
#include "fsfw_tests/internal/InternalUnitTester.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
#include "fsfw/tcdistribution/CCSDSDistributor.h"
|
||||
#include "fsfw/tcdistribution/PUSDistributor.h"
|
||||
#include "fsfw/timemanager/TimeStamper.h"
|
||||
#include "fsfw/tmtcpacket/pus/tm.h"
|
||||
|
||||
#if OBSW_ADD_CFDP_COMPONENTS == 1
|
||||
namespace cfdp {
|
||||
EntityId REMOTE_CFDP_ID(cfdp::WidthInBytes::TWO_BYTES, common::COMMON_CFDP_CLIENT_ENTITY_ID);
|
||||
RemoteEntityCfg GROUND_REMOTE_CFG(REMOTE_CFDP_ID);
|
||||
OneRemoteConfigProvider REMOTE_CFG_PROVIDER(GROUND_REMOTE_CFG);
|
||||
HostFilesystem HOST_FS;
|
||||
ExampleUserHandler USER_HANDLER(HOST_FS);
|
||||
ExampleFaultHandler EXAMPLE_FAULT_HANDLER;
|
||||
} // namespace cfdp
|
||||
#endif
|
||||
|
||||
void ObjectFactory::produceGenericObjects(PusTmFunnel **pusFunnel,
|
||||
const AcceptsTelemetryIF &tmtcBridge,
|
||||
CcsdsDistributor **ccsdsDistrib,
|
||||
StorageManagerIF &tcStore, StorageManagerIF &tmStore) {
|
||||
|
||||
void ObjectFactory::produceGenericObjects() {
|
||||
#if OBSW_ADD_CORE_COMPONENTS == 1
|
||||
/* Framework objects */
|
||||
new EventManager(objects::EVENT_MANAGER);
|
||||
new HealthTable(objects::HEALTH_TABLE);
|
||||
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
||||
auto *stamperAndReader = new CdsShortTimeStamper(objects::TIME_STAMPER);
|
||||
new VerificationReporter();
|
||||
*ccsdsDistrib =
|
||||
new CcsdsDistributor(common::COMMON_PUS_APID, objects::CCSDS_DISTRIBUTOR, &tcStore);
|
||||
new PusDistributor(common::COMMON_PUS_APID, objects::PUS_DISTRIBUTOR, *ccsdsDistrib);
|
||||
*pusFunnel = new PusTmFunnel(objects::PUS_TM_FUNNEL, tmtcBridge, *stamperAndReader, tmStore);
|
||||
auto *cfdpFunnel =
|
||||
new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, common::COMMON_CFDP_APID, tmtcBridge, tmStore);
|
||||
new TmFunnel(objects::TM_FUNNEL, **pusFunnel, *cfdpFunnel);
|
||||
/* Framework objects */
|
||||
new EventManager(objects::EVENT_MANAGER);
|
||||
new HealthTable(objects::HEALTH_TABLE);
|
||||
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
||||
new TimeStamper(objects::TIME_STAMPER);
|
||||
new CCSDSDistributor(apid::APID, objects::CCSDS_DISTRIBUTOR);
|
||||
new PUSDistributor(apid::APID, objects::PUS_DISTRIBUTOR,
|
||||
objects::CCSDS_DISTRIBUTOR);
|
||||
new TmFunnel(objects::TM_FUNNEL);
|
||||
#endif /* OBSW_ADD_CORE_COMPONENTS == 1 */
|
||||
|
||||
/* PUS stack */
|
||||
/* PUS stack */
|
||||
#if OBSW_ADD_PUS_STACK == 1
|
||||
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_1, objects::PUS_TM_FUNNEL, 5);
|
||||
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_2, 3, 10);
|
||||
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_3);
|
||||
new Service5EventReporting(PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING,
|
||||
common::COMMON_PUS_APID, pus::PUS_SERVICE_5),
|
||||
20, 40);
|
||||
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_8, 3, 10);
|
||||
new Service9TimeManagement(
|
||||
PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, common::COMMON_PUS_APID, pus::PUS_SERVICE_9));
|
||||
new Service17Test(
|
||||
PsbParams(objects::PUS_SERVICE_17_TEST, common::COMMON_PUS_APID, pus::PUS_SERVICE_17));
|
||||
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_20);
|
||||
#if OBSW_ADD_CORE_COMPONENTS == 1
|
||||
new Service11TelecommandScheduling<cfg::OBSW_MAX_SCHEDULED_TCS>(
|
||||
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, common::COMMON_PUS_APID, pus::PUS_SERVICE_11),
|
||||
*ccsdsDistrib);
|
||||
#endif
|
||||
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, common::COMMON_PUS_APID,
|
||||
pus::PUS_SERVICE_200);
|
||||
new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION,
|
||||
apid::APID, pus::PUS_SERVICE_1, objects::TM_FUNNEL, 5);
|
||||
new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS,
|
||||
apid::APID, pus::PUS_SERVICE_2, 3, 10);
|
||||
new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, apid::APID, pus::PUS_SERVICE_3);
|
||||
new Service5EventReporting(objects::PUS_SERVICE_5_EVENT_REPORTING,
|
||||
apid::APID, pus::PUS_SERVICE_5, 50);
|
||||
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT,
|
||||
apid::APID, pus::PUS_SERVICE_8, 3, 10);
|
||||
new Service9TimeManagement(objects::PUS_SERVICE_9_TIME_MGMT, apid::APID,
|
||||
pus::PUS_SERVICE_9);
|
||||
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::APID,
|
||||
pus::PUS_SERVICE_17);
|
||||
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::APID,
|
||||
pus::PUS_SERVICE_20);
|
||||
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT,
|
||||
apid::APID, pus::PUS_SERVICE_200);
|
||||
#endif /* OBSW_ADD_PUS_STACK == 1 */
|
||||
|
||||
#if OBSW_ADD_TASK_EXAMPLE == 1
|
||||
/* Demo objects */
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_1);
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_2);
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_3);
|
||||
/* Demo objects */
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_1);
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_2);
|
||||
new FsfwExampleTask(objects::TEST_DUMMY_3);
|
||||
|
||||
bool enablePrintout = false;
|
||||
|
||||
bool enablePrintout = false;
|
||||
#if OBSW_TASK_EXAMPLE_PRINTOUT == 1
|
||||
enablePrintout = true;
|
||||
enablePrintout = true;
|
||||
#endif
|
||||
new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout);
|
||||
new FsfwReaderTask(objects::TEST_DUMMY_4, enablePrintout);
|
||||
#endif /* OBSW_ADD_TASK_EXAMPLE == 1 */
|
||||
|
||||
#if OBSW_ADD_DEVICE_HANDLER_DEMO == 1
|
||||
|
||||
#if OBSW_DEVICE_HANDLER_PRINTOUT == 1
|
||||
bool enableInfoPrintout = true;
|
||||
bool enableInfoPrintout = true;
|
||||
#else
|
||||
bool enableInfoPrintout = false;
|
||||
bool enableInfoPrintout = false;
|
||||
#endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */
|
||||
|
||||
/* Demo device handler object */
|
||||
size_t expectedMaxReplyLen = 64;
|
||||
CookieIF *testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0),
|
||||
expectedMaxReplyLen);
|
||||
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
|
||||
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
|
||||
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
|
||||
testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1),
|
||||
expectedMaxReplyLen);
|
||||
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
|
||||
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);
|
||||
/* Demo device handler object */
|
||||
size_t expectedMaxReplyLen = 64;
|
||||
CookieIF* testCookie = new TestCookie(
|
||||
static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0), expectedMaxReplyLen);
|
||||
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
|
||||
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
|
||||
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
|
||||
testCookie = new TestCookie(static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1),
|
||||
expectedMaxReplyLen);
|
||||
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
|
||||
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);
|
||||
|
||||
new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0,
|
||||
objects::TEST_DEVICE_HANDLER_1);
|
||||
new TestAssembly(objects::TEST_ASSEMBLY, objects::NO_OBJECT, objects::TEST_DEVICE_HANDLER_0,
|
||||
objects::TEST_DEVICE_HANDLER_1);
|
||||
|
||||
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
|
||||
|
||||
/* Demo controller object */
|
||||
|
||||
/* Demo controller object */
|
||||
#if OBSW_ADD_CONTROLLER_DEMO == 1
|
||||
|
||||
#if OBSW_CONTROLLER_PRINTOUT == 1
|
||||
#endif
|
||||
new TestController(objects::TEST_CONTROLLER, objects::NO_OBJECT);
|
||||
new TestController(objects::TEST_CONTROLLER);
|
||||
|
||||
#endif /* OBSW_ADD_CONTROLLER_DEMO == 1 */
|
||||
|
||||
#if OBSW_PERFORM_INTERNAL_UNITTEST == 1
|
||||
InternalUnitTester::TestConfig testCfg;
|
||||
testCfg.testArrayPrinter = false;
|
||||
InternalUnitTester::TestConfig testCfg;
|
||||
testCfg.testArrayPrinter = false;
|
||||
#if defined FSFW_OSAL_HOST
|
||||
// Not implemented yet for hosted OSAL (requires C++20)
|
||||
testCfg.testSemaphores = false;
|
||||
// Not implemented yet for hosted OSAL (requires C++20)
|
||||
testCfg.testSemaphores = false;
|
||||
#endif
|
||||
InternalUnitTester unittester;
|
||||
unittester.performTests(testCfg);
|
||||
InternalUnitTester unittester;
|
||||
unittester.performTests(testCfg);
|
||||
#endif /* OBSW_PERFORM_INTERNAL_UNITTEST == 1 */
|
||||
|
||||
#if OBSW_ADD_CFDP_COMPONENTS == 1
|
||||
using namespace cfdp;
|
||||
MessageQueueIF *cfdpMsgQueue = QueueFactory::instance()->createMessageQueue(32);
|
||||
CfdpDistribCfg cfg(objects::CFDP_DISTRIBUTOR, tcStore, cfdpMsgQueue);
|
||||
new CfdpDistributor(cfg);
|
||||
|
||||
auto *msgQueue = QueueFactory::instance()->createMessageQueue(32);
|
||||
UnsignedByteField<uint16_t> remoteEntityId(common::COMMON_CFDP_CLIENT_ENTITY_ID);
|
||||
cfdp::EntityId remoteId(remoteEntityId);
|
||||
cfdp::RemoteEntityCfg remoteCfg(remoteId);
|
||||
remoteCfg.defaultChecksum = cfdp::ChecksumType::CRC_32;
|
||||
FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, *cfdpFunnel, tcStore, tmStore,
|
||||
*msgQueue);
|
||||
cfdp::IndicationCfg indicationCfg;
|
||||
UnsignedByteField<uint16_t> apid(common::COMMON_CFDP_APID);
|
||||
cfdp::EntityId localId(apid);
|
||||
GROUND_REMOTE_CFG.defaultChecksum = cfdp::ChecksumType::CRC_32;
|
||||
if (PACKET_LIST_PTR == nullptr or LOST_SEGMENTS_PTR == nullptr) {
|
||||
sif::error << "CFDP: No packet list or lost segments container set" << std::endl;
|
||||
}
|
||||
CfdpHandlerCfg cfdpCfg(localId, indicationCfg, USER_HANDLER, EXAMPLE_FAULT_HANDLER,
|
||||
*PACKET_LIST_PTR, *LOST_SEGMENTS_PTR, REMOTE_CFG_PROVIDER);
|
||||
auto *cfdpHandler = new CfdpHandler(params, cfdpCfg);
|
||||
CcsdsDistributorIF::DestInfo info("CFDP Destination", common::COMMON_CFDP_APID,
|
||||
cfdpHandler->getRequestQueue(), true);
|
||||
(*ccsdsDistrib)->registerApplication(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Factory::setStaticFrameworkObjectIds() {
|
||||
MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<float>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<double>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<uint32_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<int32_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<int16_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
MonitoringReportContent<uint16_t>::timeStamperId = objects::TIME_STAMPER;
|
||||
|
||||
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_DISTRIBUTOR;
|
||||
PusServiceBase::PACKET_DESTINATION = objects::PUS_TM_FUNNEL;
|
||||
TmFunnel::downlinkDestination = objects::DOWNLINK_DESTINATION;
|
||||
// No storage object for now.
|
||||
TmFunnel::storageDestination = objects::NO_OBJECT;
|
||||
|
||||
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
|
||||
CommandingServiceBase::defaultPacketDestination = objects::PUS_TM_FUNNEL;
|
||||
PusServiceBase::packetSource = objects::PUS_DISTRIBUTOR;
|
||||
PusServiceBase::packetDestination = objects::TM_FUNNEL;
|
||||
|
||||
CommandingServiceBase::defaultPacketSource = objects::PUS_DISTRIBUTOR;
|
||||
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
|
||||
|
||||
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
|
||||
|
||||
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
|
||||
|
||||
VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,24 +3,15 @@
|
||||
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "example/utility/PusTmFunnel.h"
|
||||
#include "fsfw/cfdp/handler/DestHandler.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
|
||||
class TmFunnel;
|
||||
class CcsdsDistributor;
|
||||
|
||||
namespace ObjectFactory {
|
||||
|
||||
/**
|
||||
* @brief Produce hardware independant objects. Called by bsp specific
|
||||
* object factory.
|
||||
*/
|
||||
void produceGenericObjects(PusTmFunnel** pusFunnel, const AcceptsTelemetryIF& tmtcBridge,
|
||||
CcsdsDistributor** ccsdsDistributor, StorageManagerIF& tcStore,
|
||||
StorageManagerIF& tmStore);
|
||||
void produceGenericObjects();
|
||||
|
||||
}
|
||||
|
||||
} // namespace ObjectFactory
|
||||
|
||||
#endif /* MISSION_CORE_GENERICFACTORY_H_ */
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
//#include "fsfw_tests/integration/TestDeviceHandler.h"
|
||||
//
|
||||
// class FsfwTestDeviceHandler: public TestDeviceHandler {
|
||||
//class FsfwTestDeviceHandler: public TestDeviceHandler {
|
||||
//
|
||||
//};
|
||||
|
||||
|
||||
|
||||
#endif /* EXAMPLE_COMMON_DEVICES_TESTDEVICEHANDLER_H_ */
|
||||
|
@ -1,6 +1,5 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE FsfwReaderTask.cpp FsfwExampleTask.cpp
|
||||
MutexExample.cpp FsfwTestTask.cpp)
|
||||
|
||||
if(FSFW_ADD_FMT_TESTS)
|
||||
target_sources(${TARGET_NAME} PRIVATE testFmt.cpp)
|
||||
endif()
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
FsfwReaderTask.cpp
|
||||
FsfwExampleTask.cpp
|
||||
MutexExample.cpp
|
||||
)
|
@ -1,239 +1,264 @@
|
||||
#include "FsfwExampleTask.h"
|
||||
|
||||
#include <fsfw/ipc/CommandMessage.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "commonObjects.h"
|
||||
#include "commonSystemObjects.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
|
||||
FsfwExampleTask::FsfwExampleTask(object_id_t objectId)
|
||||
: SystemObject(objectId),
|
||||
poolManager(this, nullptr),
|
||||
demoSet(this),
|
||||
monitor(objectId, MONITOR_ID, gp_id_t(objectId, FsfwDemoSet::VARIABLE_LIMIT), 30, 10) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(10, CommandMessage::MAX_MESSAGE_SIZE);
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/ipc/CommandMessage.h>
|
||||
|
||||
|
||||
FsfwExampleTask::FsfwExampleTask(object_id_t objectId): SystemObject(objectId),
|
||||
poolManager(this, nullptr), demoSet(this),
|
||||
monitor(objectId, MONITOR_ID, gp_id_t(objectId, FsfwDemoSet::VARIABLE_LIMIT), 30, 10)
|
||||
{
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(10,
|
||||
CommandMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
FsfwExampleTask::~FsfwExampleTask() {}
|
||||
FsfwExampleTask::~FsfwExampleTask() {
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) {
|
||||
if (operationCode == OpCodes::DELAY_SHORT) {
|
||||
TaskFactory::delayTask(5);
|
||||
}
|
||||
|
||||
// TODO: Move this to new test controller?
|
||||
ReturnValue_t result = performMonitoringDemo();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (operationCode == OpCodes::SEND_RAND_NUM) {
|
||||
result = performSendOperation();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
if(operationCode == OpCodes::DELAY_SHORT){
|
||||
TaskFactory::delayTask(5);
|
||||
}
|
||||
}
|
||||
|
||||
if (operationCode == OpCodes::RECEIVE_RAND_NUM) {
|
||||
result = performReceiveOperation();
|
||||
}
|
||||
// TODO: Move this to new test controller?
|
||||
ReturnValue_t result = performMonitoringDemo();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (operationCode == OpCodes::SEND_RAND_NUM) {
|
||||
result = performSendOperation();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (operationCode == OpCodes::RECEIVE_RAND_NUM) {
|
||||
result = performReceiveOperation();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
object_id_t FsfwExampleTask::getNextRecipient() {
|
||||
switch (this->getObjectId()) {
|
||||
case (objects::TEST_DUMMY_1): {
|
||||
return objects::TEST_DUMMY_2;
|
||||
switch(this->getObjectId()) {
|
||||
case(objects::TEST_DUMMY_1): {
|
||||
return objects::TEST_DUMMY_2;
|
||||
}
|
||||
case (objects::TEST_DUMMY_2): {
|
||||
return objects::TEST_DUMMY_3;
|
||||
case(objects::TEST_DUMMY_2): {
|
||||
return objects::TEST_DUMMY_3;
|
||||
}
|
||||
case (objects::TEST_DUMMY_3): {
|
||||
return objects::TEST_DUMMY_1;
|
||||
case(objects::TEST_DUMMY_3): {
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
default:
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
}
|
||||
|
||||
object_id_t FsfwExampleTask::getSender() {
|
||||
switch (this->getObjectId()) {
|
||||
case (objects::TEST_DUMMY_1): {
|
||||
return objects::TEST_DUMMY_3;
|
||||
switch(this->getObjectId()) {
|
||||
case(objects::TEST_DUMMY_1): {
|
||||
return objects::TEST_DUMMY_3;
|
||||
}
|
||||
case (objects::TEST_DUMMY_2): {
|
||||
return objects::TEST_DUMMY_1;
|
||||
case(objects::TEST_DUMMY_2): {
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
case (objects::TEST_DUMMY_3): {
|
||||
return objects::TEST_DUMMY_2;
|
||||
case(objects::TEST_DUMMY_3): {
|
||||
return objects::TEST_DUMMY_2;
|
||||
}
|
||||
default:
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
return objects::TEST_DUMMY_1;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::initialize() {
|
||||
// Get the dataset of the sender. Will be cached for later checks.
|
||||
object_id_t sender = getSender();
|
||||
auto *senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
|
||||
if (senderIF == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
// we need a private copy of the previous dataset.. or we use the shared
|
||||
// dataset.
|
||||
senderSet = new FsfwDemoSet(senderIF);
|
||||
if (senderSet == nullptr) {
|
||||
ReturnValue_t FsfwExampleTask::initialize() {
|
||||
// Get the dataset of the sender. Will be cached for later checks.
|
||||
object_id_t sender = getSender();
|
||||
HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
|
||||
if(senderIF == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl;
|
||||
sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
|
||||
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return poolManager.initialize(commandQueue);
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
// we need a private copy of the previous dataset.. or we use the shared dataset.
|
||||
senderSet = new FsfwDemoSet(senderIF);
|
||||
if(senderSet == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return poolManager.initialize(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::initializeAfterTaskCreation() {
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
}
|
||||
|
||||
object_id_t FsfwExampleTask::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
object_id_t FsfwExampleTask::getObjectId() const {
|
||||
return SystemObject::getObjectId();
|
||||
}
|
||||
|
||||
MessageQueueId_t FsfwExampleTask::getMessageQueueId() { return commandQueue->getId(); }
|
||||
MessageQueueId_t FsfwExampleTask::getMessageQueueId(){
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void FsfwExampleTask::setTaskIF(PeriodicTaskIF *task) { this->task = task; }
|
||||
void FsfwExampleTask::setTaskIF(PeriodicTaskIF* task){
|
||||
this->task = task;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *FsfwExampleTask::getDataSetHandle(sid_t sid) { return &demoSet; }
|
||||
LocalPoolDataSetBase* FsfwExampleTask::getDataSetHandle(sid_t sid) {
|
||||
return &demoSet;
|
||||
}
|
||||
|
||||
uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const { return task->getPeriodMs(); }
|
||||
uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const {
|
||||
return task->getPeriodMs();
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0}));
|
||||
return returnvalue::OK;
|
||||
ReturnValue_t FsfwExampleTask::initializeLocalDataPool(
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry<uint16_t>({0}));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
|
||||
ReturnValue_t result = demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20);
|
||||
if (result != returnvalue::OK) {
|
||||
/* Configuration error */
|
||||
ReturnValue_t result = demoSet.variableLimit.read(
|
||||
MutexIF::TimeoutType::WAITING, 20);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl;
|
||||
sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl;
|
||||
#else
|
||||
sif::printError("DummyObject::performOperation: Could not read variableLimit!\n");
|
||||
sif::printError("DummyObject::performOperation: Could not read variableLimit!\n");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
if (this->getObjectId() == objects::TEST_DUMMY_5) {
|
||||
if (demoSet.variableLimit.value > 20) {
|
||||
demoSet.variableLimit.value = 0;
|
||||
return result;
|
||||
}
|
||||
demoSet.variableLimit.value++;
|
||||
demoSet.variableLimit.commit(20);
|
||||
monitor.check();
|
||||
}
|
||||
return returnvalue::OK;
|
||||
if(this->getObjectId() == objects::TEST_DUMMY_5){
|
||||
if(demoSet.variableLimit.value > 20){
|
||||
demoSet.variableLimit.value = 0;
|
||||
}
|
||||
demoSet.variableLimit.value++;
|
||||
demoSet.variableLimit.commit(20);
|
||||
monitor.check();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::performSendOperation() {
|
||||
object_id_t nextRecipient = getNextRecipient();
|
||||
auto *target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
|
||||
if (target == nullptr) {
|
||||
/* Configuration error */
|
||||
object_id_t nextRecipient = getNextRecipient();
|
||||
FsfwExampleTask* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
|
||||
if (target == nullptr) {
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl;
|
||||
sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl;
|
||||
#else
|
||||
sif::printError("DummyObject::performOperation: Next recipient does not exist!\n");
|
||||
sif::printError("DummyObject::performOperation: Next recipient does not exist!\n");
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t randomNumber = rand() % 100;
|
||||
CommandMessage message;
|
||||
message.setParameter(randomNumber);
|
||||
message.setParameter2(this->getMessageQueueId());
|
||||
|
||||
/* Send message using own message queue */
|
||||
ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
|
||||
if (result != returnvalue::OK && result != MessageQueueIF::FULL) {
|
||||
uint32_t randomNumber = rand() % 100;
|
||||
CommandMessage message;
|
||||
message.setParameter(randomNumber);
|
||||
message.setParameter2(this->getMessageQueueId());
|
||||
|
||||
/* Send message using own message queue */
|
||||
ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK
|
||||
&& result != MessageQueueIF::FULL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
|
||||
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Send message without via MessageQueueSenderIF */
|
||||
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
|
||||
commandQueue->getId());
|
||||
if (result != returnvalue::OK && result != MessageQueueIF::FULL) {
|
||||
/* Send message without via MessageQueueSenderIF */
|
||||
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
|
||||
commandQueue->getId());
|
||||
if (result != HasReturnvaluesIF::RETURN_OK
|
||||
&& result != MessageQueueIF::FULL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
|
||||
sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||
sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
demoSet.variableWrite.value = randomNumber;
|
||||
result = demoSet.variableWrite.commit(20);
|
||||
demoSet.variableWrite.value = randomNumber;
|
||||
result = demoSet.variableWrite.commit(20);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwExampleTask::performReceiveOperation() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
while (result != MessageQueueIF::EMPTY) {
|
||||
CommandMessage receivedMessage;
|
||||
result = commandQueue->receiveMessage(&receivedMessage);
|
||||
if (result != returnvalue::OK && result != MessageQueueIF::EMPTY) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
while (result != MessageQueueIF::EMPTY) {
|
||||
CommandMessage receivedMessage;
|
||||
result = commandQueue->receiveMessage(&receivedMessage);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK
|
||||
&& result != MessageQueueIF::EMPTY) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Receive failed with " << result << std::endl;
|
||||
sif::debug << "Receive failed with " << result << std::endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (result != MessageQueueIF::EMPTY) {
|
||||
break;
|
||||
}
|
||||
if (result != MessageQueueIF::EMPTY) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
#if OBSW_VERBOSE_LEVEL >= 2
|
||||
sif::debug << "Message Received by " << getObjectId() << " from Queue "
|
||||
<< receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter()
|
||||
<< " Queue " << receivedMessage.getParameter2() << std::endl;
|
||||
sif::debug << "Message Received by " << getObjectId() << " from Queue " <<
|
||||
receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter() <<
|
||||
" Queue " << receivedMessage.getParameter2() << std::endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (senderSet == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if(senderSet == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, 20);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (senderSet->variableRead.value != receivedMessage.getParameter()) {
|
||||
result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING,
|
||||
20);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if(senderSet->variableRead.value != receivedMessage.getParameter()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex << "0x"
|
||||
<< senderSet->variableRead.getDataPoolId() << std::dec << " has wrong value."
|
||||
<< std::endl;
|
||||
sif::error << "Value: " << demoSet.variableRead.value
|
||||
<< ", expected: " << receivedMessage.getParameter() << std::endl;
|
||||
sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex <<
|
||||
"0x" << senderSet->variableRead.getDataPoolId() << std::dec <<
|
||||
" has wrong value." << std::endl;
|
||||
sif::error << "Value: " << demoSet.variableRead.value << ", expected: " <<
|
||||
receivedMessage.getParameter() << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t FsfwExampleTask::getCommandQueue() const { return commandQueue->getId(); }
|
||||
MessageQueueId_t FsfwExampleTask::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
LocalDataPoolManager *FsfwExampleTask::getHkManagerHandle() { return &poolManager; }
|
||||
LocalDataPoolManager* FsfwExampleTask::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
#ifndef MISSION_DEMO_FSFWDEMOTASK_H_
|
||||
#define MISSION_DEMO_FSFWDEMOTASK_H_
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/monitoring/AbsLimitMonitor.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
|
||||
#include "testdefinitions/demoDefinitions.h"
|
||||
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/monitoring/AbsLimitMonitor.h>
|
||||
|
||||
class PeriodicTaskIF;
|
||||
|
||||
|
||||
/**
|
||||
* @brief This demo set shows the local data pool functionality and fixed
|
||||
* timeslot capabilities of the FSFW.
|
||||
@ -24,82 +25,92 @@ class PeriodicTaskIF;
|
||||
* value directly from the sender via the local data pool interface.
|
||||
* If the timing is set up correctly, the values will always be the same.
|
||||
*/
|
||||
class FsfwExampleTask : public ExecutableObjectIF, public SystemObject, public HasLocalDataPoolIF {
|
||||
public:
|
||||
enum OpCodes { SEND_RAND_NUM, RECEIVE_RAND_NUM, DELAY_SHORT };
|
||||
class FsfwExampleTask:
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasLocalDataPoolIF {
|
||||
public:
|
||||
enum OpCodes {
|
||||
SEND_RAND_NUM,
|
||||
RECEIVE_RAND_NUM,
|
||||
DELAY_SHORT
|
||||
};
|
||||
|
||||
static constexpr uint8_t MONITOR_ID = 2;
|
||||
static constexpr uint8_t MONITOR_ID = 2;
|
||||
|
||||
/**
|
||||
* @brief Simple constructor, only expects object ID.
|
||||
* @param objectId
|
||||
*/
|
||||
FsfwExampleTask(object_id_t objectId);
|
||||
/**
|
||||
* @brief Simple constructor, only expects object ID.
|
||||
* @param objectId
|
||||
*/
|
||||
FsfwExampleTask(object_id_t objectId);
|
||||
|
||||
virtual ~FsfwExampleTask();
|
||||
virtual ~FsfwExampleTask();
|
||||
|
||||
/**
|
||||
* @brief The performOperation method is executed in a task.
|
||||
* @details There are no restrictions for calls within this method, so any
|
||||
* other member of the class can be used.
|
||||
* @return Currently, the return value is ignored.
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
/**
|
||||
* @brief The performOperation method is executed in a task.
|
||||
* @details There are no restrictions for calls within this method, so any
|
||||
* other member of the class can be used.
|
||||
* @return Currently, the return value is ignored.
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the global object manager
|
||||
* @details
|
||||
* This function will always be called before any tasks are started.
|
||||
* It can also be used to return error codes in the software initialization
|
||||
* process cleanly.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initialize() override;
|
||||
/**
|
||||
* @brief This function will be called by the global object manager
|
||||
* @details
|
||||
* This function will always be called before any tasks are started.
|
||||
* It can also be used to return error codes in the software initialization
|
||||
* process cleanly.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the OSAL task handlers
|
||||
* @details
|
||||
* This function will be called before the first #performOperation
|
||||
* call after the tasks have been started. It can be used if some
|
||||
* initialization process requires task specific properties like
|
||||
* periodic intervals (by using the PeriodicTaskIF* handle).
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
/**
|
||||
* @brief This function will be called by the OSAL task handlers
|
||||
* @details
|
||||
* This function will be called before the first #performOperation
|
||||
* call after the tasks have been started. It can be used if some
|
||||
* initialization process requires task specific properties like
|
||||
* periodic intervals (by using the PeriodicTaskIF* handle).
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
/**
|
||||
* This function will be called by the OSAL task handler. The
|
||||
* task interface handle can be cached to access task specific properties.
|
||||
* @param task
|
||||
*/
|
||||
void setTaskIF(PeriodicTaskIF *task) override;
|
||||
/**
|
||||
* This function will be called by the OSAL task handler. The
|
||||
* task interface handle can be cached to access task specific properties.
|
||||
* @param task
|
||||
*/
|
||||
void setTaskIF(PeriodicTaskIF* task) override;
|
||||
|
||||
object_id_t getObjectId() const override;
|
||||
object_id_t getObjectId() const override;
|
||||
|
||||
MessageQueueId_t getMessageQueueId();
|
||||
MessageQueueId_t getMessageQueueId();
|
||||
|
||||
private:
|
||||
LocalDataPoolManager poolManager;
|
||||
FsfwDemoSet *senderSet = nullptr;
|
||||
FsfwDemoSet demoSet;
|
||||
AbsLimitMonitor<int32_t> monitor;
|
||||
PeriodicTaskIF *task = nullptr;
|
||||
MessageQueueIF *commandQueue = nullptr;
|
||||
|
||||
/* HasLocalDatapoolIF overrides */
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
uint32_t getPeriodicOperationFrequency() const override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
LocalDataPoolManager *getHkManagerHandle() override;
|
||||
private:
|
||||
LocalDataPoolManager poolManager;
|
||||
FsfwDemoSet* senderSet = nullptr;
|
||||
FsfwDemoSet demoSet;
|
||||
AbsLimitMonitor<int32_t> monitor;
|
||||
PeriodicTaskIF* task = nullptr;
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
object_id_t getNextRecipient();
|
||||
object_id_t getSender();
|
||||
/* HasLocalDatapoolIF overrides */
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
uint32_t getPeriodicOperationFrequency() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
|
||||
ReturnValue_t performMonitoringDemo();
|
||||
ReturnValue_t performSendOperation();
|
||||
ReturnValue_t performReceiveOperation();
|
||||
object_id_t getNextRecipient();
|
||||
object_id_t getSender();
|
||||
|
||||
ReturnValue_t performMonitoringDemo();
|
||||
ReturnValue_t performSendOperation();
|
||||
ReturnValue_t performReceiveOperation();
|
||||
uint8_t execCounter = 0;
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEMO_FSFWDEMOTASK_H_ */
|
||||
|
@ -1,55 +1,55 @@
|
||||
#include "FsfwReaderTask.h"
|
||||
|
||||
#include <OBSWConfig.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout)
|
||||
: SystemObject(objectId),
|
||||
printoutEnabled(enablePrintout),
|
||||
opDivider(10),
|
||||
readSet(this->getObjectId(), gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE),
|
||||
gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE),
|
||||
gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) {
|
||||
/* Special protection for set reading because each variable is read from a
|
||||
* different pool */
|
||||
readSet.setReadCommitProtectionBehaviour(true);
|
||||
#include <OBSWConfig.h>
|
||||
|
||||
|
||||
FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout):
|
||||
SystemObject(objectId), printoutEnabled(enablePrintout), opDivider(10),
|
||||
readSet(this->getObjectId(),
|
||||
gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE),
|
||||
gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE),
|
||||
gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) {
|
||||
/* Special protection for set reading because each variable is read from a different pool */
|
||||
readSet.setReadCommitProtectionBehaviour(true);
|
||||
}
|
||||
|
||||
FsfwReaderTask::~FsfwReaderTask() = default;
|
||||
FsfwReaderTask::~FsfwReaderTask() {
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() {
|
||||
/* Give other task some time to set up local data pools. */
|
||||
TaskFactory::delayTask(20);
|
||||
return returnvalue::OK;
|
||||
/* Give other task some time to set up local data pools. */
|
||||
TaskFactory::delayTask(20);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
|
||||
PoolReadGuard readHelper(&readSet);
|
||||
PoolReadGuard readHelper(&readSet);
|
||||
|
||||
uint32_t variable1 = readSet.variable1.value;
|
||||
uint32_t variable2 = readSet.variable2.value;
|
||||
uint32_t variable3 = readSet.variable3.value;
|
||||
uint32_t variable1 = readSet.variable1.value;
|
||||
uint32_t variable2 = readSet.variable2.value;
|
||||
uint32_t variable3 = readSet.variable3.value;
|
||||
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
if (opDivider.checkAndIncrement() and printoutEnabled) {
|
||||
if(opDivider.checkAndIncrement() and printoutEnabled) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "FsfwPeriodicTask::performOperation: Reading variables." << std::endl;
|
||||
sif::info << "Variable read from demo object 1: " << variable1 << std::endl;
|
||||
sif::info << "Variable read from demo object 2: " << variable2 << std::endl;
|
||||
sif::info << "Variable read from demo object 3: " << variable3 << std::endl;
|
||||
sif::info << "FsfwPeriodicTask::performOperation: Reading variables." << std::endl;
|
||||
sif::info << "Variable read from demo object 1: " << variable1 << std::endl;
|
||||
sif::info << "Variable read from demo object 2: " << variable2 << std::endl;
|
||||
sif::info << "Variable read from demo object 3: " << variable3 << std::endl;
|
||||
#else
|
||||
sif::printInfo("FsfwPeriodicTask::performOperation: Reading variables.\n\r");
|
||||
sif::printInfo("Variable read from demo object 1: %d\n\r", variable1);
|
||||
sif::printInfo("Variable read from demo object 2: %d\n\r", variable2);
|
||||
sif::printInfo("Variable read from demo object 3: %d\n\r", variable3);
|
||||
sif::printInfo("FsfwPeriodicTask::performOperation: Reading variables.\n\r");
|
||||
sif::printInfo("Variable read from demo object 1: %d\n\r", variable1);
|
||||
sif::printInfo("Variable read from demo object 2: %d\n\r", variable2);
|
||||
sif::printInfo("Variable read from demo object 3: %d\n\r", variable3);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (variable1 and variable2 and variable3) {
|
||||
};
|
||||
if(variable1 and variable2 and variable3) {};
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
#ifndef MISSION_DEMO_FSFWPERIODICTASK_H_
|
||||
#define MISSION_DEMO_FSFWPERIODICTASK_H_
|
||||
|
||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
|
||||
#include "testdefinitions/demoDefinitions.h"
|
||||
|
||||
class FsfwReaderTask : public ExecutableObjectIF, public SystemObject {
|
||||
public:
|
||||
FsfwReaderTask(object_id_t objectId, bool enablePrintout);
|
||||
~FsfwReaderTask() override;
|
||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
class FsfwReaderTask: public ExecutableObjectIF, public SystemObject {
|
||||
public:
|
||||
FsfwReaderTask(object_id_t objectId, bool enablePrintout);
|
||||
virtual ~FsfwReaderTask();
|
||||
|
||||
private:
|
||||
bool printoutEnabled = false;
|
||||
PeriodicOperationDivider opDivider;
|
||||
CompleteDemoReadSet readSet;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
private:
|
||||
bool printoutEnabled = false;
|
||||
PeriodicOperationDivider opDivider;
|
||||
CompleteDemoReadSet readSet;
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEMO_FSFWPERIODICTASK_H_ */
|
||||
|
@ -1,21 +0,0 @@
|
||||
#include "FsfwTestTask.h"
|
||||
|
||||
#include <commonConfig.h>
|
||||
|
||||
#if FSFW_ADD_FMT_TESTS == 1
|
||||
#include "testFmt.h"
|
||||
#endif
|
||||
|
||||
FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent)
|
||||
: TestTask(objectId), periodicEvent(periodicEvent) {
|
||||
#if FSFW_ADD_FMT_TESTS == 1
|
||||
fmtTests();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwTestTask::performPeriodicAction() {
|
||||
if (periodicEvent) {
|
||||
triggerEvent(TEST_EVENT, 0x1234, 0x4321);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#ifndef EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_
|
||||
#define EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_
|
||||
|
||||
#include "events/subsystemIdRanges.h"
|
||||
#include "fsfw/events/Event.h"
|
||||
#include "fsfw_tests/integration/task/TestTask.h"
|
||||
|
||||
class FsfwTestTask : public TestTask {
|
||||
public:
|
||||
FsfwTestTask(object_id_t objectId, bool periodicEvent);
|
||||
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
|
||||
private:
|
||||
bool periodicEvent = false;
|
||||
static constexpr uint8_t subsystemId = SUBSYSTEM_ID::TEST_TASK_ID;
|
||||
static constexpr Event TEST_EVENT = event::makeEvent(subsystemId, 0, severity::INFO);
|
||||
};
|
||||
|
||||
#endif /* EXAMPLE_COMMON_EXAMPLE_TEST_FSFWTESTTASK_H_ */
|
@ -3,43 +3,45 @@
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
void MutexExample::example() {
|
||||
MutexIF *mutex = MutexFactory::instance()->createMutex();
|
||||
MutexIF *mutex2 = MutexFactory::instance()->createMutex();
|
||||
|
||||
ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, 2 * 60 * 1000);
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
void MutexExample::example(){
|
||||
MutexIF* mutex = MutexFactory::instance()->createMutex();
|
||||
MutexIF* mutex2 = MutexFactory::instance()->createMutex();
|
||||
|
||||
result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != returnvalue::OK) {
|
||||
ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
|
||||
2 * 60 * 1000);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
result = mutex->unlockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||
sif::error << "MutexExample::example: Lock Failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||
sif::printError("MutexExample::example: Lock Failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
result = mutex2->unlockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
result = mutex->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
result = mutex2->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl;
|
||||
#else
|
||||
sif::printError("MutexExample::example: Unlock Failed with %hu\n", result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef EXAMPLE_COMMON_MUTEXEXAMPLE_H_
|
||||
#define EXAMPLE_COMMON_MUTEXEXAMPLE_H_
|
||||
#ifndef MISSION_DEMO_MUTEXEXAMPLE_H_
|
||||
#define MISSION_DEMO_MUTEXEXAMPLE_H_
|
||||
|
||||
namespace MutexExample {
|
||||
void example();
|
||||
void example();
|
||||
};
|
||||
|
||||
#endif /* EXAMPLE_COMMON_MUTEXEXAMPLE_H_ */
|
||||
#endif /* MISSION_DEMO_MUTEXEXAMPLE_H_ */
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include "testFmt.h"
|
||||
|
||||
void fmtTests() {
|
||||
sif::fdebug(__FILENAME__, __LINE__, "Hello {} {}", "World\n");
|
||||
sif::fdebug_t(__FILENAME__, __LINE__, "Hallo\n");
|
||||
FSFW_LOGD("{}", "Hallo\n");
|
||||
// MY_LOG("{}", "test\n");
|
||||
// sif::finfo_t("Hallo\n");
|
||||
// sif::finfo("Hallo\n");
|
||||
// sif::fwarning("Hello\n");
|
||||
// sif::fwarning_t("Hello\n");
|
||||
// sif::ferror("Hello\n");
|
||||
// sif::ferror_t("Hello\n");
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
#ifndef FSFW_EXAMPLE_HOSTED_TESTFMT_H
|
||||
#define FSFW_EXAMPLE_HOSTED_TESTFMT_H
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <fmt/color.h>
|
||||
#include <fmt/compile.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/ipc/MutexIF.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
|
||||
#define __FILENAME_REL__ (((const char *)__FILE__ + SOURCE_PATH_SIZE))
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
void fmtTests();
|
||||
|
||||
namespace sif {
|
||||
|
||||
static std::array<char, 524> PRINT_BUF = {};
|
||||
|
||||
static const char INFO_PREFIX[] = "INFO";
|
||||
static const char DEBUG_PREFIX[] = "DEBUG";
|
||||
static const char WARNING_PREFIX[] = "WARNING";
|
||||
static const char ERROR_PREFIX[] = "ERROR";
|
||||
|
||||
enum class LogLevel : unsigned int { DEBUG = 0, INFO = 1, WARNING = 2, ERROR = 3 };
|
||||
|
||||
static const char *PREFIX_ARR[4] = {DEBUG_PREFIX, INFO_PREFIX, WARNING_PREFIX, ERROR_PREFIX};
|
||||
|
||||
static const std::array<fmt::color, 4> LOG_COLOR_ARR = {
|
||||
fmt::color::deep_sky_blue, fmt::color::forest_green, fmt::color::orange_red, fmt::color::red};
|
||||
|
||||
static MutexIF *PRINT_MUTEX = MutexFactory::instance()->createMutex();
|
||||
|
||||
static size_t writeTypePrefix(LogLevel level) {
|
||||
auto idx = static_cast<unsigned int>(level);
|
||||
const auto result =
|
||||
fmt::format_to_n(PRINT_BUF.begin(), PRINT_BUF.size() - 1,
|
||||
fmt::runtime(fmt::format(fg(LOG_COLOR_ARR[idx]), PREFIX_ARR[idx])));
|
||||
return result.size;
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
size_t logTraced(LogLevel level, const char *file, unsigned int line, bool timed,
|
||||
fmt::format_string<T...> fmt, T &&...args) noexcept {
|
||||
try {
|
||||
MutexGuard mg(PRINT_MUTEX);
|
||||
size_t bufPos = writeTypePrefix(level);
|
||||
auto currentIter = PRINT_BUF.begin() + bufPos;
|
||||
if (timed) {
|
||||
Clock::TimeOfDay_t logTime;
|
||||
Clock::getDateAndTime(&logTime);
|
||||
const auto result = fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos,
|
||||
" | {}[l.{}] | {:02}:{:02}:{:02}.{:03} | {}", file, line,
|
||||
logTime.hour, logTime.minute, logTime.second,
|
||||
logTime.usecond / 1000, fmt::format(fmt, args...));
|
||||
*result.out = '\0';
|
||||
bufPos += result.size;
|
||||
} else {
|
||||
const auto result =
|
||||
fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos, " | {}[l.{}] | {}", file,
|
||||
line, fmt::format(fmt, args...));
|
||||
*result.out = '\0';
|
||||
bufPos += result.size;
|
||||
}
|
||||
|
||||
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
||||
return bufPos;
|
||||
} catch (const fmt::v8::format_error &e) {
|
||||
fmt::print("Printing failed with error: {}\n", e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
size_t log(LogLevel level, bool timed, fmt::format_string<T...> fmt, T &&...args) noexcept {
|
||||
try {
|
||||
MutexGuard mg(PRINT_MUTEX);
|
||||
size_t bufPos = writeTypePrefix(level);
|
||||
auto currentIter = PRINT_BUF.begin() + bufPos;
|
||||
if (timed) {
|
||||
Clock::TimeOfDay_t logTime;
|
||||
Clock::getDateAndTime(&logTime);
|
||||
const auto result = fmt::format_to_n(
|
||||
currentIter, PRINT_BUF.size() - bufPos, " | {:02}:{:02}:{:02}.{:03} | {}", logTime.hour,
|
||||
logTime.minute, logTime.second, logTime.usecond / 1000, fmt::format(fmt, args...));
|
||||
bufPos += result.size;
|
||||
}
|
||||
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
||||
return bufPos;
|
||||
} catch (const fmt::v8::format_error &e) {
|
||||
fmt::print("Printing failed with error: {}\n", e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void fdebug(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
||||
T &&...args) noexcept {
|
||||
logTraced(LogLevel::DEBUG, file, line, false, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void fdebug_t(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
||||
T &&...args) noexcept {
|
||||
logTraced(LogLevel::DEBUG, file, line, true, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void finfo_t(fmt::format_string<T...> fmt, T &&...args) {
|
||||
log(LogLevel::INFO, true, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void finfo(fmt::format_string<T...> fmt, T &&...args) {
|
||||
log(LogLevel::INFO, false, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void fwarning(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
|
||||
logTraced(LogLevel::WARNING, file, line, false, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void fwarning_t(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
|
||||
logTraced(LogLevel::WARNING, file, line, true, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void ferror(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
|
||||
logTraced(LogLevel::ERROR, file, line, false, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void ferror_t(const char *file, unsigned int line, fmt::format_string<T...> fmt, T &&...args) {
|
||||
logTraced(LogLevel::ERROR, file, line, true, fmt, args...);
|
||||
}
|
||||
|
||||
} // namespace sif
|
||||
|
||||
#define FSFW_LOGI(format, ...) finfo(FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGIT(format, ...) finfo_t(FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGD(format, ...) sif::fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGDT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGW(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGWT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGE(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#define FSFW_LOGET(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||
|
||||
#endif // FSFW_EXAMPLE_HOSTED_TESTFMT_H
|
@ -1,8 +1,8 @@
|
||||
#ifndef MISSION_DEMO_DEMODEFINITIONS_H_
|
||||
#define MISSION_DEMO_DEMODEFINITIONS_H_
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
|
||||
/**
|
||||
* @brief This demo set showcases the local data pool functionality of the
|
||||
@ -11,22 +11,27 @@
|
||||
* Each demo object will have an own instance of this set class, which contains
|
||||
* pool variables (for read and write access respectively).
|
||||
*/
|
||||
class FsfwDemoSet : public StaticLocalDataSet<3> {
|
||||
public:
|
||||
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||
class FsfwDemoSet: public StaticLocalDataSet<3> {
|
||||
public:
|
||||
|
||||
enum PoolIds { VARIABLE, VARIABLE_LIMIT };
|
||||
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||
|
||||
FsfwDemoSet(HasLocalDataPoolIF *hkOwner) : StaticLocalDataSet(hkOwner, DEMO_SET_ID) {}
|
||||
enum PoolIds {
|
||||
VARIABLE,
|
||||
VARIABLE_LIMIT
|
||||
};
|
||||
|
||||
lp_var_t<uint32_t> variableRead =
|
||||
lp_var_t<uint32_t>(sid.objectId, PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ);
|
||||
lp_var_t<uint32_t> variableWrite =
|
||||
lp_var_t<uint32_t>(sid.objectId, PoolIds::VARIABLE, this, pool_rwm_t::VAR_WRITE);
|
||||
lp_var_t<uint16_t> variableLimit =
|
||||
lp_var_t<uint16_t>(sid.objectId, PoolIds::VARIABLE_LIMIT, this);
|
||||
FsfwDemoSet(HasLocalDataPoolIF* hkOwner):
|
||||
StaticLocalDataSet(hkOwner, DEMO_SET_ID) {}
|
||||
|
||||
lp_var_t<uint32_t> variableRead = lp_var_t<uint32_t>(sid.objectId,
|
||||
PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ);
|
||||
lp_var_t<uint32_t> variableWrite = lp_var_t<uint32_t>(sid.objectId,
|
||||
PoolIds::VARIABLE, this, pool_rwm_t::VAR_WRITE);
|
||||
lp_var_t<uint16_t> variableLimit = lp_var_t<uint16_t>(sid.objectId,
|
||||
PoolIds::VARIABLE_LIMIT, this);
|
||||
private:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
/**
|
||||
@ -34,21 +39,25 @@ class FsfwDemoSet : public StaticLocalDataSet<3> {
|
||||
* above. An example application would be a consumer object like a controller
|
||||
* which reads multiple sensor values at once.
|
||||
*/
|
||||
class CompleteDemoReadSet : public StaticLocalDataSet<3> {
|
||||
public:
|
||||
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||
class CompleteDemoReadSet: public StaticLocalDataSet<3> {
|
||||
public:
|
||||
static constexpr uint32_t DEMO_SET_ID = 0;
|
||||
|
||||
CompleteDemoReadSet(object_id_t owner, gp_id_t variable1, gp_id_t variable2, gp_id_t variable3)
|
||||
: StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)),
|
||||
variable1(variable1, this, pool_rwm_t::VAR_READ),
|
||||
variable2(variable2, this, pool_rwm_t::VAR_READ),
|
||||
variable3(variable3, this, pool_rwm_t::VAR_READ) {}
|
||||
CompleteDemoReadSet(object_id_t owner, gp_id_t variable1,
|
||||
gp_id_t variable2, gp_id_t variable3):
|
||||
StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)),
|
||||
variable1(variable1, this, pool_rwm_t::VAR_READ),
|
||||
variable2(variable2, this, pool_rwm_t::VAR_READ),
|
||||
variable3(variable3, this, pool_rwm_t::VAR_READ) {}
|
||||
|
||||
lp_var_t<uint32_t> variable1;
|
||||
lp_var_t<uint32_t> variable2;
|
||||
lp_var_t<uint32_t> variable3;
|
||||
|
||||
private:
|
||||
lp_var_t<uint32_t> variable1;
|
||||
lp_var_t<uint32_t> variable2;
|
||||
lp_var_t<uint32_t> variable3;
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* MISSION_DEMO_DEMODEFINITIONS_H_ */
|
||||
|
@ -1,2 +1,4 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE utility.cpp TmFunnel.cpp PusTmFunnel.cpp
|
||||
CfdpTmFunnel.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
utility.cpp
|
||||
TmFunnel.cpp
|
||||
)
|
||||
|
@ -1,84 +0,0 @@
|
||||
#include "CfdpTmFunnel.h"
|
||||
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
|
||||
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore)
|
||||
: SystemObject(objectId), cfdpInCcsdsApid(cfdpInCcsdsApid), tmStore(tmStore) {
|
||||
msgQueue = QueueFactory::instance()->createMessageQueue(5);
|
||||
msgQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue());
|
||||
}
|
||||
|
||||
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
|
||||
|
||||
MessageQueueId_t CfdpTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
|
||||
return msgQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
|
||||
TmTcMessage currentMessage;
|
||||
ReturnValue_t status = msgQueue->receiveMessage(¤tMessage);
|
||||
while (status == returnvalue::OK) {
|
||||
status = handlePacket(currentMessage);
|
||||
if (status != returnvalue::OK) {
|
||||
sif::warning << "CfdpTmFunnel packet handling failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
status = msgQueue->receiveMessage(¤tMessage);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#ifndef FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
|
||||
#define FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
|
||||
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
|
||||
class CfdpTmFunnel : public AcceptsTelemetryIF, public SystemObject {
|
||||
public:
|
||||
CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
|
||||
const AcceptsTelemetryIF& downlinkDestination, StorageManagerIF& tmStore);
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
ReturnValue_t handlePacket(TmTcMessage& msg);
|
||||
|
||||
uint16_t sourceSequenceCount = 0;
|
||||
uint16_t cfdpInCcsdsApid;
|
||||
MessageQueueIF* msgQueue;
|
||||
StorageManagerIF& tmStore;
|
||||
};
|
||||
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
|
@ -1,9 +1,10 @@
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/tmtcpacket/pus/tc.h>
|
||||
#include <fsfw/tmtcpacket/pus/tm.h>
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <mission/utility/PusPacketCreator.h>
|
||||
|
||||
void PusPacketCreator::createPusPacketAndPrint() {
|
||||
// TODO: use TC packet stored here instead..
|
||||
// TODO: use TC packet stored here instead..
|
||||
|
||||
}
|
||||
|
@ -9,8 +9,8 @@
|
||||
#define MISSION_UTILITY_PUSPACKETCREATOR_H_
|
||||
|
||||
class PusPacketCreator {
|
||||
public:
|
||||
static void createPusPacketAndPrint();
|
||||
public:
|
||||
static void createPusPacketAndPrint();
|
||||
};
|
||||
|
||||
#endif /* MISSION_UTILITY_PUSPACKETCREATOR_H_ */
|
||||
|
@ -1,68 +0,0 @@
|
||||
#include "PusTmFunnel.h"
|
||||
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/objectmanager.h"
|
||||
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
|
||||
|
||||
PusTmFunnel::PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination,
|
||||
TimeReaderIF &timeReader, StorageManagerIF &tmStore, uint32_t messageDepth)
|
||||
: SystemObject(objectId), timeReader(timeReader), tmStore(tmStore) {
|
||||
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
|
||||
MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
tmQueue->setDefaultDestination(downlinkDestination.getReportReceptionQueue());
|
||||
}
|
||||
|
||||
PusTmFunnel::~PusTmFunnel() = default;
|
||||
|
||||
MessageQueueId_t PusTmFunnel::getReportReceptionQueue(uint8_t virtualChannel) const {
|
||||
return tmQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
|
||||
TmTcMessage currentMessage;
|
||||
ReturnValue_t status = tmQueue->receiveMessage(¤tMessage);
|
||||
while (status == returnvalue::OK) {
|
||||
status = handlePacket(currentMessage);
|
||||
if (status != returnvalue::OK) {
|
||||
sif::warning << "TmFunnel packet handling failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
status = tmQueue->receiveMessage(¤tMessage);
|
||||
}
|
||||
|
||||
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"; }
|
@ -1,39 +0,0 @@
|
||||
#ifndef FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
|
||||
#define FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
|
||||
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||
|
||||
#include "fsfw/timemanager/TimeReaderIF.h"
|
||||
|
||||
/**
|
||||
* @brief TM Recipient.
|
||||
* @details
|
||||
* Main telemetry receiver. All generated telemetry is funneled into
|
||||
* this object.
|
||||
* @ingroup utility
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PusTmFunnel : public AcceptsTelemetryIF, public SystemObject {
|
||||
public:
|
||||
explicit PusTmFunnel(object_id_t objectId, const AcceptsTelemetryIF &downlinkDestination,
|
||||
TimeReaderIF &timeReader, StorageManagerIF &tmStore,
|
||||
uint32_t messageDepth = 20);
|
||||
[[nodiscard]] const char *getName() const override;
|
||||
~PusTmFunnel() override;
|
||||
|
||||
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode);
|
||||
|
||||
private:
|
||||
uint16_t sourceSequenceCount = 0;
|
||||
TimeReaderIF &timeReader;
|
||||
StorageManagerIF &tmStore;
|
||||
MessageQueueIF *tmQueue = nullptr;
|
||||
ReturnValue_t handlePacket(TmTcMessage &message);
|
||||
};
|
||||
|
||||
#endif // FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H
|
@ -6,16 +6,17 @@
|
||||
|
||||
namespace task {
|
||||
|
||||
void printInitError(const char *objName, object_id_t objectId) {
|
||||
void printInitError(const char* objName, object_id_t objectId) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "InitMission: Adding object " << objName << "(" << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << objectId << std::dec << ") failed." << std::endl;
|
||||
sif::error << "InitMission: Adding object " << objName << "("
|
||||
<< std::setw(8) << std::setfill('0') << std::hex << objectId
|
||||
<< std::dec << ") failed." << std::endl;
|
||||
#else
|
||||
sif::printError("InitMission: Adding object %s (0x%08x) failed.\n", objName,
|
||||
static_cast<unsigned int>(objectId));
|
||||
sif::printError("InitMission: Adding object %s (0x%08x) failed.\n",
|
||||
objName, static_cast<unsigned int>(objectId));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace task
|
||||
}
|
||||
|
||||
#endif /* MISSION_UTILITY_TASKCREATION_H_ */
|
||||
|
@ -1,16 +1,120 @@
|
||||
#include "TmFunnel.h"
|
||||
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/tmtcpacket/pus/tm.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
TmFunnel::TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel)
|
||||
: SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel) {}
|
||||
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT;
|
||||
object_id_t TmFunnel::storageDestination = objects::NO_OBJECT;
|
||||
|
||||
TmFunnel::~TmFunnel() = default;
|
||||
|
||||
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
|
||||
pusFunnel.performOperation(operationCode);
|
||||
cfdpFunnel.performOperation(operationCode);
|
||||
return returnvalue::OK;
|
||||
TmFunnel::TmFunnel(object_id_t objectId, uint32_t messageDepth):
|
||||
SystemObject(objectId), messageDepth(messageDepth) {
|
||||
tmQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
|
||||
MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
storageQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
|
||||
MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
ReturnValue_t TmFunnel::initialize() { return returnvalue::OK; }
|
||||
TmFunnel::~TmFunnel() {
|
||||
}
|
||||
|
||||
MessageQueueId_t TmFunnel::getReportReceptionQueue(uint8_t virtualChannel) {
|
||||
return tmQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t TmFunnel::performOperation(uint8_t operationCode) {
|
||||
TmTcMessage currentMessage;
|
||||
ReturnValue_t status = tmQueue->receiveMessage(¤tMessage);
|
||||
while(status == HasReturnvaluesIF::RETURN_OK)
|
||||
{
|
||||
status = handlePacket(¤tMessage);
|
||||
if(status != HasReturnvaluesIF::RETURN_OK){
|
||||
break;
|
||||
}
|
||||
status = tmQueue->receiveMessage(¤tMessage);
|
||||
}
|
||||
|
||||
if (status == MessageQueueIF::EMPTY) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t TmFunnel::handlePacket(TmTcMessage* message) {
|
||||
uint8_t* packetData = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = tmPool->modifyData(message->getStorageId(),
|
||||
&packetData, &size);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
TmPacketPusC packet(packetData);
|
||||
packet.setPacketSequenceCount(this->sourceSequenceCount);
|
||||
sourceSequenceCount++;
|
||||
sourceSequenceCount = sourceSequenceCount %
|
||||
SpacePacketBase::LIMIT_SEQUENCE_COUNT;
|
||||
packet.setErrorControl();
|
||||
|
||||
result = tmQueue->sendToDefault(message);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
tmPool->deleteData(message->getStorageId());
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmFunnel::handlePacket: Error sending to downlink handler" << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
if(storageDestination != objects::NO_OBJECT) {
|
||||
result = storageQueue->sendToDefault(message);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
tmPool->deleteData(message->getStorageId());
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmFunnel::handlePacket: Error sending to storage handler" << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t TmFunnel::initialize() {
|
||||
|
||||
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
|
||||
if(tmPool == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmFunnel::initialize: TM store not set." << std::endl;
|
||||
sif::error << "Make sure the tm store is set up properly and implements StorageManagerIF" <<
|
||||
std::endl;
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
AcceptsTelemetryIF* tmTarget = ObjectManager::instance()->
|
||||
get<AcceptsTelemetryIF>(downlinkDestination);
|
||||
if(tmTarget == nullptr){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmFunnel::initialize: Downlink Destination not set." << std::endl;
|
||||
sif::error << "Make sure the downlink destination object is set up properly and implements "
|
||||
"AcceptsTelemetryIF" << std::endl;
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue());
|
||||
|
||||
// Storage destination is optional.
|
||||
if(storageDestination == objects::NO_OBJECT) {
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
AcceptsTelemetryIF* storageTarget = ObjectManager::instance()->
|
||||
get<AcceptsTelemetryIF>(storageDestination);
|
||||
if(storageTarget != nullptr) {
|
||||
storageQueue->setDefaultDestination(
|
||||
storageTarget->getReportReceptionQueue());
|
||||
}
|
||||
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#ifndef MISSION_UTILITY_TMFUNNEL_H_
|
||||
#define MISSION_UTILITY_TMFUNNEL_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||
|
||||
#include "CfdpTmFunnel.h"
|
||||
#include "PusTmFunnel.h"
|
||||
#include "fsfw/timemanager/TimeReaderIF.h"
|
||||
namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TM Recipient.
|
||||
@ -19,17 +19,33 @@
|
||||
* @ingroup utility
|
||||
* @author J. Meier
|
||||
*/
|
||||
class TmFunnel : public ExecutableObjectIF, public SystemObject {
|
||||
public:
|
||||
TmFunnel(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel);
|
||||
~TmFunnel() override;
|
||||
class TmFunnel:
|
||||
public AcceptsTelemetryIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
TmFunnel(object_id_t objectId, uint32_t messageDepth = 20);
|
||||
virtual ~TmFunnel();
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
virtual MessageQueueId_t getReportReceptionQueue(
|
||||
uint8_t virtualChannel = 0) override;
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
PusTmFunnel& pusFunnel;
|
||||
CfdpTmFunnel& cfdpFunnel;
|
||||
protected:
|
||||
static object_id_t downlinkDestination;
|
||||
static object_id_t storageDestination;
|
||||
|
||||
private:
|
||||
uint16_t sourceSequenceCount = 0;
|
||||
MessageQueueIF* tmQueue = nullptr;
|
||||
MessageQueueIF* storageQueue = nullptr;
|
||||
|
||||
StorageManagerIF* tmPool = nullptr;
|
||||
uint32_t messageDepth = 0;
|
||||
|
||||
ReturnValue_t handlePacket(TmTcMessage* message);
|
||||
};
|
||||
|
||||
#endif /* MISSION_UTILITY_TMFUNNEL_H_ */
|
||||
|
@ -5,21 +5,16 @@
|
||||
* Authors:
|
||||
*
|
||||
* Assembled from the code released on Stackoverflow by:
|
||||
* Dennis (instructable.com/member/nqtronix) |
|
||||
* https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string
|
||||
* Dennis (instructable.com/member/nqtronix) | https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string
|
||||
* and
|
||||
* Alexis Wilke |
|
||||
* https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date
|
||||
* Alexis Wilke | https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date
|
||||
*
|
||||
* Assembled by Jean Rabault
|
||||
*
|
||||
* UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds
|
||||
* since 1st Jan 1970) of compilation from macros using the compiler defined
|
||||
* __TIME__ macro. This should include Gregorian calendar leap days, in
|
||||
* particular the 29ths of February, 100 and 400 years modulo leaps.
|
||||
* UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro.
|
||||
* This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
|
||||
*
|
||||
* Careful: __TIME__ is the local time of the computer, NOT the UTC time in
|
||||
* general!
|
||||
* Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
|
||||
*
|
||||
*/
|
||||
|
||||
@ -27,66 +22,76 @@
|
||||
#define COMPILE_TIME_H_
|
||||
|
||||
// Some definitions for calculation
|
||||
#define SEC_PER_MIN 60UL
|
||||
#define SEC_PER_HOUR 3600UL
|
||||
#define SEC_PER_DAY 86400UL
|
||||
#define SEC_PER_YEAR (SEC_PER_DAY * 365)
|
||||
#define SEC_PER_MIN 60UL
|
||||
#define SEC_PER_HOUR 3600UL
|
||||
#define SEC_PER_DAY 86400UL
|
||||
#define SEC_PER_YEAR (SEC_PER_DAY*365)
|
||||
|
||||
// extracts 1..4 characters from a string and interprets it as a decimal value
|
||||
#define CONV_STR2DEC_1(str, i) (str[i] > '0' ? str[i] - '0' : 0)
|
||||
#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i) * 10 + str[i + 1] - '0')
|
||||
#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i) * 10 + str[i + 2] - '0')
|
||||
#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i) * 10 + str[i + 3] - '0')
|
||||
#define CONV_STR2DEC_1(str, i) (str[i]>'0'?str[i]-'0':0)
|
||||
#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0')
|
||||
#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0')
|
||||
#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0')
|
||||
|
||||
// Custom "glue logic" to convert the month name to a usable number
|
||||
#define GET_MONTH(str, i) \
|
||||
(str[i] == 'J' && str[i + 1] == 'a' && str[i + 2] == 'n' ? 1 \
|
||||
: str[i] == 'F' && str[i + 1] == 'e' && str[i + 2] == 'b' ? 2 \
|
||||
: str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'r' ? 3 \
|
||||
: str[i] == 'A' && str[i + 1] == 'p' && str[i + 2] == 'r' ? 4 \
|
||||
: str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'y' ? 5 \
|
||||
: str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'n' ? 6 \
|
||||
: str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'l' ? 7 \
|
||||
: str[i] == 'A' && str[i + 1] == 'u' && str[i + 2] == 'g' ? 8 \
|
||||
: str[i] == 'S' && str[i + 1] == 'e' && str[i + 2] == 'p' ? 9 \
|
||||
: str[i] == 'O' && str[i + 1] == 'c' && str[i + 2] == 't' ? 10 \
|
||||
: str[i] == 'N' && str[i + 1] == 'o' && str[i + 2] == 'v' ? 11 \
|
||||
: str[i] == 'D' && str[i + 1] == 'e' && str[i + 2] == 'c' ? 12 \
|
||||
: 0)
|
||||
#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \
|
||||
str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \
|
||||
str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \
|
||||
str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \
|
||||
str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \
|
||||
str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \
|
||||
str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \
|
||||
str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \
|
||||
str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \
|
||||
str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \
|
||||
str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 : \
|
||||
str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0)
|
||||
|
||||
// extract the information from the time string given by __TIME__ and __DATE__
|
||||
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
|
||||
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
|
||||
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
|
||||
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
|
||||
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
|
||||
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
|
||||
#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6)
|
||||
#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3)
|
||||
#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0)
|
||||
#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4)
|
||||
#define __TIME_MONTH__ GET_MONTH(__DATE__, 0)
|
||||
#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7)
|
||||
|
||||
// Days in February
|
||||
#define _UNIX_TIMESTAMP_FDAY(year) \
|
||||
(((year) % 400) == 0UL ? 29UL \
|
||||
: (((year) % 100) == 0UL ? 28UL : (((year) % 4) == 0UL ? 29UL : 28UL)))
|
||||
(((year) % 400) == 0UL ? 29UL : \
|
||||
(((year) % 100) == 0UL ? 28UL : \
|
||||
(((year) % 4) == 0UL ? 29UL : \
|
||||
28UL)))
|
||||
|
||||
// Days in the year
|
||||
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
|
||||
(/* January */ day /* February */ + (month >= 2 ? 31UL : 0UL) /* March */ + \
|
||||
(month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) /* April */ + \
|
||||
(month >= 4 ? 31UL : 0UL) /* May */ + (month >= 5 ? 30UL : 0UL) /* June */ + \
|
||||
(month >= 6 ? 31UL : 0UL) /* July */ + (month >= 7 ? 30UL : 0UL) /* August */ + \
|
||||
(month >= 8 ? 31UL : 0UL) /* September */ + (month >= 9 ? 31UL : 0UL) /* October */ + \
|
||||
(month >= 10 ? 30UL : 0UL) /* November */ + (month >= 11 ? 31UL : 0UL) /* December */ + \
|
||||
(month >= 12 ? 30UL : 0UL))
|
||||
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
|
||||
( \
|
||||
/* January */ day \
|
||||
/* February */ + (month >= 2 ? 31UL : 0UL) \
|
||||
/* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \
|
||||
/* April */ + (month >= 4 ? 31UL : 0UL) \
|
||||
/* May */ + (month >= 5 ? 30UL : 0UL) \
|
||||
/* June */ + (month >= 6 ? 31UL : 0UL) \
|
||||
/* July */ + (month >= 7 ? 30UL : 0UL) \
|
||||
/* August */ + (month >= 8 ? 31UL : 0UL) \
|
||||
/* September */+ (month >= 9 ? 31UL : 0UL) \
|
||||
/* October */ + (month >= 10 ? 30UL : 0UL) \
|
||||
/* November */ + (month >= 11 ? 31UL : 0UL) \
|
||||
/* December */ + (month >= 12 ? 30UL : 0UL) \
|
||||
)
|
||||
|
||||
// get the UNIX timestamp from a digits representation
|
||||
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
|
||||
(/* time */ second + minute * SEC_PER_MIN + hour * SEC_PER_HOUR + \
|
||||
/* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY + \
|
||||
/* year */ (year - 1970UL) * SEC_PER_YEAR + ((year - 1969UL) / 4UL) * SEC_PER_DAY - \
|
||||
((year - 1901UL) / 100UL) * SEC_PER_DAY + ((year - 1601UL) / 400UL) * SEC_PER_DAY)
|
||||
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
|
||||
( /* time */ second \
|
||||
+ minute * SEC_PER_MIN \
|
||||
+ hour * SEC_PER_HOUR \
|
||||
+ /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \
|
||||
+ /* year */ (year - 1970UL) * SEC_PER_YEAR \
|
||||
+ ((year - 1969UL) / 4UL) * SEC_PER_DAY \
|
||||
- ((year - 1901UL) / 100UL) * SEC_PER_DAY \
|
||||
+ ((year - 1601UL) / 400UL) * SEC_PER_DAY \
|
||||
)
|
||||
|
||||
// the UNIX timestamp
|
||||
#define UNIX_TIMESTAMP \
|
||||
(_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, \
|
||||
__TIME_MINUTES__, __TIME_SECONDS__))
|
||||
#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__))
|
||||
|
||||
#endif
|
||||
|
@ -1,22 +1,22 @@
|
||||
#include "utility.h"
|
||||
|
||||
#include <FSFWConfig.h>
|
||||
#include <OBSWVersion.h>
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
void utility::commonInitPrint(const char *const os, const char *const board) {
|
||||
if (os == nullptr or board == nullptr) {
|
||||
return;
|
||||
}
|
||||
void utility::commonInitPrint(const char *const os, const char* const board) {
|
||||
if(os == nullptr or board == nullptr) {
|
||||
return;
|
||||
}
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
std::cout << "-- FSFW Example (" << os << ") v" << FSFW_EXAMPLE_VERSION << "."
|
||||
<< FSFW_EXAMPLE_SUBVERSION << "." << FSFW_EXAMPLE_REVISION << " --" << std::endl;
|
||||
std::cout << "-- Compiled for " << board << " --" << std::endl;
|
||||
std::cout << "-- Compiled on " << __DATE__ << " " << __TIME__ << " --" << std::endl;
|
||||
std::cout << "-- FSFW Example (" << os<< ") v" << FSFW_EXAMPLE_VERSION << "." <<
|
||||
FSFW_EXAMPLE_SUBVERSION << "." << FSFW_EXAMPLE_REVISION << " --" << std::endl;
|
||||
std::cout << "-- Compiled for " << board << " --" << std::endl;
|
||||
std::cout << "-- Compiled on " << __DATE__ << " " << __TIME__ << " --" << std::endl;
|
||||
#else
|
||||
printf("\n\r-- FSFW Example (%s) v%d.%d.%d --\n", os, FSFW_EXAMPLE_VERSION,
|
||||
FSFW_EXAMPLE_SUBVERSION, FSFW_EXAMPLE_REVISION);
|
||||
printf("-- Compiled for %s --\n", board);
|
||||
printf("-- Compiled on %s %s --\n", __DATE__, __TIME__);
|
||||
printf("\n\r-- FSFW Example (%s) v%d.%d.%d --\n", os, FSFW_EXAMPLE_VERSION,
|
||||
FSFW_EXAMPLE_SUBVERSION, FSFW_EXAMPLE_REVISION);
|
||||
printf("-- Compiled for %s --\n", board);
|
||||
printf("-- Compiled on %s %s --\n", __DATE__, __TIME__);
|
||||
#endif
|
||||
}
|
||||
|
@ -3,8 +3,9 @@
|
||||
|
||||
namespace utility {
|
||||
|
||||
void commonInitPrint(const char *const os, const char *const board);
|
||||
void commonInitPrint(const char *const os, const char* const board);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* COMMON_UTILITY_UTILITY_H_ */
|
||||
|
@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
counter=0
|
||||
common_example_dir="example_common"
|
||||
while [ ${counter} -lt 5 ]
|
||||
do
|
||||
if [ ! -d ${common_example_dir} ];then
|
||||
break
|
||||
fi
|
||||
counter=$((counter=counter + 1))
|
||||
cd ..
|
||||
done
|
||||
|
||||
if [ "${counter}" -ge 5 ];then
|
||||
echo "${common_example_dir} not found in upper directories!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
folder_list=(
|
||||
"./bsp_hosted"
|
||||
"./example_common"
|
||||
)
|
||||
|
||||
cmake_fmt="cmake-format"
|
||||
file_selectors="-iname CMakeLists.txt"
|
||||
if command -v ${cmake_fmt} &> /dev/null; then
|
||||
echo "Auto-formatting all CMakeLists.txt files"
|
||||
${cmake_fmt} -i CMakeLists.txt
|
||||
for dir in ${folder_list[@]}; do
|
||||
find ${dir} ${file_selectors} | xargs ${cmake_fmt} -i
|
||||
done
|
||||
else
|
||||
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||
fi
|
||||
|
||||
cpp_format="clang-format"
|
||||
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||
if command -v ${cpp_format} &> /dev/null; then
|
||||
for dir in ${folder_list[@]}; do
|
||||
echo "Auto-formatting C/C++ files in ${dir} recursively"
|
||||
find ${dir} ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
done
|
||||
else
|
||||
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||
fi
|
@ -1,7 +1,9 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE STM32TestTask.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
STM32TestTask.cpp
|
||||
)
|
||||
|
||||
option(STM32_ADD_NETWORKING_CODE "Add networking code requiring lwIP" ON)
|
||||
|
||||
if(STM32_ADD_NETWORKING_CODE)
|
||||
add_subdirectory(networking)
|
||||
endif()
|
||||
add_subdirectory(networking)
|
||||
endif()
|
@ -1,33 +1,22 @@
|
||||
#include "STM32TestTask.h"
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "stm32h7xx_nucleo.h"
|
||||
#include "OBSWConfig.h"
|
||||
|
||||
STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed)
|
||||
: TestTask(objectId), blinkyLed(blinkyLed) {
|
||||
BSP_LED_Init(LED1);
|
||||
BSP_LED_Init(LED2);
|
||||
BSP_LED_Init(LED3);
|
||||
}
|
||||
|
||||
ReturnValue_t STM32TestTask::initialize() {
|
||||
if (testSpi) {
|
||||
spiComIF = new SpiComIF(objects::SPI_COM_IF);
|
||||
spiTest = new SpiTest(*spiComIF);
|
||||
}
|
||||
return TestTask::initialize();
|
||||
STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout,
|
||||
bool blinkyLed): TestTask(objectId, enablePrintout),
|
||||
blinkyLed(blinkyLed) {
|
||||
BSP_LED_Init(LED1);
|
||||
BSP_LED_Init(LED2);
|
||||
BSP_LED_Init(LED3);
|
||||
}
|
||||
|
||||
ReturnValue_t STM32TestTask::performPeriodicAction() {
|
||||
if (blinkyLed) {
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 0
|
||||
BSP_LED_Toggle(LED1);
|
||||
BSP_LED_Toggle(LED2);
|
||||
if(blinkyLed) {
|
||||
#if OBSW_ETHERNET_USE_LEDS == 0
|
||||
BSP_LED_Toggle(LED1);
|
||||
BSP_LED_Toggle(LED2);
|
||||
#endif
|
||||
BSP_LED_Toggle(LED3);
|
||||
}
|
||||
if (testSpi) {
|
||||
spiTest->performOperation();
|
||||
}
|
||||
return TestTask::performPeriodicAction();
|
||||
BSP_LED_Toggle(LED3);
|
||||
}
|
||||
return TestTask::performPeriodicAction();
|
||||
}
|
||||
|
@ -1,22 +1,19 @@
|
||||
#ifndef BSP_STM32_BOARDTEST_STM32TESTTASK_H_
|
||||
#define BSP_STM32_BOARDTEST_STM32TESTTASK_H_
|
||||
|
||||
#include "bsp_stm32h7_freertos/boardtest/SpiTest.h"
|
||||
#include "fsfw_tests/integration/task/TestTask.h"
|
||||
#include "../test/TestTask.h"
|
||||
|
||||
class STM32TestTask : public TestTask {
|
||||
public:
|
||||
STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed = true);
|
||||
class STM32TestTask: public TestTask {
|
||||
public:
|
||||
STM32TestTask(object_id_t objectId, bool enablePrintout, bool blinkyLed = true);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
private:
|
||||
|
||||
private:
|
||||
SpiComIF *spiComIF = nullptr;
|
||||
SpiTest *spiTest = nullptr;
|
||||
bool blinkyLed = false;
|
||||
|
||||
bool blinkyLed = false;
|
||||
bool testSpi = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */
|
||||
|
@ -1,8 +1,14 @@
|
||||
# These are part of the RTEMS BSP for RTEMS
|
||||
if(FSFW_OSAL MATCHES freertos)
|
||||
target_sources(${TARGET_NAME} PRIVATE ethernetif.c)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
ethernetif.c
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
${TARGET_NAME} PRIVATE UdpTcLwIpPollingTask.cpp TmTcLwIpUdpBridge.cpp
|
||||
networking.cpp app_dhcp.cpp app_ethernet.cpp)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
UdpTcLwIpPollingTask.cpp
|
||||
TmTcLwIpUdpBridge.cpp
|
||||
networking.cpp
|
||||
app_dhcp.cpp
|
||||
app_ethernet.cpp
|
||||
)
|
||||
|
@ -1,189 +1,204 @@
|
||||
#include "TmTcLwIpUdpBridge.h"
|
||||
#include "udp_config.h"
|
||||
#include "app_ethernet.h"
|
||||
#include "ethernetif.h"
|
||||
#include <OBSWConfig.h>
|
||||
|
||||
#include <fsfw/ipc/MutexGuard.h>
|
||||
#include <fsfw/serialize/EndianConverter.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/serialize/EndianConverter.h>
|
||||
|
||||
#include "app_ethernet.h"
|
||||
#include "udp_config.h"
|
||||
|
||||
TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor,
|
||||
object_id_t tmStoreId, object_id_t tcStoreId)
|
||||
: TmTcBridge(objectId, ccsdsPacketDistributor, tmStoreId, tcStoreId) {
|
||||
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
|
||||
TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId,
|
||||
object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
|
||||
object_id_t tcStoreId):
|
||||
TmTcBridge(objectId, ccsdsPacketDistributor, tmStoreId, tcStoreId) {
|
||||
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
|
||||
}
|
||||
|
||||
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() = default;
|
||||
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {}
|
||||
|
||||
ReturnValue_t TmTcLwIpUdpBridge::initialize() {
|
||||
TmTcBridge::initialize();
|
||||
bridgeLock = MutexFactory::instance()->createMutex();
|
||||
if (bridgeLock == nullptr) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
ReturnValue_t result = udp_server_init();
|
||||
return result;
|
||||
TmTcBridge::initialize();
|
||||
bridgeLock = MutexFactory::instance()->createMutex();
|
||||
if(bridgeLock == nullptr) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
ReturnValue_t result = udp_server_init();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init() {
|
||||
err_t err;
|
||||
/* Create a new UDP control block */
|
||||
TmTcLwIpUdpBridge::upcb = udp_new();
|
||||
if (TmTcLwIpUdpBridge::upcb) {
|
||||
sif::printInfo("Opening UDP server on port %d\n", UDP_SERVER_PORT);
|
||||
/* Bind the upcb to the UDP_PORT port */
|
||||
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
|
||||
err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
|
||||
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) {
|
||||
err_t err;
|
||||
/* Create a new UDP control block */
|
||||
TmTcLwIpUdpBridge::upcb = udp_new();
|
||||
if (TmTcLwIpUdpBridge::upcb)
|
||||
{
|
||||
/* Bind the upcb to the UDP_PORT port */
|
||||
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
|
||||
err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
|
||||
|
||||
if (err == ERR_OK) {
|
||||
/* Set a receive callback for the upcb */
|
||||
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback, (void *)this);
|
||||
return RETURN_OK;
|
||||
if(err == ERR_OK)
|
||||
{
|
||||
/* Set a receive callback for the upcb */
|
||||
udp_recv(TmTcLwIpUdpBridge::upcb, &udp_server_receive_callback,
|
||||
(void*) this);
|
||||
return RETURN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
udp_remove(TmTcLwIpUdpBridge::upcb);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
udp_remove(TmTcLwIpUdpBridge::upcb);
|
||||
return RETURN_FAILED;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
|
||||
TmTcBridge::performOperation();
|
||||
TmTcBridge::performOperation();
|
||||
|
||||
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
|
||||
if (connectFlag) {
|
||||
uint32_t ipAddress = ((ip4_addr *)&lastAdd)->addr;
|
||||
int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
|
||||
int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
|
||||
int ipAddress3 = (ipAddress & 0xFF00) >> 8;
|
||||
int ipAddress4 = ipAddress & 0xFF;
|
||||
#if TCPIP_RECV_WIRETAPPING == 1
|
||||
if(connectFlag) {
|
||||
uint32_t ipAddress = ((ip4_addr*) &lastAdd)->addr;
|
||||
int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
|
||||
int ipAddress2 = (ipAddress & 0xFF0000) >> 16;
|
||||
int ipAddress3 = (ipAddress & 0xFF00) >> 8;
|
||||
int ipAddress4 = ipAddress & 0xFF;
|
||||
#if OBSW_VERBOSE_LEVEL == 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec << ipAddress4 << "."
|
||||
<< ipAddress3 << "." << ipAddress2 << "." << ipAddress1 << std::endl;
|
||||
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
|
||||
sif::info << "TmTcLwIpUdpBridge: Client IP Port " << (int)portSwapped << std::endl;
|
||||
sif::info << "TmTcLwIpUdpBridge: Client IP Address " << std::dec
|
||||
<< ipAddress4 << "." << ipAddress3 << "." << ipAddress2 << "."
|
||||
<< ipAddress1 << std::endl;
|
||||
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
|
||||
sif::info << "TmTcLwIpUdpBridge: Client IP Port "
|
||||
<< (int)portSwapped << std::endl;
|
||||
#else
|
||||
sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n", ipAddress4, ipAddress3,
|
||||
ipAddress2, ipAddress1);
|
||||
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
|
||||
sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped);
|
||||
sif::printInfo("TmTcLwIpUdpBridge: Client IP Address %d.%d.%d.%d\n",
|
||||
ipAddress4, ipAddress3, ipAddress2, ipAddress1);
|
||||
uint16_t portSwapped = EndianConverter::convertBigEndian(lastPort);
|
||||
sif::printInfo("TmTcLwIpUdpBridge: Client IP Port: %d\n", portSwapped);
|
||||
#endif
|
||||
#endif
|
||||
connectFlag = false;
|
||||
}
|
||||
connectFlag = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
|
||||
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
|
||||
/* copy data to pbuf */
|
||||
err_t err = pbuf_take(p_tx, (const char *)data, dataLen);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p_tx);
|
||||
return err;
|
||||
ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t * data, size_t dataLen) {
|
||||
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, dataLen, PBUF_RAM);
|
||||
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && (upcb != nullptr)) {
|
||||
/* copy data to pbuf */
|
||||
err_t err = pbuf_take(p_tx, (char*) data, dataLen);
|
||||
if(err!=ERR_OK){
|
||||
pbuf_free(p_tx);
|
||||
return err;
|
||||
}
|
||||
/* Connect to the remote client */
|
||||
err = udp_connect(TmTcLwIpUdpBridge::upcb, &lastAdd , lastPort);
|
||||
if(err != ERR_OK){
|
||||
pbuf_free(p_tx);
|
||||
return err;
|
||||
}
|
||||
/* Tell the client that we have accepted it */
|
||||
err = udp_send(TmTcLwIpUdpBridge::upcb, p_tx);
|
||||
pbuf_free(p_tx);
|
||||
if(err!=ERR_OK){
|
||||
return err;
|
||||
}
|
||||
|
||||
/* free the UDP connection, so we can accept new clients */
|
||||
udp_disconnect (TmTcLwIpUdpBridge::upcb);
|
||||
}
|
||||
/* Connect to the remote client */
|
||||
err = udp_connect(TmTcLwIpUdpBridge::upcb, &lastAdd, lastPort);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p_tx);
|
||||
return err;
|
||||
else{
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
/* Tell the client that we have accepted it */
|
||||
err = udp_send(TmTcLwIpUdpBridge::upcb, p_tx);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
void TmTcLwIpUdpBridge::udp_server_receive_callback(void* arg,
|
||||
struct udp_pcb* upcb_, struct pbuf* p, const ip_addr_t* addr,
|
||||
u16_t port) {
|
||||
struct pbuf *p_tx = nullptr;
|
||||
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge*>(arg);
|
||||
if(udpBridge == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!" <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!\n");
|
||||
#endif
|
||||
}
|
||||
/* allocate pbuf from RAM*/
|
||||
p_tx = pbuf_alloc(PBUF_TRANSPORT,p->len, PBUF_RAM);
|
||||
|
||||
if(p_tx != NULL)
|
||||
{
|
||||
if(udpBridge != nullptr) {
|
||||
MutexGuard lg(udpBridge->bridgeLock);
|
||||
udpBridge->upcb = upcb_;
|
||||
udpBridge->lastAdd = *addr;
|
||||
udpBridge->lastPort = port;
|
||||
if(not udpBridge->comLinkUp()) {
|
||||
udpBridge->registerCommConnect();
|
||||
#if TCPIP_RECV_WIRETAPPING == 1
|
||||
udpBridge->connectFlag = true;
|
||||
#endif
|
||||
/* This should have already been done, but we will still do it */
|
||||
udpBridge->physicalConnectStatusChange(true);
|
||||
}
|
||||
}
|
||||
pbuf_take(p_tx, (char*)p->payload, p->len);
|
||||
/* send the received data to the uart port */
|
||||
char* data = reinterpret_cast<char*>(p_tx->payload);
|
||||
*(data+p_tx->len) = '\0';
|
||||
|
||||
#if TCPIP_RECV_WIRETAPPING == 1
|
||||
udpBridge->printData(p,data);
|
||||
#endif
|
||||
|
||||
store_address_t storeId;
|
||||
ReturnValue_t returnValue = udpBridge->tcStore->addData(&storeId,
|
||||
reinterpret_cast<uint8_t*>(p->payload), p->len);
|
||||
if (returnValue != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UDP Server: Data storage failed" << std::endl;
|
||||
#endif
|
||||
pbuf_free(p_tx);
|
||||
return;
|
||||
}
|
||||
TmTcMessage message(storeId);
|
||||
if (udpBridge->tmTcReceptionQueue->sendToDefault(&message)
|
||||
!= RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcLwIpUdpBridgw::udp_server_receive_callback:"
|
||||
<< " Sending message to queue failed" << std::endl;
|
||||
#endif
|
||||
udpBridge->tcStore->deleteData(storeId);
|
||||
}
|
||||
}
|
||||
/* Free the p_tx buffer */
|
||||
pbuf_free(p_tx);
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* free the UDP connection, so we can accept new clients */
|
||||
udp_disconnect(TmTcLwIpUdpBridge::upcb);
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg, struct udp_pcb *upcb_,
|
||||
struct pbuf *p, const ip_addr_t *addr,
|
||||
u16_t port) {
|
||||
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge *>(arg);
|
||||
if (udpBridge == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid UDP bridge!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"TmTcLwIpUdpBridge::udp_server_receive_callback: Invalid "
|
||||
"UDP bridge!\n");
|
||||
#endif
|
||||
}
|
||||
/* allocate pbuf from RAM*/
|
||||
struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
|
||||
|
||||
if (p_tx != nullptr) {
|
||||
if (udpBridge != nullptr) {
|
||||
MutexGuard lg(udpBridge->bridgeLock);
|
||||
udpBridge->upcb = upcb_;
|
||||
udpBridge->lastAdd = *addr;
|
||||
udpBridge->lastPort = port;
|
||||
if (not udpBridge->comLinkUp()) {
|
||||
udpBridge->registerCommConnect();
|
||||
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
|
||||
udpBridge->connectFlag = true;
|
||||
#endif
|
||||
/* This should have already been done, but we will still do it */
|
||||
udpBridge->physicalConnectStatusChange(true);
|
||||
}
|
||||
}
|
||||
pbuf_take(p_tx, (char *)p->payload, p->len);
|
||||
/* send the received data to the uart port */
|
||||
char *data = reinterpret_cast<char *>(p_tx->payload);
|
||||
*(data + p_tx->len) = '\0';
|
||||
|
||||
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
|
||||
udpBridge->printData(reinterpret_cast<uint8_t *>(p->payload), p->len);
|
||||
#endif
|
||||
|
||||
store_address_t storeId;
|
||||
ReturnValue_t returnValue =
|
||||
udpBridge->tcStore->addData(&storeId, reinterpret_cast<uint8_t *>(p->payload), p->len);
|
||||
if (returnValue != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UDP Server: Data storage failed" << std::endl;
|
||||
#endif
|
||||
pbuf_free(p_tx);
|
||||
return;
|
||||
}
|
||||
TmTcMessage message(storeId);
|
||||
if (udpBridge->tmTcReceptionQueue->sendToDefault(&message) != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcLwIpUdpBridgw::udp_server_receive_callback:"
|
||||
<< " Sending message to queue failed" << std::endl;
|
||||
#endif
|
||||
udpBridge->tcStore->deleteData(storeId);
|
||||
}
|
||||
}
|
||||
/* Free the p_tx buffer */
|
||||
pbuf_free(p_tx);
|
||||
}
|
||||
|
||||
/* Caller must ensure thread-safety */
|
||||
bool TmTcLwIpUdpBridge::comLinkUp() const { return communicationLinkUp; }
|
||||
bool TmTcLwIpUdpBridge::comLinkUp() const {
|
||||
return communicationLinkUp;
|
||||
}
|
||||
|
||||
/* Caller must ensure thread-safety */
|
||||
void TmTcLwIpUdpBridge::physicalConnectStatusChange(bool connect) {
|
||||
if (connect) {
|
||||
/* Physical connection does not mean there is a recipient to send packets
|
||||
too. This will be done by the receive callback! */
|
||||
physicalConnection = true;
|
||||
} else {
|
||||
physicalConnection = false;
|
||||
/* If there is no physical connection, we can't send anything back */
|
||||
registerCommDisconnect();
|
||||
}
|
||||
if(connect) {
|
||||
/* Physical connection does not mean there is a recipient to send packets too.
|
||||
This will be done by the receive callback! */
|
||||
physicalConnection = true;
|
||||
}
|
||||
else {
|
||||
physicalConnection = false;
|
||||
/* If there is no physical connection, we can't send anything back */
|
||||
registerCommDisconnect();
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +1,79 @@
|
||||
#ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
|
||||
#define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
|
||||
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <fsfw/tmtcservices/TmTcBridge.h>
|
||||
|
||||
#include "commonConfig.h"
|
||||
#include "fsfw/tmtcservices/TmTcBridge.h"
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
#define TCPIP_RECV_WIRETAPPING 0
|
||||
|
||||
/**
|
||||
* This bridge is used to forward TMTC packets received via LwIP UDP to the
|
||||
* internal software bus.
|
||||
* This bridge is used to forward TMTC packets received via LwIP UDP to the internal software bus.
|
||||
*/
|
||||
class TmTcLwIpUdpBridge : public TmTcBridge {
|
||||
friend class UdpTcLwIpPollingTask;
|
||||
friend class UdpTcLwIpPollingTask;
|
||||
public:
|
||||
TmTcLwIpUdpBridge(object_id_t objectId,
|
||||
object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
|
||||
object_id_t tcStoreId);
|
||||
virtual ~TmTcLwIpUdpBridge();
|
||||
|
||||
public:
|
||||
TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, object_id_t tmStoreId,
|
||||
object_id_t tcStoreId);
|
||||
~TmTcLwIpUdpBridge() override;
|
||||
virtual ReturnValue_t initialize() override;
|
||||
ReturnValue_t udp_server_init();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t udp_server_init();
|
||||
/**
|
||||
* In addition to default implementation, ethernet link status is checked.
|
||||
* @param operationCode
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
|
||||
/**
|
||||
* In addition to default implementation, ethernet link status is checked.
|
||||
* @param operationCode
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
/** TM Send implementation uses udp_send function from lwIP stack
|
||||
* @param data
|
||||
* @param dataLen
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
||||
|
||||
/** TM Send implementation uses udp_send function from lwIP stack
|
||||
* @param data
|
||||
* @param dataLen
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override;
|
||||
/**
|
||||
* @brief This function is called when an UDP datagram has been
|
||||
* received on the port UDP_PORT.
|
||||
* @param arg
|
||||
* @param upcb_
|
||||
* @param p
|
||||
* @param addr Source address which will be bound to TmTcUdpBridge::lastAdd
|
||||
* @param port
|
||||
*/
|
||||
static void udp_server_receive_callback(void *arg,
|
||||
struct udp_pcb *upcb_, struct pbuf *p, const ip_addr_t *addr,
|
||||
u16_t port);
|
||||
|
||||
/**
|
||||
* @brief This function is called when an UDP datagram has been
|
||||
* received on the port UDP_PORT.
|
||||
* @param arg
|
||||
* @param upcb_
|
||||
* @param p
|
||||
* @param addr Source address which will be bound to TmTcUdpBridge::lastAdd
|
||||
* @param port
|
||||
*/
|
||||
static void udp_server_receive_callback(void *arg, struct udp_pcb *upcb_, struct pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port);
|
||||
/**
|
||||
* Check whether the communication link is up.
|
||||
* Caller must ensure thread-safety by using the bridge lock.
|
||||
* @return
|
||||
*/
|
||||
bool comLinkUp() const;
|
||||
|
||||
/**
|
||||
* Check whether the communication link is up.
|
||||
* Caller must ensure thread-safety by using the bridge lock.
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] bool comLinkUp() const;
|
||||
private:
|
||||
struct udp_pcb *upcb = nullptr;
|
||||
ip_addr_t lastAdd;
|
||||
u16_t lastPort = 0;
|
||||
bool physicalConnection = false;
|
||||
MutexIF* bridgeLock = nullptr;
|
||||
|
||||
private:
|
||||
struct udp_pcb *upcb = nullptr;
|
||||
ip_addr_t lastAdd{};
|
||||
u16_t lastPort = 0;
|
||||
bool physicalConnection = false;
|
||||
MutexIF *bridgeLock = nullptr;
|
||||
|
||||
#if OBSW_TCPIP_UDP_WIRETAPPING == 1
|
||||
bool connectFlag = false;
|
||||
#if TCPIP_RECV_WIRETAPPING == 1
|
||||
bool connectFlag = false;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Used to notify bridge about change in the physical ethernet connection.
|
||||
* Connection does not mean that replies are possible (recipient not set yet),
|
||||
* but disconnect means that we can't send anything. Caller must ensure
|
||||
* thread-safety by using the bridge lock.
|
||||
*/
|
||||
void physicalConnectStatusChange(bool connect);
|
||||
/**
|
||||
* Used to notify bridge about change in the physical ethernet connection.
|
||||
* Connection does not mean that replies are possible (recipient not set yet), but
|
||||
* disconnect means that we can't send anything. Caller must ensure thread-safety
|
||||
* by using the bridge lock.
|
||||
*/
|
||||
void physicalConnectStatusChange(bool connect);
|
||||
};
|
||||
|
||||
#endif /* BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ */
|
||||
|
@ -1,58 +1,66 @@
|
||||
#include "UdpTcLwIpPollingTask.h"
|
||||
|
||||
#include "TmTcLwIpUdpBridge.h"
|
||||
#include "app_dhcp.h"
|
||||
#include "app_ethernet.h"
|
||||
#include "ethernetif.h"
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "app_dhcp.h"
|
||||
#include "networking.h"
|
||||
#include <hardware_init.h>
|
||||
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
|
||||
|
||||
#include "lwip/timeouts.h"
|
||||
|
||||
UdpTcLwIpPollingTask::UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId,
|
||||
struct netif *gnetif)
|
||||
: SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) {}
|
||||
struct netif* gnetif):
|
||||
SystemObject(objectId), periodicHandleCounter(0), bridgeId(bridgeId), gnetif(gnetif) {
|
||||
}
|
||||
|
||||
UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() = default;
|
||||
UdpTcLwIpPollingTask::~UdpTcLwIpPollingTask() {
|
||||
}
|
||||
|
||||
ReturnValue_t UdpTcLwIpPollingTask::initialize() {
|
||||
udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId);
|
||||
if (udpBridge == nullptr) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
if (netif_is_link_up(gnetif)) {
|
||||
networking::setEthCableConnected(true);
|
||||
}
|
||||
return RETURN_OK;
|
||||
udpBridge = ObjectManager::instance()->get<TmTcLwIpUdpBridge>(bridgeId);
|
||||
if(udpBridge == nullptr) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
if (netif_is_link_up(gnetif)) {
|
||||
networking::setEthCableConnected(true);
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Poll the EMAC Interface and pass content to the network interface (lwIP) */
|
||||
ReturnValue_t UdpTcLwIpPollingTask::performOperation(uint8_t operationCode) {
|
||||
/* Read a received packet from the Ethernet buffers and send it
|
||||
to the lwIP for handling */
|
||||
ethernetif_input(gnetif);
|
||||
/* Read a received packet from the Ethernet buffers and send it
|
||||
to the lwIP for handling */
|
||||
ethernetif_input(gnetif);
|
||||
|
||||
/* Handle timeouts */
|
||||
sys_check_timeouts();
|
||||
/* Handle timeouts */
|
||||
sys_check_timeouts();
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK == 1
|
||||
networking::ethernetLinkPeriodicHandle(gnetif);
|
||||
networking::ethernetLinkPeriodicHandle(gnetif);
|
||||
#endif
|
||||
|
||||
if (udpBridge != nullptr) {
|
||||
MutexGuard lg(udpBridge->bridgeLock);
|
||||
/* In case ethernet cable is disconnected */
|
||||
if (not networking::getEthCableConnected() and udpBridge->comLinkUp()) {
|
||||
udpBridge->physicalConnectStatusChange(false);
|
||||
} else if (networking::getEthCableConnected() and not udpBridge->comLinkUp()) {
|
||||
udpBridge->physicalConnectStatusChange(true);
|
||||
if(udpBridge != nullptr) {
|
||||
MutexGuard lg(udpBridge->bridgeLock);
|
||||
/* In case ethernet cable is disconnected */
|
||||
if(not networking::getEthCableConnected() and udpBridge->comLinkUp()) {
|
||||
udpBridge->physicalConnectStatusChange(false);
|
||||
}
|
||||
else if(networking::getEthCableConnected() and not udpBridge->comLinkUp()) {
|
||||
udpBridge->physicalConnectStatusChange(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_DHCP == 1
|
||||
DHCP_Periodic_Handle(gnetif);
|
||||
DHCP_Periodic_Handle(gnetif);
|
||||
#endif
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#ifndef BSP_STM32_RTEMS_EMACPOLLINGTASK_H_
|
||||
#define BSP_STM32_RTEMS_EMACPOLLINGTASK_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <lwip/netif.h>
|
||||
|
||||
class TmTcLwIpUdpBridge;
|
||||
@ -11,26 +13,29 @@ class TmTcLwIpUdpBridge;
|
||||
* @brief Separate task to poll EMAC interface.
|
||||
* Polled data is passed to the netif (lwIP)
|
||||
*/
|
||||
class UdpTcLwIpPollingTask : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif *gnetif);
|
||||
~UdpTcLwIpPollingTask() override;
|
||||
class UdpTcLwIpPollingTask:
|
||||
public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
UdpTcLwIpPollingTask(object_id_t objectId, object_id_t bridgeId, struct netif* gnetif);
|
||||
virtual ~UdpTcLwIpPollingTask();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* Executed periodically.
|
||||
* @param operationCode
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
|
||||
private:
|
||||
static const uint8_t PERIODIC_HANDLE_TRIGGER = 5;
|
||||
uint8_t periodicHandleCounter;
|
||||
object_id_t bridgeId = 0;
|
||||
TmTcLwIpUdpBridge *udpBridge = nullptr;
|
||||
struct netif *gnetif = nullptr;
|
||||
/**
|
||||
* Executed periodically.
|
||||
* @param operationCode
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
private:
|
||||
static const uint8_t PERIODIC_HANDLE_TRIGGER = 5;
|
||||
uint8_t periodicHandleCounter;
|
||||
object_id_t bridgeId = 0;
|
||||
TmTcLwIpUdpBridge* udpBridge = nullptr;
|
||||
struct netif* gnetif = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif /* BSP_STM32_RTEMS_EMACPOLLINGTASK_H_ */
|
||||
|
@ -1,76 +1,80 @@
|
||||
#include "app_dhcp.h"
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "lwip/dhcp.h"
|
||||
|
||||
#include "app_dhcp.h"
|
||||
#include "app_ethernet.h"
|
||||
#include "networking.h"
|
||||
#include "stm32h7xx_nucleo.h"
|
||||
#include "udp_config.h"
|
||||
#include "ethernetif.h"
|
||||
|
||||
#include "lwip/dhcp.h"
|
||||
#include "stm32h7xx_nucleo.h"
|
||||
|
||||
#if LWIP_DHCP == 1
|
||||
|
||||
uint8_t DHCP_state = DHCP_OFF;
|
||||
uint32_t DHCPfineTimer = 0;
|
||||
|
||||
void handle_dhcp_timeout(struct netif *netif);
|
||||
void handle_dhcp_start(struct netif *netif);
|
||||
void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp);
|
||||
void handle_dhcp_down(struct netif *netif);
|
||||
void handle_dhcp_timeout(struct netif* netif);
|
||||
void handle_dhcp_start(struct netif* netif);
|
||||
void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp);
|
||||
void handle_dhcp_down(struct netif* netif);
|
||||
|
||||
/**
|
||||
* @brief DHCP_Process_Handle
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void DHCP_Process(struct netif *netif) {
|
||||
struct dhcp *dhcp = nullptr;
|
||||
switch (DHCP_state) {
|
||||
void DHCP_Process(struct netif *netif)
|
||||
{
|
||||
struct dhcp* dhcp = NULL;
|
||||
switch (DHCP_state) {
|
||||
case DHCP_START: {
|
||||
handle_dhcp_start(netif);
|
||||
break;
|
||||
handle_dhcp_start(netif);
|
||||
break;
|
||||
}
|
||||
case DHCP_WAIT_ADDRESS: {
|
||||
handle_dhcp_wait(netif, &dhcp);
|
||||
break;
|
||||
handle_dhcp_wait(netif, &dhcp);
|
||||
break;
|
||||
}
|
||||
|
||||
case DHCP_LINK_DOWN: {
|
||||
handle_dhcp_down(netif);
|
||||
break;
|
||||
handle_dhcp_down(netif);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_dhcp_timeout(struct netif *netif) {
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gw;
|
||||
void handle_dhcp_timeout(struct netif* netif) {
|
||||
ip_addr_t ipaddr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gw;
|
||||
|
||||
DHCP_state = DHCP_TIMEOUT;
|
||||
DHCP_state = DHCP_TIMEOUT;
|
||||
|
||||
/* Stop DHCP */
|
||||
dhcp_stop(netif);
|
||||
/* Stop DHCP */
|
||||
dhcp_stop(netif);
|
||||
|
||||
/* Static address used */
|
||||
networking::setLwipAddresses(&ipaddr, &netmask, &gw);
|
||||
netif_set_addr(netif, &ipaddr, &netmask, &gw);
|
||||
/* Static address used */
|
||||
networking::setLwipAddresses(&ipaddr, &netmask, &gw);
|
||||
netif_set_addr(netif, &ipaddr, &netmask, &gw);
|
||||
|
||||
printf("DHCP Timeout\n\r");
|
||||
uint8_t iptxt[20];
|
||||
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("Assigning static IP address: %s\n", iptxt);
|
||||
printf("DHCP Timeout\n\r");
|
||||
uint8_t iptxt[20];
|
||||
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("Assigning static IP address: %s\n", iptxt);
|
||||
|
||||
#if defined FSFW_OSAL_FREERTOS
|
||||
ETH_HandleTypeDef *handle = getEthernetHandle();
|
||||
handle->gState = HAL_ETH_STATE_READY;
|
||||
ETH_HandleTypeDef* handle = getEthernetHandle();
|
||||
handle->gState = HAL_ETH_STATE_READY;
|
||||
#endif
|
||||
|
||||
#if OBSW_ETHERNET_TMTC_COMMANDING == 1
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -80,69 +84,74 @@ void handle_dhcp_timeout(struct netif *netif) {
|
||||
* @param netif
|
||||
* @retval None
|
||||
*/
|
||||
void DHCP_Periodic_Handle(struct netif *netif) {
|
||||
/* Fine DHCP periodic process every 500ms */
|
||||
if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
|
||||
DHCPfineTimer = HAL_GetTick();
|
||||
/* process DHCP state machine */
|
||||
DHCP_Process(netif);
|
||||
}
|
||||
void DHCP_Periodic_Handle(struct netif *netif)
|
||||
{
|
||||
/* Fine DHCP periodic process every 500ms */
|
||||
if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
|
||||
DHCPfineTimer = HAL_GetTick();
|
||||
/* process DHCP state machine */
|
||||
DHCP_Process(netif);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_dhcp_start(struct netif *netif) {
|
||||
printf("handle_dhcp_start: Looking for DHCP server ...\n\r");
|
||||
void handle_dhcp_start(struct netif* netif) {
|
||||
printf("handle_dhcp_start: Looking for DHCP server ...\n\r");
|
||||
#if OBSW_ETHERNET_TMTC_COMMANDING == 1
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
#endif
|
||||
#endif
|
||||
ip_addr_set_zero_ip4(&netif->ip_addr);
|
||||
ip_addr_set_zero_ip4(&netif->netmask);
|
||||
ip_addr_set_zero_ip4(&netif->gw);
|
||||
dhcp_start(netif);
|
||||
DHCP_state = DHCP_WAIT_ADDRESS;
|
||||
}
|
||||
|
||||
void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp) {
|
||||
if (dhcp_supplied_address(netif)) {
|
||||
DHCP_state = DHCP_ADDRESS_ASSIGNED;
|
||||
printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("Listener port: %d\n\r", UDP_SERVER_PORT);
|
||||
#if OBSW_ETHERNET_TMTC_COMMANDING == 1
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
*dhcp =
|
||||
static_cast<struct dhcp *>(netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP));
|
||||
|
||||
/* DHCP timeout */
|
||||
if ((*dhcp)->tries > MAX_DHCP_TRIES) {
|
||||
handle_dhcp_timeout(netif);
|
||||
}
|
||||
}
|
||||
ip_addr_set_zero_ip4(&netif->ip_addr);
|
||||
ip_addr_set_zero_ip4(&netif->netmask);
|
||||
ip_addr_set_zero_ip4(&netif->gw);
|
||||
dhcp_start(netif);
|
||||
DHCP_state = DHCP_WAIT_ADDRESS;
|
||||
}
|
||||
|
||||
void handle_dhcp_down(struct netif *netif) {
|
||||
static_cast<void>(netif);
|
||||
DHCP_state = DHCP_OFF;
|
||||
void handle_dhcp_wait(struct netif* netif, struct dhcp** dhcp) {
|
||||
if (dhcp_supplied_address(netif)) {
|
||||
DHCP_state = DHCP_ADDRESS_ASSIGNED;
|
||||
printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("Listener port: %d\n\r", UDP_SERVER_PORT);
|
||||
#if OBSW_ETHERNET_TMTC_COMMANDING == 1
|
||||
printf("DHCP_Process: The network cable is not connected.\n\r");
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_On(LED2);
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*dhcp = (struct dhcp*) netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
|
||||
|
||||
/* Global boolean to track ethernet connection */
|
||||
networking::setEthCableConnected(false);
|
||||
/* DHCP timeout */
|
||||
if ((*dhcp)->tries > MAX_DHCP_TRIES)
|
||||
{
|
||||
handle_dhcp_timeout(netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t get_dhcp_state() { return DHCP_state; }
|
||||
void handle_dhcp_down(struct netif* netif) {
|
||||
DHCP_state = DHCP_OFF;
|
||||
#if OBSW_ETHERNET_TMTC_COMMANDING == 1
|
||||
printf("DHCP_Process: The network cable is not connected.\n\r");
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_On(LED2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void set_dhcp_state(uint8_t new_state) { DHCP_state = new_state; }
|
||||
/* Global boolean to track ethernet connection */
|
||||
networking::setEthCableConnected(false);
|
||||
}
|
||||
|
||||
uint8_t get_dhcp_state() {
|
||||
return DHCP_state;
|
||||
}
|
||||
|
||||
void set_dhcp_state(uint8_t new_state) {
|
||||
DHCP_state = new_state;
|
||||
}
|
||||
|
||||
#endif /* LWIP_DHCP == 1 */
|
||||
|
@ -12,12 +12,12 @@ extern "C" {
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/* DHCP process states */
|
||||
#define DHCP_OFF (uint8_t)0
|
||||
#define DHCP_START (uint8_t)1
|
||||
#define DHCP_WAIT_ADDRESS (uint8_t)2
|
||||
#define DHCP_ADDRESS_ASSIGNED (uint8_t)3
|
||||
#define DHCP_TIMEOUT (uint8_t)4
|
||||
#define DHCP_LINK_DOWN (uint8_t)5
|
||||
#define DHCP_OFF (uint8_t) 0
|
||||
#define DHCP_START (uint8_t) 1
|
||||
#define DHCP_WAIT_ADDRESS (uint8_t) 2
|
||||
#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3
|
||||
#define DHCP_TIMEOUT (uint8_t) 4
|
||||
#define DHCP_LINK_DOWN (uint8_t) 5
|
||||
|
||||
uint8_t get_dhcp_state();
|
||||
void set_dhcp_state(uint8_t new_state);
|
||||
|
@ -1,18 +1,17 @@
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_ethernet.h"
|
||||
|
||||
#include "ethernetif.h"
|
||||
#include "networking.h"
|
||||
#include "udp_config.h"
|
||||
#include "networking.h"
|
||||
|
||||
#if LWIP_DHCP
|
||||
#include "app_dhcp.h"
|
||||
#endif
|
||||
|
||||
#include <OBSWConfig.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwipopts.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <stm32h7xx_nucleo.h>
|
||||
#include <OBSWConfig.h>
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
@ -21,7 +20,8 @@
|
||||
uint32_t ethernetLinkTimer = 0;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void handle_status_change(struct netif *netif, bool link_up);
|
||||
void handle_status_change(struct netif* netif, bool link_up);
|
||||
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
@ -29,43 +29,48 @@ void handle_status_change(struct netif *netif, bool link_up);
|
||||
* @param netif: the network interface
|
||||
* @retval None
|
||||
*/
|
||||
void networking::ethernetLinkStatusUpdated(struct netif *netif) {
|
||||
if (netif_is_link_up(netif)) {
|
||||
networking::setEthCableConnected(true);
|
||||
handle_status_change(netif, true);
|
||||
} else {
|
||||
networking::setEthCableConnected(false);
|
||||
handle_status_change(netif, false);
|
||||
}
|
||||
void networking::ethernetLinkStatusUpdated(struct netif *netif)
|
||||
{
|
||||
if (netif_is_link_up(netif))
|
||||
{
|
||||
networking::setEthCableConnected(true);
|
||||
handle_status_change(netif, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
networking::setEthCableConnected(false);
|
||||
handle_status_change(netif, false);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_status_change(struct netif *netif, bool link_up) {
|
||||
if (link_up) {
|
||||
void handle_status_change(struct netif* netif, bool link_up) {
|
||||
if(link_up) {
|
||||
#if LWIP_DHCP
|
||||
/* Update DHCP state machine */
|
||||
set_dhcp_state(DHCP_START);
|
||||
/* Update DHCP state machine */
|
||||
set_dhcp_state(DHCP_START);
|
||||
#else
|
||||
uint8_t iptxt[20];
|
||||
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt,
|
||||
UDP_SERVER_PORT);
|
||||
uint8_t iptxt[20];
|
||||
sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
printf("\rNetwork cable connected. Static IP address: %s | Port: %d\n\r", iptxt,
|
||||
UDP_SERVER_PORT);
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
BSP_LED_On(LED1);
|
||||
BSP_LED_Off(LED2);
|
||||
#endif
|
||||
#endif /* LWIP_DHCP */
|
||||
} else {
|
||||
printf("Network cable disconnected\n\r");
|
||||
}
|
||||
else {
|
||||
printf("Network cable disconnected\n\r");
|
||||
#if LWIP_DHCP
|
||||
/* Update DHCP state machine */
|
||||
set_dhcp_state(DHCP_LINK_DOWN);
|
||||
/* Update DHCP state machine */
|
||||
set_dhcp_state(DHCP_LINK_DOWN);
|
||||
#else
|
||||
#if OBSW_ETHERNET_USE_LED1_LED2 == 1
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_On(LED2);
|
||||
BSP_LED_Off(LED1);
|
||||
BSP_LED_On(LED2);
|
||||
#endif
|
||||
#endif /* LWIP_DHCP */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
@ -75,12 +80,14 @@ void handle_status_change(struct netif *netif, bool link_up) {
|
||||
* @param netif
|
||||
* @retval None
|
||||
*/
|
||||
void networking::ethernetLinkPeriodicHandle(struct netif *netif) {
|
||||
/* Ethernet Link every 100ms */
|
||||
if (HAL_GetTick() - ethernetLinkTimer >= 100) {
|
||||
ethernetLinkTimer = HAL_GetTick();
|
||||
ethernet_link_check_state(netif);
|
||||
}
|
||||
void networking::ethernetLinkPeriodicHandle(struct netif *netif)
|
||||
{
|
||||
/* Ethernet Link every 100ms */
|
||||
if (HAL_GetTick() - ethernetLinkTimer >= 100)
|
||||
{
|
||||
ethernetLinkTimer = HAL_GetTick();
|
||||
ethernet_link_check_state(netif);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||
|
@ -1,54 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_UDP_Echo_Client/Inc/app_ethernet.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for app_ethernet.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_UDP_Echo_Client/Inc/app_ethernet.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for app_ethernet.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef EXAMPLE_COMMON_APP_ETHERNET_H
|
||||
#define EXAMPLE_COMMON_APP_ETHERNET_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
@ -65,7 +65,7 @@ namespace networking {
|
||||
void ethernetLinkStatusUpdated(struct netif *netif);
|
||||
void ethernetLinkPeriodicHandle(struct netif *netif);
|
||||
|
||||
} // namespace networking
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -73,4 +73,6 @@ void ethernetLinkPeriodicHandle(struct netif *netif);
|
||||
|
||||
#endif /* EXAMPLE_COMMON_APP_ETHERNET_H */
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
@ -1,61 +1,58 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file implements Ethernet network interface drivers for lwIP
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_UDP_Echo_Client/Src/ethernetif.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file implements Ethernet network interface drivers for lwIP
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "ethernetif.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "lan8742.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "stm32h7xx_hal.h"
|
||||
#include <lan8742.h>
|
||||
#include <stm32h7xx_hal.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/opt.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <netif/etharp.h>
|
||||
|
||||
#ifdef FSFW_OSAL_RTEMS
|
||||
#include <rtems.h>
|
||||
@ -67,166 +64,142 @@
|
||||
#define IFNAME0 's'
|
||||
#define IFNAME1 't'
|
||||
|
||||
#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
|
||||
|
||||
#define ETH_RX_BUFFER_SIZE 1536U
|
||||
#define ETH_RX_BUFFER_CNT 12U
|
||||
#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT)*2U)
|
||||
|
||||
#define DMA_DESCRIPTOR_ALIGNMENT 0x20
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/*
|
||||
/*
|
||||
@Note: This interface is implemented to operate in zero-copy mode only:
|
||||
- Rx buffers are allocated statically and passed directly to the LwIP
|
||||
stack they will return back to DMA after been processed by the stack.
|
||||
- Tx Buffers will be allocated from LwIP stack memory heap,
|
||||
- Rx buffers are allocated statically and passed directly to the LwIP stack
|
||||
they will return back to DMA after been processed by the stack.
|
||||
- Tx Buffers will be allocated from LwIP stack memory heap,
|
||||
then passed to ETH HAL driver.
|
||||
|
||||
@Notes:
|
||||
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
|
||||
@Notes:
|
||||
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
|
||||
to customize it please redefine ETH_RX_DESC_CNT in stm32xxxx_hal_conf.h
|
||||
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
|
||||
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
|
||||
to customize it please redefine ETH_TX_DESC_CNT in stm32xxxx_hal_conf.h
|
||||
|
||||
2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
|
||||
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
|
||||
passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
|
||||
*/
|
||||
typedef enum { RX_ALLOC_OK = 0x00, RX_ALLOC_ERROR = 0x01 } RxAllocStatusTypeDef;
|
||||
|
||||
typedef struct {
|
||||
struct pbuf_custom pbuf_custom;
|
||||
uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
|
||||
} RxBuff_t;
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
|
||||
#if defined(__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma location=0x30040000
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
#pragma location=0x30040060
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
#pragma location=0x30040200
|
||||
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
|
||||
|
||||
#pragma location = 0x30000000
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
#pragma location = 0x30000200
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
|
||||
|
||||
#elif defined(__CC_ARM) /* MDK ARM Compiler */
|
||||
__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
__attribute__((section(".RxArraySection"))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
|
||||
|
||||
__attribute__((section(".RxDecripSection")))
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
|
||||
__attribute__((section(".TxDecripSection")))
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
|
||||
|
||||
#elif defined(__GNUC__) /* GNU Compiler */
|
||||
#elif defined ( __GNUC__ ) /* GNU Compiler */
|
||||
|
||||
#ifdef FSFW_OSAL_RTEMS
|
||||
/* Put into special RTEMS section and align correctly */
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
|
||||
__attribute__((section(".bsp_nocache"),
|
||||
__aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Rx DMA Descriptors */
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Rx DMA Descriptors */
|
||||
/* Put into special RTEMS section and align correctly */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
|
||||
__attribute__((section(".bsp_nocache"),
|
||||
__aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */
|
||||
/* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely
|
||||
* placing it */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Tx DMA Descriptors */
|
||||
/* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely placing it */
|
||||
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
|
||||
#elif defined FSFW_OSAL_FREERTOS
|
||||
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]
|
||||
__attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]
|
||||
__attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
|
||||
|
||||
#endif /* FSFW_OSAL_RTEMS */
|
||||
/* Placement and alignment specified in linker script here */
|
||||
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
|
||||
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
|
||||
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
|
||||
#endif /* FSFW_FREERTOS */
|
||||
|
||||
#endif /* defined ( __GNUC__ ) */
|
||||
|
||||
/* Memory Pool Declaration */
|
||||
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
|
||||
|
||||
#if defined(__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma location = 0x30000400
|
||||
extern u8_t memp_memory_RX_POOL_base[];
|
||||
|
||||
#elif defined(__CC_ARM) /* MDK ARM Compiler */
|
||||
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
|
||||
|
||||
#elif defined(__GNUC__) /* GNU Compiler */
|
||||
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
|
||||
|
||||
#endif
|
||||
|
||||
/* Global boolean to track ethernet connection */
|
||||
bool ethernet_cable_connected;
|
||||
|
||||
/* Variable Definitions */
|
||||
static uint8_t RxAllocStatus;
|
||||
struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT];
|
||||
uint32_t current_pbuf_idx =0;
|
||||
|
||||
/* Global Ethernet handle*/
|
||||
ETH_HandleTypeDef EthHandle;
|
||||
ETH_TxPacketConfig TxConfig;
|
||||
ETH_TxPacketConfig TxConfig;
|
||||
|
||||
lan8742_Object_t LAN8742;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
u32_t sys_now(void);
|
||||
extern void Error_Handler(void);
|
||||
void pbuf_free_custom(struct pbuf *p);
|
||||
|
||||
int32_t ETH_PHY_IO_Init(void);
|
||||
int32_t ETH_PHY_IO_DeInit(void);
|
||||
int32_t ETH_PHY_IO_DeInit (void);
|
||||
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
|
||||
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
|
||||
int32_t ETH_PHY_IO_GetTick(void);
|
||||
|
||||
lan8742_Object_t LAN8742;
|
||||
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg,
|
||||
ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick};
|
||||
|
||||
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
|
||||
ETH_PHY_IO_DeInit,
|
||||
ETH_PHY_IO_WriteReg,
|
||||
ETH_PHY_IO_ReadReg,
|
||||
ETH_PHY_IO_GetTick};
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
void pbuf_free_custom(struct pbuf *p);
|
||||
/*******************************************************************************
|
||||
LL Driver Interface ( LwIP stack --> ETH)
|
||||
LL Driver Interface ( LwIP stack --> ETH)
|
||||
*******************************************************************************/
|
||||
/**
|
||||
* @brief In this function, the hardware should be initialized.
|
||||
* Called from ethernetif_init().
|
||||
*
|
||||
* @param netif the already initialized lwip network interface structure
|
||||
* for this ethernetif
|
||||
*/
|
||||
static void low_level_init(struct netif *netif) {
|
||||
uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2,
|
||||
ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
|
||||
|
||||
EthHandle.Instance = ETH;
|
||||
* @brief In this function, the hardware should be initialized.
|
||||
* Called from ethernetif_init().
|
||||
*
|
||||
* @param netif the already initialized lwip network interface structure
|
||||
* for this ethernetif
|
||||
*/
|
||||
static void low_level_init(struct netif *netif)
|
||||
{
|
||||
uint32_t idx = 0;
|
||||
uint8_t macaddress[6]= {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
|
||||
|
||||
EthHandle.Instance = ETH;
|
||||
EthHandle.Init.MACAddr = macaddress;
|
||||
EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
|
||||
EthHandle.Init.RxDesc = DMARxDscrTab;
|
||||
EthHandle.Init.TxDesc = DMATxDscrTab;
|
||||
EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
|
||||
|
||||
|
||||
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
|
||||
HAL_ETH_Init(&EthHandle);
|
||||
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = ETH_HWADDR_LEN;
|
||||
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr[0] = ETH_MAC_ADDR0;
|
||||
netif->hwaddr[1] = ETH_MAC_ADDR1;
|
||||
netif->hwaddr[2] = ETH_MAC_ADDR2;
|
||||
netif->hwaddr[3] = ETH_MAC_ADDR3;
|
||||
netif->hwaddr[4] = ETH_MAC_ADDR4;
|
||||
netif->hwaddr[5] = ETH_MAC_ADDR5;
|
||||
|
||||
netif->hwaddr[0] = 0x02;
|
||||
netif->hwaddr[1] = 0x00;
|
||||
netif->hwaddr[2] = 0x00;
|
||||
netif->hwaddr[3] = 0x00;
|
||||
netif->hwaddr[4] = 0x00;
|
||||
netif->hwaddr[5] = 0x00;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = ETH_MAX_PAYLOAD;
|
||||
|
||||
|
||||
/* device capabilities */
|
||||
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
|
||||
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
||||
/* Initialize the RX POOL */
|
||||
LWIP_MEMPOOL_INIT(RX_POOL);
|
||||
|
||||
|
||||
for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
|
||||
{
|
||||
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
|
||||
|
||||
/* Set Custom pbuf free function */
|
||||
rx_pbuf[idx].custom_free_function = pbuf_free_custom;
|
||||
}
|
||||
|
||||
/* Set Tx packet config common parameters */
|
||||
memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
|
||||
memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
|
||||
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
|
||||
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
|
||||
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
|
||||
@ -238,114 +211,152 @@ static void low_level_init(struct netif *netif) {
|
||||
LAN8742_Init(&LAN8742);
|
||||
|
||||
ethernet_link_check_state(netif);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function should do the actual transmission of the packet. The
|
||||
* packet is contained in the pbuf that is passed to the function. This pbuf
|
||||
* might be chained.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and
|
||||
* type)
|
||||
* @return ERR_OK if the packet could be sent
|
||||
* an err_t value if the packet couldn't be sent
|
||||
*
|
||||
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
||||
* strange results. You might consider waiting for space in the DMA queue
|
||||
* to become availale since the stack doesn't retry to send a packet
|
||||
* dropped because of memory failure (except for the TCP timers).
|
||||
*/
|
||||
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
|
||||
uint32_t i = 0U;
|
||||
struct pbuf *q = NULL;
|
||||
* @brief This function should do the actual transmission of the packet. The packet is
|
||||
* contained in the pbuf that is passed to the function. This pbuf
|
||||
* might be chained.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
||||
* @return ERR_OK if the packet could be sent
|
||||
* an err_t value if the packet couldn't be sent
|
||||
*
|
||||
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
||||
* strange results. You might consider waiting for space in the DMA queue
|
||||
* to become availale since the stack doesn't retry to send a packet
|
||||
* dropped because of memory failure (except for the TCP timers).
|
||||
*/
|
||||
static err_t low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
uint32_t i=0, framelen = 0;
|
||||
struct pbuf *q;
|
||||
err_t errval = ERR_OK;
|
||||
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};
|
||||
|
||||
memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
if (i >= ETH_TX_DESC_CNT) return ERR_IF;
|
||||
|
||||
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
|
||||
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
if(i >= ETH_TX_DESC_CNT)
|
||||
return ERR_IF;
|
||||
|
||||
Txbuffer[i].buffer = q->payload;
|
||||
Txbuffer[i].len = q->len;
|
||||
|
||||
if (i > 0) {
|
||||
Txbuffer[i - 1].next = &Txbuffer[i];
|
||||
framelen += q->len;
|
||||
|
||||
if(i>0)
|
||||
{
|
||||
Txbuffer[i-1].next = &Txbuffer[i];
|
||||
}
|
||||
|
||||
if (q->next == NULL) {
|
||||
|
||||
if(q->next == NULL)
|
||||
{
|
||||
Txbuffer[i].next = NULL;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
TxConfig.Length = p->tot_len;
|
||||
TxConfig.Length = framelen;
|
||||
TxConfig.TxBuffer = Txbuffer;
|
||||
TxConfig.pData = p;
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
|
||||
if (ret != HAL_OK) {
|
||||
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
|
||||
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20);
|
||||
|
||||
if(ret != HAL_OK) {
|
||||
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", ret);
|
||||
}
|
||||
|
||||
return errval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf *low_level_input(struct netif *netif) {
|
||||
* @brief Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf * low_level_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
ETH_BufferTypeDef RxBuff;
|
||||
uint32_t framelength = 0;
|
||||
|
||||
if (RxAllocStatus == RX_ALLOC_OK) {
|
||||
HAL_ETH_ReadData(&EthHandle, (void **)&p);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is the ethernetif_input task, it is processed when a
|
||||
* packet is ready to be read from the interface. It uses the function
|
||||
* low_level_input() that should handle the actual reception of bytes from the
|
||||
* network interface. Then the type of the received packet is determined and the
|
||||
* appropriate input function is called.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
*/
|
||||
void ethernetif_input(struct netif *netif) {
|
||||
struct pbuf *p = NULL;
|
||||
|
||||
do {
|
||||
p = low_level_input(netif);
|
||||
if (p != NULL) {
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
if (HAL_ETH_IsRxDataAvailable(&EthHandle))
|
||||
{
|
||||
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff);
|
||||
HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
|
||||
|
||||
/* Invalidate data cache for ETH Rx Buffers */
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff, (ETH_RX_DESC_CNT*ETH_RX_BUFFER_SIZE));
|
||||
|
||||
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_POOL, &rx_pbuf[current_pbuf_idx], RxBuff.buffer, ETH_RX_BUFFER_SIZE);
|
||||
if(current_pbuf_idx < (ETH_RX_DESC_CNT -1))
|
||||
{
|
||||
current_pbuf_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_pbuf_idx = 0;
|
||||
}
|
||||
|
||||
} while (p != NULL);
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Should be called at the beginning of the program to set up the
|
||||
* network interface. It calls the function low_level_init() to do the
|
||||
* actual setup of the hardware.
|
||||
*
|
||||
* This function should be passed as a parameter to netif_add().
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return ERR_OK if the loopif is initialized
|
||||
* ERR_MEM if private data couldn't be allocated
|
||||
* any other err_t on error
|
||||
*/
|
||||
err_t ethernetif_init(struct netif *netif) {
|
||||
* @brief This function is the ethernetif_input task, it is processed when a packet
|
||||
* is ready to be read from the interface. It uses the function low_level_input()
|
||||
* that should handle the actual reception of bytes from the network
|
||||
* interface. Then the type of the received packet is determined and
|
||||
* the appropriate input function is called.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
*/
|
||||
void ethernetif_input(struct netif *netif)
|
||||
{
|
||||
err_t err;
|
||||
struct pbuf *p;
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
p = low_level_input(netif);
|
||||
|
||||
/* no packet could be read, silently ignore this */
|
||||
if (p == NULL) return;
|
||||
|
||||
/* entry point to the LwIP stack */
|
||||
err = netif->input(p, netif);
|
||||
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
HAL_ETH_BuildRxDescriptors(&EthHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Should be called at the beginning of the program to set up the
|
||||
* network interface. It calls the function low_level_init() to do the
|
||||
* actual setup of the hardware.
|
||||
*
|
||||
* This function should be passed as a parameter to netif_add().
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return ERR_OK if the loopif is initialized
|
||||
* ERR_MEM if private data couldn't be allocated
|
||||
* any other err_t on error
|
||||
*/
|
||||
err_t ethernetif_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
@ -355,7 +366,6 @@ err_t ethernetif_init(struct netif *netif) {
|
||||
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
|
||||
/* We directly use etharp_output() here to save a function call.
|
||||
* You can instead declare your own function an call etharp_output()
|
||||
* from it if you have to do some checks before sending (e.g. if link
|
||||
@ -370,49 +380,54 @@ err_t ethernetif_init(struct netif *netif) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Custom Rx pbuf free callback
|
||||
* @param pbuf: pbuf to be freed
|
||||
* @retval None
|
||||
*/
|
||||
void pbuf_free_custom(struct pbuf *p) {
|
||||
struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
|
||||
LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
|
||||
/* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
|
||||
* call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
|
||||
if (RxAllocStatus == RX_ALLOC_ERROR) {
|
||||
RxAllocStatus = RX_ALLOC_OK;
|
||||
* @brief Custom Rx pbuf free callback
|
||||
* @param pbuf: pbuf to be freed
|
||||
* @retval None
|
||||
*/
|
||||
void pbuf_free_custom(struct pbuf *p)
|
||||
{
|
||||
if(p != NULL)
|
||||
{
|
||||
p->flags = 0;
|
||||
p->next = NULL;
|
||||
p->len = p->tot_len = 0;
|
||||
p->ref = 0;
|
||||
p->payload = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current time in milliseconds
|
||||
* when LWIP_TIMERS == 1 and NO_SYS == 1
|
||||
* @param None
|
||||
* @retval Current Time value
|
||||
*/
|
||||
u32_t sys_now(void) { return HAL_GetTick(); }
|
||||
* @brief Returns the current time in milliseconds
|
||||
* when LWIP_TIMERS == 1 and NO_SYS == 1
|
||||
* @param None
|
||||
* @retval Current Time value
|
||||
*/
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Ethernet MSP Routines
|
||||
*******************************************************************************/
|
||||
/**
|
||||
* @brief Initializes the ETH MSP.
|
||||
* @param heth: ETH handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
|
||||
* @brief Initializes the ETH MSP.
|
||||
* @param heth: ETH handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
|
||||
/* Ethernett MSP init: RMII Mode */
|
||||
|
||||
|
||||
/* Enable GPIOs clocks */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
|
||||
/* Ethernet pins configuration
|
||||
* ************************************************/
|
||||
/* Ethernet pins configuration ************************************************/
|
||||
/*
|
||||
RMII_REF_CLK ----------------------> PA1
|
||||
RMII_MDIO -------------------------> PA2
|
||||
@ -429,29 +444,29 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
|
||||
/* Configure PA1, PA2 and PA7 */
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
|
||||
/* Configure PB13 */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_13;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
|
||||
/* Configure PC1, PC4 and PC5 */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
/* Configure PG2, PG11, PG13 and PG14 */
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13;
|
||||
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
#if NO_SYS == 0
|
||||
/* Enable the Ethernet global Interrupt */
|
||||
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
|
||||
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||
#endif
|
||||
|
||||
|
||||
/* Enable Ethernet clocks */
|
||||
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
||||
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
||||
@ -462,167 +477,137 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
|
||||
PHI IO Functions
|
||||
*******************************************************************************/
|
||||
/**
|
||||
* @brief Initializes the MDIO interface GPIO and clocks.
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
int32_t ETH_PHY_IO_Init(void) {
|
||||
/* We assume that MDIO GPIO configuration is already done
|
||||
in the ETH_MspInit() else it should be done here
|
||||
* @brief Initializes the MDIO interface GPIO and clocks.
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
|
||||
int32_t ETH_PHY_IO_Init(void)
|
||||
{
|
||||
/* We assume that MDIO GPIO configuration is already done
|
||||
in the ETH_MspInit() else it should be done here
|
||||
*/
|
||||
|
||||
/* Configure the MDIO Clock */
|
||||
HAL_ETH_SetMDIOClockRange(&EthHandle);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the MDIO interface .
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
int32_t ETH_PHY_IO_DeInit(void) { return 0; }
|
||||
* @brief De-Initializes the MDIO interface .
|
||||
* @param None
|
||||
* @retval 0 if OK, -1 if ERROR
|
||||
*/
|
||||
int32_t ETH_PHY_IO_DeInit (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param pRegVal: pointer to hold the register value
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) {
|
||||
if (HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK) {
|
||||
* @brief Read a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param pRegVal: pointer to hold the register value
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
|
||||
{
|
||||
if(HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param RegVal: Value to be written
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) {
|
||||
if (HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK) {
|
||||
* @brief Write a value to a PHY register through the MDIO interface.
|
||||
* @param DevAddr: PHY port address
|
||||
* @param RegAddr: PHY register address
|
||||
* @param RegVal: Value to be written
|
||||
* @retval 0 if OK -1 if Error
|
||||
*/
|
||||
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
|
||||
{
|
||||
if(HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the time in millisecons used for internal PHY driver process.
|
||||
* @retval Time value
|
||||
*/
|
||||
int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); }
|
||||
* @brief Get the time in millisecons used for internal PHY driver process.
|
||||
* @retval Time value
|
||||
*/
|
||||
int32_t ETH_PHY_IO_GetTick(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @retval None
|
||||
*/
|
||||
void ethernet_link_check_state(struct netif *netif) {
|
||||
ETH_MACConfigTypeDef MACConf = {0};
|
||||
int32_t PHYLinkState = 0U;
|
||||
uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
|
||||
|
||||
* @brief
|
||||
* @retval None
|
||||
*/
|
||||
void ethernet_link_check_state(struct netif *netif)
|
||||
{
|
||||
ETH_MACConfigTypeDef MACConf;
|
||||
uint32_t PHYLinkState;
|
||||
uint32_t linkchanged = 0, speed = 0, duplex =0;
|
||||
|
||||
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
|
||||
|
||||
if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) {
|
||||
HAL_ETH_Stop_IT(&EthHandle);
|
||||
if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
|
||||
{
|
||||
HAL_ETH_Stop(&EthHandle);
|
||||
netif_set_down(netif);
|
||||
netif_set_link_down(netif);
|
||||
} else if (!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) {
|
||||
switch (PHYLinkState) {
|
||||
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
|
||||
duplex = ETH_FULLDUPLEX_MODE;
|
||||
speed = ETH_SPEED_100M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
|
||||
duplex = ETH_HALFDUPLEX_MODE;
|
||||
speed = ETH_SPEED_100M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
|
||||
duplex = ETH_FULLDUPLEX_MODE;
|
||||
speed = ETH_SPEED_10M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
|
||||
duplex = ETH_HALFDUPLEX_MODE;
|
||||
speed = ETH_SPEED_10M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
|
||||
{
|
||||
switch (PHYLinkState)
|
||||
{
|
||||
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
|
||||
duplex = ETH_FULLDUPLEX_MODE;
|
||||
speed = ETH_SPEED_100M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
|
||||
duplex = ETH_HALFDUPLEX_MODE;
|
||||
speed = ETH_SPEED_100M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
|
||||
duplex = ETH_FULLDUPLEX_MODE;
|
||||
speed = ETH_SPEED_10M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
|
||||
duplex = ETH_HALFDUPLEX_MODE;
|
||||
speed = ETH_SPEED_10M;
|
||||
linkchanged = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (linkchanged) {
|
||||
if(linkchanged)
|
||||
{
|
||||
/* Get MAC Config MAC */
|
||||
HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
|
||||
MACConf.DuplexMode = duplex;
|
||||
MACConf.Speed = speed;
|
||||
HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
|
||||
HAL_ETH_Start_IT(&EthHandle);
|
||||
HAL_ETH_Start(&EthHandle);
|
||||
netif_set_up(netif);
|
||||
netif_set_link_up(netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_ETH_RxAllocateCallback(uint8_t **buff) {
|
||||
struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
|
||||
if (p) {
|
||||
/* Get the buff from the struct pbuf address. */
|
||||
*buff = (uint8_t *)p + offsetof(RxBuff_t, buff);
|
||||
p->custom_free_function = pbuf_free_custom;
|
||||
/* Initialize the struct pbuf.
|
||||
* This must be performed whenever a buffer's allocated because it may be
|
||||
* changed by lwIP or the app, e.g., pbuf_free decrements ref. */
|
||||
pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
|
||||
} else {
|
||||
RxAllocStatus = RX_ALLOC_ERROR;
|
||||
*buff = NULL;
|
||||
}
|
||||
ETH_HandleTypeDef* getEthernetHandle() {
|
||||
return &EthHandle;
|
||||
}
|
||||
|
||||
void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) {
|
||||
struct pbuf **ppStart = (struct pbuf **)pStart;
|
||||
struct pbuf **ppEnd = (struct pbuf **)pEnd;
|
||||
struct pbuf *p = NULL;
|
||||
|
||||
/* Get the struct pbuf from the buff address. */
|
||||
p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
|
||||
p->next = NULL;
|
||||
p->tot_len = 0;
|
||||
p->len = Length;
|
||||
|
||||
/* Chain the buffer. */
|
||||
if (!*ppStart) {
|
||||
/* The first buffer of the packet. */
|
||||
*ppStart = p;
|
||||
} else {
|
||||
/* Chain the buffer to the end of the packet. */
|
||||
(*ppEnd)->next = p;
|
||||
}
|
||||
*ppEnd = p;
|
||||
|
||||
/* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its
|
||||
* tot_len set to its own length, plus the length of all the following pbufs in the chain. */
|
||||
for (p = *ppStart; p != NULL; p = p->next) {
|
||||
p->tot_len += Length;
|
||||
}
|
||||
|
||||
/* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length);
|
||||
}
|
||||
|
||||
void HAL_ETH_TxFreeCallback(uint32_t *buff) { pbuf_free((struct pbuf *)buff); }
|
||||
|
||||
ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; }
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
@ -1,69 +1,72 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/ethernetif.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for ethernetif.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
******************************************************************************
|
||||
* @file LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/ethernetif.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for ethernetif.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __ETHERNETIF_H__
|
||||
#define __ETHERNETIF_H__
|
||||
|
||||
#include <stm32h7xx_hal.h>
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
#include <stm32h7xx_hal.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ETH_RX_BUFFER_SIZE (1536UL)
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
ETH_HandleTypeDef *getEthernetHandle();
|
||||
ETH_HandleTypeDef* getEthernetHandle();
|
||||
err_t ethernetif_init(struct netif *netif);
|
||||
void ethernetif_input(struct netif *netif);
|
||||
void ethernet_link_check_state(struct netif *netif);
|
||||
|
||||
extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];
|
||||
extern ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];
|
||||
extern uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,15 +1,19 @@
|
||||
#include "networking.h"
|
||||
|
||||
#include "udp_config.h"
|
||||
#include "networking.h"
|
||||
|
||||
bool ethernetCableConnected = false;
|
||||
|
||||
void networking::setEthCableConnected(bool status) { ethernetCableConnected = status; }
|
||||
|
||||
bool networking::getEthCableConnected() { return ethernetCableConnected; }
|
||||
|
||||
void networking::setLwipAddresses(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
|
||||
IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
|
||||
IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
void networking::setEthCableConnected(bool status) {
|
||||
ethernetCableConnected = status;
|
||||
}
|
||||
|
||||
bool networking::getEthCableConnected() {
|
||||
return ethernetCableConnected;
|
||||
}
|
||||
|
||||
void networking::setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw) {
|
||||
IP4_ADDR(ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
|
||||
IP4_ADDR(netmask, NETMASK_ADDR0, NETMASK_ADDR1 ,
|
||||
NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
IP4_ADDR(gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ namespace networking {
|
||||
|
||||
void setEthCableConnected(bool status);
|
||||
bool getEthCableConnected();
|
||||
void setLwipAddresses(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw);
|
||||
void setLwipAddresses(ip_addr_t* ipaddr, ip_addr_t* netmask, ip_addr_t* gw);
|
||||
|
||||
} // namespace networking
|
||||
}
|
||||
|
||||
#endif /* BSP_STM32H7_RTEMS_NETWORKING_NETWORKING_H_ */
|
||||
|
@ -6,32 +6,31 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* UDP local connection port. Client needs to bind to this port */
|
||||
#define UDP_SERVER_PORT 7
|
||||
#define UDP_SERVER_PORT 7
|
||||
|
||||
/*Static DEST IP ADDRESS:
|
||||
* DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */
|
||||
#define DEST_IP_ADDR0 ((uint8_t)169U)
|
||||
#define DEST_IP_ADDR1 ((uint8_t)254U)
|
||||
#define DEST_IP_ADDR2 ((uint8_t)39U)
|
||||
#define DEST_IP_ADDR3 ((uint8_t)2U)
|
||||
/*Static DEST IP ADDRESS: DEST_IP_ADDR0.DEST_IP_ADDR1.DEST_IP_ADDR2.DEST_IP_ADDR3 */
|
||||
#define DEST_IP_ADDR0 ((uint8_t)169U)
|
||||
#define DEST_IP_ADDR1 ((uint8_t)254U)
|
||||
#define DEST_IP_ADDR2 ((uint8_t)39U)
|
||||
#define DEST_IP_ADDR3 ((uint8_t)2U)
|
||||
|
||||
/*Static IP ADDRESS*/
|
||||
#define IP_ADDR0 169
|
||||
#define IP_ADDR1 254
|
||||
#define IP_ADDR2 1
|
||||
#define IP_ADDR3 38
|
||||
#define IP_ADDR0 169
|
||||
#define IP_ADDR1 254
|
||||
#define IP_ADDR2 1
|
||||
#define IP_ADDR3 38
|
||||
|
||||
/*NETMASK*/
|
||||
#define NETMASK_ADDR0 255
|
||||
#define NETMASK_ADDR1 255
|
||||
#define NETMASK_ADDR2 0
|
||||
#define NETMASK_ADDR3 0
|
||||
#define NETMASK_ADDR0 255
|
||||
#define NETMASK_ADDR1 255
|
||||
#define NETMASK_ADDR2 0
|
||||
#define NETMASK_ADDR3 0
|
||||
|
||||
/*Gateway Address*/
|
||||
#define GW_ADDR0 192
|
||||
#define GW_ADDR1 168
|
||||
#define GW_ADDR2 178
|
||||
#define GW_ADDR3 1
|
||||
#define GW_ADDR0 192
|
||||
#define GW_ADDR1 168
|
||||
#define GW_ADDR2 178
|
||||
#define GW_ADDR3 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user