9 Commits

25 changed files with 435 additions and 649 deletions

45
cmake/BuildType.cmake Normal file
View File

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

42
cmake/common.cmake Normal file
View File

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

View File

@@ -6,11 +6,11 @@
#include <cstdint> #include <cstdint>
#cmakedefine01 FSFW_ADD_FMT_TESTS #cmakedefine01 OBSW_ADD_FMT_TESTS
//! Specify the debug output verbose level //! Specify the debug output verbose level
#define OBSW_VERBOSE_LEVEL 1 #define OBSW_VERBOSE_LEVEL 1
#define OBSW_TCPIP_UDP_WIRETAPPING 0
#define OBSW_PRINT_MISSED_DEADLINES 0 #define OBSW_PRINT_MISSED_DEADLINES 0
//! Perform internal unit testd at application startup //! Perform internal unit testd at application startup

View File

@@ -33,13 +33,7 @@ ReturnValue_t pst::pollingSequenceExamples(FixedTimeslotTaskIF *thisSequence) {
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("pst::pollingSequenceInitFunction: Initialization errors\n");
sif::error << "pst::pollingSequenceInitFunction: Initialization errors!"
<< std::endl;
#else
sif::printError(
"pst::pollingSequenceInitFunction: Initialization errors!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
@@ -75,13 +69,7 @@ ReturnValue_t pst::pollingSequenceDevices(FixedTimeslotTaskIF *thisSequence) {
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("pst::pollingSequenceTestFunction: Initialization errors\n");
sif::error << "pst::pollingSequenceTestFunction: Initialization errors!"
<< std::endl;
#else
sif::printError(
"pst::pollingSequenceTestFunction: Initialization errors!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }

View File

@@ -27,36 +27,26 @@ void FsfwTestController::performControlOperation() {
return; return;
} }
switch (currentTraceType) { switch (currentTraceType) {
case (NONE): { case (NONE): {
break; break;
} }
case (TRACE_DEV_0_UINT8): { case (TRACE_DEV_0_UINT8): {
if (traceCounter == 0) { if (traceCounter == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI("Tracing finished\n");
sif::info << "Tracing finished" << std::endl; traceVariable = false;
#else traceCounter = traceCycles;
sif::printInfo("Tracing finished\n"); currentTraceType = TraceTypes::NONE;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ break;
traceVariable = false; }
traceCounter = traceCycles; PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
currentTraceType = TraceTypes::NONE; FSFW_LOGI("Tracing device 0 variable 0 (UINT8), current value: {}",
static_cast<int>(deviceDataset0.testUint8Var.value));
traceCounter--;
break;
}
case (TRACE_DEV_0_VECTOR): {
break; 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;
}
} }
} }
} }
@@ -67,20 +57,10 @@ ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
HasLocalDataPoolIF *device0 = auto* device0 =
ObjectManager::instance()->get<HasLocalDataPoolIF>( ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
deviceDataset0.getCreatorObjectId());
if (device0 == nullptr) { if (device0 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGW("initializeAfterTaskCreation: Test device handler 0 handle invalid\n");
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; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
ProvidesDataPoolSubscriptionIF *subscriptionIF = ProvidesDataPoolSubscriptionIF *subscriptionIF =
@@ -93,20 +73,10 @@ ReturnValue_t FsfwTestController::initializeAfterTaskCreation() {
td::PoolIds::TEST_UINT8_ID, getObjectId(), getCommandQueue(), false); td::PoolIds::TEST_UINT8_ID, getObjectId(), getCommandQueue(), false);
} }
HasLocalDataPoolIF *device1 = auto* device1 =
ObjectManager::instance()->get<HasLocalDataPoolIF>( ObjectManager::instance()->get<HasLocalDataPoolIF>(deviceDataset0.getCreatorObjectId());
deviceDataset0.getCreatorObjectId());
if (device1 == nullptr) { if (device1 == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGW("initializeAfterTaskCreation: Test device handler 1 handle invalid\n");
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(); subscriptionIF = device1->getSubscriptionInterface();
@@ -142,19 +112,8 @@ void FsfwTestController::handleChangedDataset(sid_t sid,
} else { } else {
printout = "Snapshot"; printout = "Snapshot";
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI("handleChangedDataset: {} update from object ID {:#010x} and set ID {}\n", printout,
sif::info << "FsfwTestController::handleChangedDataset: " << printout sid.objectId, sid.ownerSetId);
<< " 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 == storeId::INVALID_STORE_ADDRESS) { if (storeId == storeId::INVALID_STORE_ADDRESS) {
if (sid.objectId == device0Id) { if (sid.objectId == device0Id) {
@@ -163,13 +122,8 @@ void FsfwTestController::handleChangedDataset(sid_t sid,
floatVec[0] = deviceDataset0.testFloat3Vec.value[0]; floatVec[0] = deviceDataset0.testFloat3Vec.value[0];
floatVec[1] = deviceDataset0.testFloat3Vec.value[1]; floatVec[1] = deviceDataset0.testFloat3Vec.value[1];
floatVec[2] = deviceDataset0.testFloat3Vec.value[2]; floatVec[2] = deviceDataset0.testFloat3Vec.value[2];
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI("Current float vector (3) values: [{},{},{}]\n", floatVec[0], floatVec[1],
sif::info << "Current float vector (3) values: [" << floatVec[0] << ", " floatVec[2]);
<< 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 */
} }
} }
} }
@@ -195,31 +149,16 @@ void FsfwTestController::handleChangedPoolVariable(gp_id_t globPoolId,
printout = "Snapshot"; printout = "Snapshot";
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI(
sif::info << "TestController::handleChangedPoolVariable: " << printout "TestController::handleChangedPoolVariable: {} update from object "
<< " update from object " "ID {:#010x} and LPID {}\n",
"ID 0x" printout, globPoolId.objectId, globPoolId.localPoolId);
<< setw(8) << setfill('0') << hex << globPoolId.objectId
<< " and local pool ID " << globPoolId.localPoolId << dec
<< setfill(' ') << endl;
#else
sif::printInfo("TestController::handleChangedPoolVariable: %s update from "
"object ID 0x%08x and "
"local pool ID %lu\n",
printout, globPoolId.objectId, globPoolId.localPoolId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if (storeId == storeId::INVALID_STORE_ADDRESS) { if (storeId == storeId::INVALID_STORE_ADDRESS) {
if (globPoolId.objectId == device0Id) { if (globPoolId.objectId == device0Id) {
PoolReadGuard readHelper(&deviceDataset0.testUint8Var); PoolReadGuard readHelper(&deviceDataset0.testUint8Var);
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI("Current test variable 0 (UINT8) value: {}",
sif::info << "Current test variable 0 (UINT8) value: " static_cast<int>(deviceDataset0.testUint8Var.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 */
} }
} }
} }

View File

@@ -66,9 +66,11 @@ void ObjectFactory::produceGenericObjects() {
pus::PUS_SERVICE_17); pus::PUS_SERVICE_17);
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS,
apid::APID, pus::PUS_SERVICE_20); apid::APID, pus::PUS_SERVICE_20);
#if OBSW_ADD_CORE_COMPONENTS == 1
new Service11TelecommandScheduling<cfg::OBSW_MAX_SCHEDULED_TCS>( new Service11TelecommandScheduling<cfg::OBSW_MAX_SCHEDULED_TCS>(
objects::PUS_SERVICE_11_TC_SCHEDULER, apid::APID, pus::PUS_SERVICE_11, objects::PUS_SERVICE_11_TC_SCHEDULER, apid::APID, pus::PUS_SERVICE_11,
ccsdsDistrib); ccsdsDistrib);
#endif
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::APID, new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::APID,
pus::PUS_SERVICE_200); pus::PUS_SERVICE_200);
#endif /* OBSW_ADD_PUS_STACK == 1 */ #endif /* OBSW_ADD_PUS_STACK == 1 */

View File

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

View File

@@ -3,7 +3,7 @@
#include <fsfw/ipc/CommandMessage.h> #include <fsfw/ipc/CommandMessage.h>
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h> #include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
@@ -80,15 +80,9 @@ object_id_t FsfwExampleTask::getSender() {
ReturnValue_t FsfwExampleTask::initialize() { ReturnValue_t FsfwExampleTask::initialize() {
// Get the dataset of the sender. Will be cached for later checks. // Get the dataset of the sender. Will be cached for later checks.
object_id_t sender = getSender(); object_id_t sender = getSender();
HasLocalDataPoolIF *senderIF = auto* senderIF = ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
ObjectManager::instance()->get<HasLocalDataPoolIF>(sender);
if (senderIF == nullptr) { if (senderIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("initialize: Sender object invalid\n");
sif::error << "FsfwDemoTask::initialize: Sender object invalid!"
<< std::endl;
#else
sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@@ -96,12 +90,7 @@ ReturnValue_t FsfwExampleTask::initialize() {
// dataset. // dataset.
senderSet = new FsfwDemoSet(senderIF); senderSet = new FsfwDemoSet(senderIF);
if (senderSet == nullptr) { if (senderSet == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("initialize: Sender dataset invalid\n");
sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!"
<< std::endl;
#else
sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return poolManager.initialize(commandQueue); return poolManager.initialize(commandQueue);
@@ -144,13 +133,7 @@ ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20); demoSet.variableLimit.read(MutexIF::TimeoutType::WAITING, 20);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
/* Configuration error */ /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("DummyObject::performOperation: Could not read variableLimit\n");
sif::error << "DummyObject::performOperation: Could not read variableLimit!"
<< std::endl;
#else
sif::printError(
"DummyObject::performOperation: Could not read variableLimit!\n");
#endif
return result; return result;
} }
if (this->getObjectId() == objects::TEST_DUMMY_5) { if (this->getObjectId() == objects::TEST_DUMMY_5) {
@@ -158,7 +141,7 @@ ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
demoSet.variableLimit.value = 0; demoSet.variableLimit.value = 0;
} }
demoSet.variableLimit.value++; demoSet.variableLimit.value++;
demoSet.variableLimit.commit(20); demoSet.variableLimit.commit(true);
monitor.check(); monitor.check();
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@@ -166,18 +149,10 @@ ReturnValue_t FsfwExampleTask::performMonitoringDemo() {
ReturnValue_t FsfwExampleTask::performSendOperation() { ReturnValue_t FsfwExampleTask::performSendOperation() {
object_id_t nextRecipient = getNextRecipient(); object_id_t nextRecipient = getNextRecipient();
FsfwExampleTask *target = auto* target = ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
ObjectManager::instance()->get<FsfwExampleTask>(nextRecipient);
if (target == nullptr) { if (target == nullptr) {
/* Configuration error */ /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("performSendOperation: Next recipient does not exist\n");
sif::error
<< "DummyObject::performOperation: Next recipient does not exist!"
<< std::endl;
#else
sif::printError(
"DummyObject::performOperation: Next recipient does not exist!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@@ -187,35 +162,20 @@ ReturnValue_t FsfwExampleTask::performSendOperation() {
message.setParameter2(this->getMessageQueueId()); message.setParameter2(this->getMessageQueueId());
/* Send message using own message queue */ /* Send message using own message queue */
ReturnValue_t result = ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message);
commandQueue->sendMessage(target->getMessageQueueId(), &message); if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) {
if (result != HasReturnvaluesIF::RETURN_OK && FSFW_LOGE("performSendOperation: Send failed with {:#06x}\n", result);
result != MessageQueueIF::FULL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with "
<< result << std::endl;
#else
sif::printError(
"FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
#endif
} }
/* Send message without via MessageQueueSenderIF */ /* Send message without via MessageQueueSenderIF */
result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message,
&message, commandQueue->getId()); commandQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK && if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::FULL) {
result != MessageQueueIF::FULL) { FSFW_LOGE("performSendOperation: Send failed with {:#06x}\n", result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FsfwDemoTask::performSendOperation: Send failed with "
<< result << std::endl;
#else
sif::printError(
"FsfwDemoTask::performSendOperation: Send failed with %hu\n", result);
#endif
} }
demoSet.variableWrite.value = randomNumber; demoSet.variableWrite.value = randomNumber;
result = demoSet.variableWrite.commit(20); result = demoSet.variableWrite.commit(true);
return result; return result;
} }
@@ -225,11 +185,8 @@ ReturnValue_t FsfwExampleTask::performReceiveOperation() {
while (result != MessageQueueIF::EMPTY) { while (result != MessageQueueIF::EMPTY) {
CommandMessage receivedMessage; CommandMessage receivedMessage;
result = commandQueue->receiveMessage(&receivedMessage); result = commandQueue->receiveMessage(&receivedMessage);
if (result != HasReturnvaluesIF::RETURN_OK && if (result != HasReturnvaluesIF::RETURN_OK && result != MessageQueueIF::EMPTY) {
result != MessageQueueIF::EMPTY) { FSFW_LOGD("performReceiveOperation: Receive failed with {}\n", result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Receive failed with " << result << std::endl;
#endif
break; break;
} }
if (result != MessageQueueIF::EMPTY) { if (result != MessageQueueIF::EMPTY) {
@@ -251,15 +208,10 @@ ReturnValue_t FsfwExampleTask::performReceiveOperation() {
return result; return result;
} }
if (senderSet->variableRead.value != receivedMessage.getParameter()) { if (senderSet->variableRead.value != receivedMessage.getParameter()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE(
sif::error << "FsfwDemoTask::performReceiveOperation: Variable " "FsfwDemoTask::performReceiveOperation: Variable {} has wrong value {}, expected {}\n",
<< std::hex << "0x" senderSet->variableRead.getDataPoolId(), demoSet.variableRead.value,
<< senderSet->variableRead.getDataPoolId() << std::dec receivedMessage.getParameter());
<< " has wrong value." << std::endl;
sif::error << "Value: " << demoSet.variableRead.value
<< ", expected: " << receivedMessage.getParameter()
<< std::endl;
#endif
} }
} }
} }

View File

@@ -2,7 +2,7 @@
#include <OBSWConfig.h> #include <OBSWConfig.h>
#include <fsfw/datapool/PoolReadGuard.h> #include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h> #include <fsfw/timemanager/Stopwatch.h>
@@ -32,25 +32,11 @@ ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) {
uint32_t variable2 = readSet.variable2.value; uint32_t variable2 = readSet.variable2.value;
uint32_t variable3 = readSet.variable3.value; uint32_t variable3 = readSet.variable3.value;
#if OBSW_VERBOSE_LEVEL >= 1
if (opDivider.checkAndIncrement() and printoutEnabled) { if (opDivider.checkAndIncrement() and printoutEnabled) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGI(
sif::info << "FsfwPeriodicTask::performOperation: Reading variables." "FsfwPeriodicTask::performOperation: Reading variables from Demo "
<< std::endl; "Object 1,2,3\n1 {} | 2 {} | 3 {}\n",
sif::info << "Variable read from demo object 1: " << variable1 << std::endl; variable1, variable2, variable3);
sif::info << "Variable read from demo object 2: " << variable2 << std::endl;
sif::info << "Variable read from demo object 3: " << variable3 << std::endl;
#else
sif::printInfo(
"FsfwPeriodicTask::performOperation: Reading variables.\n\r");
sif::printInfo("Variable read from demo object 1: %d\n\r", variable1);
sif::printInfo("Variable read from demo object 2: %d\n\r", variable2);
sif::printInfo("Variable read from demo object 3: %d\n\r", variable3);
#endif
} }
#else
if (variable1 and variable2 and variable3) {
};
#endif
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@@ -2,13 +2,13 @@
#include <commonConfig.h> #include <commonConfig.h>
#if FSFW_ADD_FMT_TESTS == 1 #if OBSW_ADD_FMT_TESTS == 1
#include "testFmt.h" #include "testFmt.h"
#endif #endif
FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent) FsfwTestTask::FsfwTestTask(object_id_t objectId, bool periodicEvent)
: TestTask(objectId), periodicEvent(periodicEvent) { : TestTask(objectId), periodicEvent(periodicEvent) {
#if FSFW_ADD_FMT_TESTS == 1 #if OBSW_ADD_FMT_TESTS == 1
fmtTests(); fmtTests();
#endif #endif
} }

View File

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

View File

@@ -1,14 +1,20 @@
#include "testFmt.h" #include "fsfw/serviceinterface/fmtWrapper.h"
void fmtTests() { void fmtTests() {
sif::fdebug(__FILENAME__, __LINE__, "Hello {} {}", "World\n"); sif::initialize();
sif::fdebug_t(__FILENAME__, __LINE__, "Hallo\n"); sif::debug_s(__FILENAME__, __LINE__, "Hello {}", "World\n");
sif::debug_st(__FILENAME__, __LINE__, "Hallo\n");
FSFW_LOGD("{}", "Hallo\n"); FSFW_LOGD("{}", "Hallo\n");
// MY_LOG("{}", "test\n"); sif::info_t("Hallo\n");
// sif::finfo_t("Hallo\n"); sif::info("Hallo\n");
// sif::finfo("Hallo\n"); sif::warning_s(__FILENAME__, __LINE__, "Hello\n");
// sif::fwarning("Hello\n"); sif::warning_st(__FILENAME__, __LINE__, "Hello\n");
// sif::fwarning_t("Hello\n"); FSFW_LOGW("Hello World\n");
// sif::ferror("Hello\n"); FSFW_LOGW("{} World\n", "Hello");
// sif::ferror_t("Hello\n"); uint8_t test0 = 5;
float test1 = 12.0;
uint32_t test2 = 0x00ff11ff;
FSFW_LOGW("Test 0 {} | Test 1 {:.3f} | Test 2 {:#010x}\n", test0, test1, test2);
sif::error_s(__FILENAME__, __LINE__, "Hello\n");
sif::error_st(__FILENAME__, __LINE__, "Hello\n");
} }

View File

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

View File

@@ -2,19 +2,12 @@
#define MISSION_UTILITY_TASKCREATION_H_ #define MISSION_UTILITY_TASKCREATION_H_
#include <fsfw/objectmanager/SystemObjectIF.h> #include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface.h>
namespace task { namespace task {
void printInitError(const char *objName, object_id_t objectId) { void printInitError(const char* objName, object_id_t objectId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGW("InitMission: Adding object {} ({:#010x}) failed\n", objName, objectId);
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));
#endif
} }
} // namespace task } // namespace task

View File

@@ -2,7 +2,7 @@
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
#include <fsfw/objectmanager/ObjectManager.h> #include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface.h>
#include <fsfw/tmtcpacket/pus/tm.h> #include <fsfw/tmtcpacket/pus/tm.h>
object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT; object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT;
@@ -58,10 +58,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage *message) {
result = tmQueue->sendToDefault(message); result = tmQueue->sendToDefault(message);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
tmPool->deleteData(message->getStorageId()); tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGET("handlePacket: Error sending to downlink handler\n");
sif::error << "TmFunnel::handlePacket: Error sending to downlink handler"
<< std::endl;
#endif
return result; return result;
} }
@@ -69,10 +66,7 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage *message) {
result = storageQueue->sendToDefault(message); result = storageQueue->sendToDefault(message);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
tmPool->deleteData(message->getStorageId()); tmPool->deleteData(message->getStorageId());
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGET("handlePacket: Error sending to storage handler\n");
sif::error << "TmFunnel::handlePacket: Error sending to storage handler"
<< std::endl;
#endif
return result; return result;
} }
} }
@@ -82,25 +76,18 @@ ReturnValue_t TmFunnel::handlePacket(TmTcMessage *message) {
ReturnValue_t TmFunnel::initialize() { ReturnValue_t TmFunnel::initialize() {
tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE); tmPool = ObjectManager::instance()->get<StorageManagerIF>(objects::TM_STORE);
if (tmPool == nullptr) { if (tmPool == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 FSFW_LOGE("{}",
sif::error << "TmFunnel::initialize: TM store not set." << std::endl; "initialize: TM store not set\n"
sif::error << "Make sure the tm store is set up properly and implements " "Make sure the tm store is set up properly and implements StorageManagerIF");
"StorageManagerIF"
<< std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
AcceptsTelemetryIF *tmTarget = auto* tmTarget = ObjectManager::instance()->get<AcceptsTelemetryIF>(downlinkDestination);
ObjectManager::instance()->get<AcceptsTelemetryIF>(downlinkDestination);
if (tmTarget == nullptr) { if (tmTarget == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmFunnel::initialize: Downlink Destination not set." FSFW_LOGE("{}",
<< std::endl; "initialize: Downlink Destination not set. Make sure the downlink destination "
sif::error << "Make sure the downlink destination object is set up " "object is set up properly and implements AcceptsTelemetryIF\n");
"properly and implements "
"AcceptsTelemetryIF"
<< std::endl;
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }

View File

@@ -1,24 +1,16 @@
#include "utility.h" #include "utility.h"
#include <FSFWConfig.h>
#include <OBSWVersion.h> #include <OBSWVersion.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include "fsfw/serviceinterface.h"
void utility::commonInitPrint(const char *const os, const char *const board) { void utility::commonInitPrint(const char *const os, const char *const board) {
if (os == nullptr or board == nullptr) { if (os == nullptr or board == nullptr) {
return; return;
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 fmt::print("-- FSFW Example ({}) v{}.{}.{} --\n", os, FSFW_EXAMPLE_VERSION,
std::cout << "-- FSFW Example (" << os << ") v" << FSFW_EXAMPLE_VERSION << "." FSFW_EXAMPLE_SUBVERSION, FSFW_EXAMPLE_REVISION);
<< FSFW_EXAMPLE_SUBVERSION << "." << FSFW_EXAMPLE_REVISION << " --" fmt::print("-- Compiled for {}\n", board);
<< std::endl; fmt::print("-- Compiled on {} {}\n", __DATE__, __TIME__);
std::cout << "-- Compiled for " << board << " --" << std::endl; sif::initialize();
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__);
#endif
} }

View File

@@ -11,9 +11,17 @@ STM32TestTask::STM32TestTask(object_id_t objectId, bool enablePrintout,
BSP_LED_Init(LED3); BSP_LED_Init(LED3);
} }
ReturnValue_t STM32TestTask::initialize() {
if (testSpi) {
spiComIF = new SpiComIF(objects::SPI_COM_IF);
spiTest = new SpiTest(*spiComIF);
}
return TestTask::initialize();
}
ReturnValue_t STM32TestTask::performPeriodicAction() { ReturnValue_t STM32TestTask::performPeriodicAction() {
if (blinkyLed) { if (blinkyLed) {
#if OBSW_ETHERNET_USE_LEDS == 0 #if OBSW_ETHERNET_USE_LED1_LED2 == 0
BSP_LED_Toggle(LED1); BSP_LED_Toggle(LED1);
BSP_LED_Toggle(LED2); BSP_LED_Toggle(LED2);
#endif #endif
@@ -24,11 +32,3 @@ ReturnValue_t STM32TestTask::performPeriodicAction() {
} }
return TestTask::performPeriodicAction(); return TestTask::performPeriodicAction();
} }
ReturnValue_t STM32TestTask::initialize() {
if (testSpi) {
spiComIF = new SpiComIF(objects::SPI_COM_IF);
spiTest = new SpiTest(*spiComIF);
}
return TestTask::initialize();
}

View File

@@ -17,7 +17,7 @@ private:
SpiTest *spiTest = nullptr; SpiTest *spiTest = nullptr;
bool blinkyLed = false; bool blinkyLed = false;
bool testSpi = true; bool testSpi = false;
}; };
#endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */ #endif /* BSP_STM32_BOARDTEST_STM32TESTTASK_H_ */

View File

@@ -1,12 +1,11 @@
#include "TmTcLwIpUdpBridge.h" #include "TmTcLwIpUdpBridge.h"
#include <OBSWConfig.h>
#include <fsfw/ipc/MutexGuard.h> #include <fsfw/ipc/MutexGuard.h>
#include <fsfw/serialize/EndianConverter.h> #include <fsfw/serialize/EndianConverter.h>
#include <fsfw/serviceinterface/ServiceInterface.h> #include <fsfw/serviceinterface/ServiceInterface.h>
#include "app_ethernet.h" #include "app_ethernet.h"
#include "ethernetif.h"
#include "udp_config.h" #include "udp_config.h"
TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId, TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId,
@@ -17,7 +16,7 @@ TmTcLwIpUdpBridge::TmTcLwIpUdpBridge(object_id_t objectId,
TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY; TmTcLwIpUdpBridge::lastAdd.addr = IPADDR_TYPE_ANY;
} }
TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() {} TmTcLwIpUdpBridge::~TmTcLwIpUdpBridge() = default;
ReturnValue_t TmTcLwIpUdpBridge::initialize() { ReturnValue_t TmTcLwIpUdpBridge::initialize() {
TmTcBridge::initialize(); TmTcBridge::initialize();
@@ -29,11 +28,12 @@ ReturnValue_t TmTcLwIpUdpBridge::initialize() {
return result; return result;
} }
ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) { ReturnValue_t TmTcLwIpUdpBridge::udp_server_init() {
err_t err; err_t err;
/* Create a new UDP control block */ /* Create a new UDP control block */
TmTcLwIpUdpBridge::upcb = udp_new(); TmTcLwIpUdpBridge::upcb = udp_new();
if (TmTcLwIpUdpBridge::upcb) { if (TmTcLwIpUdpBridge::upcb) {
sif::printInfo("Opening UDP server on port %d\n", UDP_SERVER_PORT);
/* Bind the upcb to the UDP_PORT port */ /* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT); err = udp_bind(TmTcLwIpUdpBridge::upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
@@ -55,7 +55,7 @@ ReturnValue_t TmTcLwIpUdpBridge::udp_server_init(void) {
ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) { ReturnValue_t TmTcLwIpUdpBridge::performOperation(uint8_t operationCode) {
TmTcBridge::performOperation(); TmTcBridge::performOperation();
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
if (connectFlag) { if (connectFlag) {
uint32_t ipAddress = ((ip4_addr *)&lastAdd)->addr; uint32_t ipAddress = ((ip4_addr *)&lastAdd)->addr;
int ipAddress1 = (ipAddress & 0xFF000000) >> 24; int ipAddress1 = (ipAddress & 0xFF000000) >> 24;
@@ -89,7 +89,7 @@ ReturnValue_t TmTcLwIpUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) && if ((p_tx != nullptr) && (lastAdd.addr != IPADDR_TYPE_ANY) &&
(upcb != nullptr)) { (upcb != nullptr)) {
/* copy data to pbuf */ /* copy data to pbuf */
err_t err = pbuf_take(p_tx, (char *)data, dataLen); err_t err = pbuf_take(p_tx, (const char *)data, dataLen);
if (err != ERR_OK) { if (err != ERR_OK) {
pbuf_free(p_tx); pbuf_free(p_tx);
return err; return err;
@@ -120,7 +120,6 @@ void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg,
struct pbuf *p, struct pbuf *p,
const ip_addr_t *addr, const ip_addr_t *addr,
u16_t port) { u16_t port) {
struct pbuf *p_tx = nullptr;
auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge *>(arg); auto udpBridge = reinterpret_cast<TmTcLwIpUdpBridge *>(arg);
if (udpBridge == nullptr) { if (udpBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -133,9 +132,9 @@ void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg,
#endif #endif
} }
/* allocate pbuf from RAM*/ /* allocate pbuf from RAM*/
p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM); struct pbuf *p_tx = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
if (p_tx != NULL) { if (p_tx != nullptr) {
if (udpBridge != nullptr) { if (udpBridge != nullptr) {
MutexGuard lg(udpBridge->bridgeLock); MutexGuard lg(udpBridge->bridgeLock);
udpBridge->upcb = upcb_; udpBridge->upcb = upcb_;
@@ -143,7 +142,7 @@ void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg,
udpBridge->lastPort = port; udpBridge->lastPort = port;
if (not udpBridge->comLinkUp()) { if (not udpBridge->comLinkUp()) {
udpBridge->registerCommConnect(); udpBridge->registerCommConnect();
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
udpBridge->connectFlag = true; udpBridge->connectFlag = true;
#endif #endif
/* This should have already been done, but we will still do it */ /* This should have already been done, but we will still do it */
@@ -155,8 +154,8 @@ void TmTcLwIpUdpBridge::udp_server_receive_callback(void *arg,
char *data = reinterpret_cast<char *>(p_tx->payload); char *data = reinterpret_cast<char *>(p_tx->payload);
*(data + p_tx->len) = '\0'; *(data + p_tx->len) = '\0';
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
udpBridge->printData(p, data); udpBridge->printData(reinterpret_cast<uint8_t *>(p->payload), p->len);
#endif #endif
store_address_t storeId; store_address_t storeId;

View File

@@ -1,12 +1,12 @@
#ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ #ifndef BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_ #define BSP_STM32_RTEMS_NETWORKING_TMTCUDPBRIDGE_H_
#include <fsfw/tmtcservices/TmTcBridge.h> #include "fsfw/tmtcservices/TmTcBridge.h"
#include "commonConfig.h"
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include <lwip/udp.h> #include <lwip/udp.h>
#define TCPIP_RECV_WIRETAPPING 0
/** /**
* This bridge is used to forward TMTC packets received via LwIP UDP to the * This bridge is used to forward TMTC packets received via LwIP UDP to the
* internal software bus. * internal software bus.
@@ -17,9 +17,9 @@ class TmTcLwIpUdpBridge : public TmTcBridge {
public: public:
TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor, TmTcLwIpUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor,
object_id_t tmStoreId, object_id_t tcStoreId); object_id_t tmStoreId, object_id_t tcStoreId);
virtual ~TmTcLwIpUdpBridge(); ~TmTcLwIpUdpBridge() override;
virtual ReturnValue_t initialize() override; ReturnValue_t initialize() override;
ReturnValue_t udp_server_init(); ReturnValue_t udp_server_init();
/** /**
@@ -27,14 +27,14 @@ public:
* @param operationCode * @param operationCode
* @return * @return
*/ */
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t performOperation(uint8_t operationCode) override;
/** TM Send implementation uses udp_send function from lwIP stack /** TM Send implementation uses udp_send function from lwIP stack
* @param data * @param data
* @param dataLen * @param dataLen
* @return * @return
*/ */
virtual ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override; ReturnValue_t sendTm(const uint8_t *data, size_t dataLen) override;
/** /**
* @brief This function is called when an UDP datagram has been * @brief This function is called when an UDP datagram has been
@@ -54,16 +54,16 @@ public:
* Caller must ensure thread-safety by using the bridge lock. * Caller must ensure thread-safety by using the bridge lock.
* @return * @return
*/ */
bool comLinkUp() const; [[nodiscard]] bool comLinkUp() const;
private: private:
struct udp_pcb *upcb = nullptr; struct udp_pcb *upcb = nullptr;
ip_addr_t lastAdd; ip_addr_t lastAdd{};
u16_t lastPort = 0; u16_t lastPort = 0;
bool physicalConnection = false; bool physicalConnection = false;
MutexIF *bridgeLock = nullptr; MutexIF *bridgeLock = nullptr;
#if TCPIP_RECV_WIRETAPPING == 1 #if OBSW_TCPIP_UDP_WIRETAPPING == 1
bool connectFlag = false; bool connectFlag = false;
#endif #endif

View File

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

View File

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

View File

@@ -1,8 +1,6 @@
#include "app_dhcp.h" #include "app_dhcp.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "app_ethernet.h"
#include "ethernetif.h"
#include "lwip/dhcp.h" #include "lwip/dhcp.h"
#include "networking.h" #include "networking.h"
#include "stm32h7xx_nucleo.h" #include "stm32h7xx_nucleo.h"
@@ -24,7 +22,7 @@ void handle_dhcp_down(struct netif *netif);
* @retval None * @retval None
*/ */
void DHCP_Process(struct netif *netif) { void DHCP_Process(struct netif *netif) {
struct dhcp *dhcp = NULL; struct dhcp *dhcp = nullptr;
switch (DHCP_state) { switch (DHCP_state) {
case DHCP_START: { case DHCP_START: {
handle_dhcp_start(netif); handle_dhcp_start(netif);
@@ -119,8 +117,8 @@ void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp) {
#endif #endif
#endif #endif
} else { } else {
*dhcp = (struct dhcp *)netif_get_client_data( *dhcp = static_cast<struct dhcp *>(netif_get_client_data(
netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP));
/* DHCP timeout */ /* DHCP timeout */
if ((*dhcp)->tries > MAX_DHCP_TRIES) { if ((*dhcp)->tries > MAX_DHCP_TRIES) {
@@ -130,6 +128,7 @@ void handle_dhcp_wait(struct netif *netif, struct dhcp **dhcp) {
} }
void handle_dhcp_down(struct netif *netif) { void handle_dhcp_down(struct netif *netif) {
static_cast<void>(netif);
DHCP_state = DHCP_OFF; DHCP_state = DHCP_OFF;
#if OBSW_ETHERNET_TMTC_COMMANDING == 1 #if OBSW_ETHERNET_TMTC_COMMANDING == 1
printf("DHCP_Process: The network cable is not connected.\n\r"); printf("DHCP_Process: The network cable is not connected.\n\r");

View File

@@ -44,16 +44,16 @@
*/ */
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "ethernetif.h" #include "ethernetif.h"
#include "lan8742.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 <string.h> #include <string.h>
#include <stdbool.h>
#include "fsfw/FSFW.h" #include "fsfw/FSFW.h"
#ifdef FSFW_OSAL_RTEMS #ifdef FSFW_OSAL_RTEMS
@@ -66,6 +66,12 @@
#define IFNAME0 's' #define IFNAME0 's'
#define IFNAME1 't' #define IFNAME1 't'
#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
#define ETH_RX_BUFFER_SIZE 1536U
#define ETH_RX_BUFFER_CNT 12U
#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U)
#define DMA_DESCRIPTOR_ALIGNMENT 0x20 #define DMA_DESCRIPTOR_ALIGNMENT 0x20
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
@@ -87,27 +93,30 @@ stack they will return back to DMA after been processed by the stack.
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must 2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen) passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
*/ */
typedef enum
{
RX_ALLOC_OK = 0x00,
RX_ALLOC_ERROR = 0x01
} RxAllocStatusTypeDef;
typedef struct
{
struct pbuf_custom pbuf_custom;
uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
} RxBuff_t;
#if defined(__ICCARM__) /*!< IAR Compiler */ #if defined(__ICCARM__) /*!< IAR Compiler */
#pragma location = 0x30040000 #pragma location=0x30000000
ETH_DMADescTypeDef ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ #pragma location=0x30000200
#pragma location = 0x30040060 ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
ETH_DMADescTypeDef
DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location = 0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT]
[ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
#elif defined(__CC_ARM) /* MDK ARM Compiler */ #elif defined(__CC_ARM) /* MDK ARM Compiler */
__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef __attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
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(".TxDecripSection"))) ETH_DMADescTypeDef
DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((section(".RxArraySection"))) uint8_t
Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
#elif defined(__GNUC__) /* GNU Compiler */ #elif defined(__GNUC__) /* GNU Compiler */
@@ -124,44 +133,57 @@ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((
* placing it */ * placing it */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];
#elif defined FSFW_OSAL_FREERTOS #elif defined FSFW_OSAL_FREERTOS
/* Placement and alignment specified in linker script here */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__(( ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((
section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ #endif /* FSFW_OSAL_RTEMS */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]
__attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
#endif /* FSFW_FREERTOS */
#endif /* defined ( __GNUC__ ) */ #endif /* defined ( __GNUC__ ) */
/* Memory Pool Declaration */
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location = 0x30000400
extern u8_t memp_memory_RX_POOL_base[];
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
#elif defined ( __GNUC__ ) /* GNU Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
#endif
/* Global boolean to track ethernet connection */ /* Global boolean to track ethernet connection */
bool ethernet_cable_connected; bool ethernet_cable_connected;
struct pbuf_custom rx_pbuf[ETH_RX_DESC_CNT]; /* Variable Definitions */
uint32_t current_pbuf_idx = 0; static uint8_t RxAllocStatus;
/* Global Ethernet handle*/
ETH_HandleTypeDef EthHandle; ETH_HandleTypeDef EthHandle;
ETH_TxPacketConfig TxConfig; ETH_TxPacketConfig TxConfig;
lan8742_Object_t LAN8742;
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
u32_t sys_now(void); u32_t sys_now(void);
void pbuf_free_custom(struct pbuf *p); extern void Error_Handler(void);
int32_t ETH_PHY_IO_Init(void); int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit(void); int32_t ETH_PHY_IO_DeInit (void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
uint32_t *pRegVal); int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr,
uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void); int32_t ETH_PHY_IO_GetTick(void);
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, lan8742_Object_t LAN8742;
ETH_PHY_IO_WriteReg, ETH_PHY_IO_ReadReg, lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
ETH_PHY_IO_DeInit,
ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg,
ETH_PHY_IO_GetTick}; ETH_PHY_IO_GetTick};
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
void pbuf_free_custom(struct pbuf *p);
/******************************************************************************* /*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH) LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/ *******************************************************************************/
@@ -173,9 +195,7 @@ lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit,
* for this ethernetif * for this ethernetif
*/ */
static void low_level_init(struct netif *netif) { static void low_level_init(struct netif *netif) {
uint32_t idx = 0; uint8_t macaddress[6]= {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
uint8_t macaddress[6] = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2,
ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
EthHandle.Instance = ETH; EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress; EthHandle.Init.MACAddr = macaddress;
@@ -188,15 +208,15 @@ static void low_level_init(struct netif *netif) {
HAL_ETH_Init(&EthHandle); HAL_ETH_Init(&EthHandle);
/* set MAC hardware address length */ /* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN; netif->hwaddr_len = ETH_HWADDR_LEN;
/* set MAC hardware address */ /* set MAC hardware address */
netif->hwaddr[0] = 0x02; netif->hwaddr[0] = ETH_MAC_ADDR0;
netif->hwaddr[1] = 0x00; netif->hwaddr[1] = ETH_MAC_ADDR1;
netif->hwaddr[2] = 0x00; netif->hwaddr[2] = ETH_MAC_ADDR2;
netif->hwaddr[3] = 0x00; netif->hwaddr[3] = ETH_MAC_ADDR3;
netif->hwaddr[4] = 0x00; netif->hwaddr[4] = ETH_MAC_ADDR4;
netif->hwaddr[5] = 0x00; netif->hwaddr[5] = ETH_MAC_ADDR5;
/* maximum transfer unit */ /* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD; netif->mtu = ETH_MAX_PAYLOAD;
@@ -205,17 +225,12 @@ static void low_level_init(struct netif *netif) {
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
for (idx = 0; idx < ETH_RX_DESC_CNT; idx++) { /* Initialize the RX POOL */
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL); LWIP_MEMPOOL_INIT(RX_POOL);
/* Set Custom pbuf free function */
rx_pbuf[idx].custom_free_function = pbuf_free_custom;
}
/* Set Tx packet config common parameters */ /* Set Tx packet config common parameters */
memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig)); memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
TxConfig.Attributes = TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
@@ -245,40 +260,43 @@ static void low_level_init(struct netif *netif) {
* dropped because of memory failure (except for the TCP timers). * dropped because of memory failure (except for the TCP timers).
*/ */
static err_t low_level_output(struct netif *netif, struct pbuf *p) { static err_t low_level_output(struct netif *netif, struct pbuf *p) {
uint32_t i = 0, framelen = 0; uint32_t i = 0U;
struct pbuf *q; struct pbuf *q = NULL;
err_t errval = ERR_OK; err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};
for (q = p; q != NULL; q = q->next) { memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
if (i >= ETH_TX_DESC_CNT)
for(q = p; q != NULL; q = q->next)
{
if(i >= ETH_TX_DESC_CNT)
return ERR_IF; return ERR_IF;
Txbuffer[i].buffer = q->payload; Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len; Txbuffer[i].len = q->len;
framelen += q->len;
if (i > 0) { if(i>0)
Txbuffer[i - 1].next = &Txbuffer[i]; {
Txbuffer[i-1].next = &Txbuffer[i];
} }
if (q->next == NULL) { if(q->next == NULL)
{
Txbuffer[i].next = NULL; Txbuffer[i].next = NULL;
} }
i++; i++;
} }
TxConfig.Length = framelen; TxConfig.Length = p->tot_len;
TxConfig.TxBuffer = Txbuffer; TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;
HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, 20); HAL_StatusTypeDef ret = HAL_ETH_Transmit(&EthHandle, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
if (ret != HAL_OK) { if (ret != HAL_OK) {
printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r", printf("low_level_output: Could not transmit ethernet packet, code %d!\n\r",
ret); ret);
} }
return errval; return errval;
} }
@@ -292,30 +310,13 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) {
*/ */
static struct pbuf *low_level_input(struct netif *netif) { static struct pbuf *low_level_input(struct netif *netif) {
struct pbuf *p = NULL; struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0;
if (HAL_ETH_IsRxDataAvailable(&EthHandle)) { if(RxAllocStatus == RX_ALLOC_OK)
HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff); {
HAL_ETH_GetRxDataLength(&EthHandle, &framelength); HAL_ETH_ReadData(&EthHandle, (void **)&p);
/* Invalidate data cache for ETH Rx Buffers */
SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff,
(ETH_RX_DESC_CNT * ETH_RX_BUFFER_SIZE));
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_POOL,
&rx_pbuf[current_pbuf_idx], RxBuff.buffer,
ETH_RX_BUFFER_SIZE);
if (current_pbuf_idx < (ETH_RX_DESC_CNT - 1)) {
current_pbuf_idx++;
} else {
current_pbuf_idx = 0;
}
return p;
} else {
return NULL;
} }
return p;
} }
/** /**
@@ -328,26 +329,21 @@ static struct pbuf *low_level_input(struct netif *netif) {
* @param netif the lwip network interface structure for this ethernetif * @param netif the lwip network interface structure for this ethernetif
*/ */
void ethernetif_input(struct netif *netif) { void ethernetif_input(struct netif *netif) {
err_t err; struct pbuf *p = NULL;
struct pbuf *p;
/* move received packet into a new pbuf */ do
p = low_level_input(netif); {
p = low_level_input( netif );
if (p != NULL)
{
if (netif->input( p, netif) != ERR_OK )
{
pbuf_free(p);
}
}
/* no packet could be read, silently ignore this */ } while(p!=NULL);
if (p == NULL)
return;
/* entry point to the LwIP stack */
err = netif->input(p, netif);
if (err != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
p = NULL;
}
HAL_ETH_BuildRxDescriptors(&EthHandle);
} }
/** /**
@@ -372,6 +368,7 @@ err_t ethernetif_init(struct netif *netif) {
netif->name[0] = IFNAME0; netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1; netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call. /* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output() * You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link * from it if you have to do some checks before sending (e.g. if link
@@ -391,12 +388,13 @@ err_t ethernetif_init(struct netif *netif) {
* @retval None * @retval None
*/ */
void pbuf_free_custom(struct pbuf *p) { void pbuf_free_custom(struct pbuf *p) {
if (p != NULL) { struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p;
p->flags = 0; LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
p->next = NULL; /* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
p->len = p->tot_len = 0; * call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
p->ref = 0; if (RxAllocStatus == RX_ALLOC_ERROR)
p->payload = NULL; {
RxAllocStatus = RX_ALLOC_OK;
} }
} }
@@ -545,19 +543,22 @@ int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); }
* @retval None * @retval None
*/ */
void ethernet_link_check_state(struct netif *netif) { void ethernet_link_check_state(struct netif *netif) {
ETH_MACConfigTypeDef MACConf; ETH_MACConfigTypeDef MACConf = {0};
uint32_t PHYLinkState; int32_t PHYLinkState = 0U;
uint32_t linkchanged = 0, speed = 0, duplex = 0; uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
PHYLinkState = LAN8742_GetLinkState(&LAN8742); PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if (netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) { if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
HAL_ETH_Stop(&EthHandle); {
HAL_ETH_Stop_IT(&EthHandle);
netif_set_down(netif); netif_set_down(netif);
netif_set_link_down(netif); netif_set_link_down(netif);
} else if (!netif_is_link_up(netif) && }
(PHYLinkState > LAN8742_STATUS_LINK_DOWN)) { else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
switch (PHYLinkState) { {
switch (PHYLinkState)
{
case LAN8742_STATUS_100MBITS_FULLDUPLEX: case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE; duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M; speed = ETH_SPEED_100M;
@@ -582,19 +583,81 @@ void ethernet_link_check_state(struct netif *netif) {
break; break;
} }
if (linkchanged) { if(linkchanged)
{
/* Get MAC Config MAC */ /* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&EthHandle, &MACConf); HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
MACConf.DuplexMode = duplex; MACConf.DuplexMode = duplex;
MACConf.Speed = speed; MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&EthHandle, &MACConf); HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
HAL_ETH_Start(&EthHandle); HAL_ETH_Start_IT(&EthHandle);
netif_set_up(netif); netif_set_up(netif);
netif_set_link_up(netif); netif_set_link_up(netif);
} }
} }
} }
void HAL_ETH_RxAllocateCallback(uint8_t **buff)
{
struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
if (p)
{
/* Get the buff from the struct pbuf address. */
*buff = (uint8_t *)p + offsetof(RxBuff_t, buff);
p->custom_free_function = pbuf_free_custom;
/* Initialize the struct pbuf.
* This must be performed whenever a buffer's allocated because it may be
* changed by lwIP or the app, e.g., pbuf_free decrements ref. */
pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
}
else
{
RxAllocStatus = RX_ALLOC_ERROR;
*buff = NULL;
}
}
void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
{
struct pbuf **ppStart = (struct pbuf **)pStart;
struct pbuf **ppEnd = (struct pbuf **)pEnd;
struct pbuf *p = NULL;
/* Get the struct pbuf from the buff address. */
p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
p->next = NULL;
p->tot_len = 0;
p->len = Length;
/* Chain the buffer. */
if (!*ppStart)
{
/* The first buffer of the packet. */
*ppStart = p;
}
else
{
/* Chain the buffer to the end of the packet. */
(*ppEnd)->next = p;
}
*ppEnd = p;
/* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len
* set to its own length, plus the length of all the following pbufs in the chain. */
for (p = *ppStart; p != NULL; p = p->next)
{
p->tot_len += Length;
}
/* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length);
}
void HAL_ETH_TxFreeCallback(uint32_t * buff)
{
pbuf_free((struct pbuf *)buff);
}
ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; } ETH_HandleTypeDef *getEthernetHandle() { return &EthHandle; }
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

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