diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..81afde3 --- /dev/null +++ b/Makefile @@ -0,0 +1,336 @@ +#------------------------------------------------------------------------------- +# Makefile for FSFW Example +#------------------------------------------------------------------------------- +# User-modifiable options +#------------------------------------------------------------------------------- +# Fundamentals on the build process of C/C++ Software: +# https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html + +# Make documentation: https://www.gnu.org/software/make/manual/make.pdf +# Online: https://www.gnu.org/software/make/manual/make.html +# General rules: http://make.mad-scientist.net/papers/rules-of-makefiles/#rule3 +SHELL = /bin/sh + + +#$(SHELL ./setup-siso-env.sh) +FRAMEWORK_PATH = fsfw +MISSION_PATH = mission +CONFIG_PATH = bsp_linux/fsfwconfig +#TEST_PATH = test +# Board support package path. This will generally contain code which is +# not portable and depends on the hardware. +BSP_PATH = bsp_linux +BASE_NAME = fsfw-example + +OS_FSFW = linux +BOARD = linux +OUTPUT_FOLDER = $(BOARD) + +BINARY_NAME = $(BASE_NAME)-$(BOARD) + +# Default debug level (for full debugging information) +DEBUG_LEVEL = -g3 + +# Default optimization level. +# 1. -O0 default for debugging +# 2. -Os for size +# 3. -O3/-O2 for speed and size. +OPTIMIZATION = -O0 + +# Output directories +BUILDPATH = _bin +DEPENDPATH = _dep +OBJECTPATH = _obj + +ifeq ($(MAKECMDGOALS),release) +BUILD_FOLDER = release +else +BUILD_FOLDER = debug +endif + +DEPENDDIR = $(DEPENDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER) +OBJDIR = $(OBJECTPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER) +BINDIR = $(BUILDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER) + +CLEANDEP = $(DEPENDPATH)/$(OUTPUT_FOLDER) +CLEANOBJ = $(OBJECTPATH)/$(OUTPUT_FOLDER) +CLEANBIN = $(BUILDPATH) + +#------------------------------------------------------------------------------- +# Tools and Includes +#------------------------------------------------------------------------------- +CROSS_COMPILE = + +# c++ compiler +CXX := $(CROSS_COMPILE)g++ +# c compiler +CC := $(CROSS_COMPILE)gcc +SIZE := $(CROSS_COMPILE)size + +# Empty initialization is important for submakefile handling! +CXXSRC := +CSRC := +INCLUDES := + + +# Directries where $(directoryname).mk files should be included from +SUBDIRS := $(BSP_PATH) $(CONFIG_PATH) $(MISSION_PATH) \ + $(FRAMEWORK_PATH) + +#SISODIR5 = /opt/siso +#SISODIR5_INCLUDE=/opt/siso/include +#PCODIR_1=/opt/pco_camera/pco_common/pco_include +#PCODIR_2=/opt/pco_camera/pco_common/pco_classes +#PCODIR_3=/opt/pco_camera/pco_me4/pco_classes +#PCOLIB_DIR=/opt/pco_camera/pco_common/pco_lib +#SISOLIB_DIR=/opt/siso/lib64 +#FG_LIB_PATH=/home/esbo/ESBOSW/DeviceTestsExample/mission/devices/Visible_Instrument +# This is a hack from http://make.mad-scientist.net/the-eval-function/ +# +# The problem is, that included makefiles should be aware of their relative path +# but not need to guess or hardcode it. So we set $(CURRENTPATH) for them. If +# we do this globally and the included makefiles want to include other makefiles as +# well, they would overwrite $(CURRENTPATH), screwing the include after them. +# +# By using a for-loop with an eval'd macro, we can generate the code to include all +# sub-makefiles (with the correct $(CURRENTPATH) set) before actually evaluating +# (and by this possibly changing $(CURRENTPATH)) them. +# +# This works recursively, if an included makefile wants to include, it can safely set +# $(SUBDIRS) (which has already been evaluated here) and do +# "$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))" +# $(SUBDIRS) must be relative to the project root, so to include subdir foo, set +# $(SUBDIRS) = $(CURRENTPATH)/foo. +define INCLUDE_FILE +CURRENTPATH := $S +include $(S)/$(notdir $S).mk +endef +$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE))) + +# Include all includes defined as INCLUDES=... +I_INCLUDES += $(addprefix -I, $(INCLUDES)) + +# Debug Info +# $(info $${I_INCLUDES} is [${I_INCLUDES}]) + +#------------------------------------------------------------------------------- +# Source Files +#------------------------------------------------------------------------------- +# Additional source files which were not includes by other .mk +# files are added here. +# To help Makefile find source files, the source location paths +# can be added by using the VPATH variable +# See: https://www.gnu.org/software/make/manual/html_node/General-Search.html +# It is recommended to only use VPATH to add source locations +# See: http://make.mad-scientist.net/papers/how-not-to-use-vpath/ + +# Please ensure that no files are included by both .mk file and here ! + +# All C Sources included by .mk files are assigned here +# Add the objects to sources so dependency handling works +C_OBJECTS += $(CSRC:.c=.o) + +# Objects built from Assembly source files +ASM_OBJECTS = $(ASRC:.S=.o) + +# Objects built from C++ source files +CXX_OBJECTS += $(CXXSRC:.cpp=.o) + +#------------------------------------------------------------------------------- +# Build Configuration + Output +#------------------------------------------------------------------------------- +WARNING_FLAGS = -Wall -Wshadow=local -Wextra -Wimplicit-fallthrough=1 \ + -Wno-unused-parameter -Wno-write-strings -Wno-unused-but-set-variable -Wno-unknown-pragmas +CUSTOM_DEFINES += -DAPI=LINUX -DLINUX=2 +# Flags for both c++ and c +CXXFLAGS += -I. $(OPTIMIZATION) $(DEBUG_LEVEL) $(DEPFLAGS) $(WARNING_FLAGS) \ + -fmessage-length=0 $(CUSTOM_DEFINES) $(I_INCLUDES) + +# Flags for c only +CFLAGS += +# Flags for c++ only +CPPFLAGS += -std=c++11 -fno-exceptions + +# For debugging. +# $(info $${CXXFLAGS} is [${CXXFLAGS}]) +# $(info $${CFLAGS} is [${CFLAGS}]) +# $(info $${CPPFLAGS} is [${CPPFLAGS}]) + + +# See: https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld +# Used to throw away unused code. Reduces code size significantly ! +# -Wl,--gc-sections: needs to be passed to the linker to discard unused sections +# KEEP_UNUSED_CODE = 1 +ifdef KEEP_UNUSED_CODE +PROTOTYPE_OPTIMIZATION = +UNUSED_CODE_REMOVAL = +else +PROTOTYPE_OPTIMIZATION = -ffunction-sections -fdata-sections +UNUSED_CODE_REMOVAL = -Wl,--gc-sections +# Link time optimization +# See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html for reference +# Link time is larger and size of object files can not be retrieved +# but resulting binary is smaller. Could be used in mission/deployment build +# Requires -ffunction-section in linker call +LINK_TIME_OPTIMIZATION = -flto +OPTIMIZATION += $(PROTOTYPE_OPTIMIZATION) +endif + +# Dependency Flags +# These flags tell the compiler to build dependencies +# See: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html +# Using following guide: +# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ +DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPENDDIR)/$*.d + +#-L $(SISOLIB_DIR) -L $(SISOLIB_DIR) -L $(PCOLIB_DIR) +LINKFLAGS = $(DEBUG_LEVEL) $(UNUSED_CODE_REMOVAL) $(OPTIMIZATION) -pthread +#LINKLIB = -lrt -lfglib5 -lpcocom_me4 -lclsersis -lpcolog `pkg-config --libs opencv4` +LINKLIB = -lrt +TARGET = Debug +OPTIMIZATION_MESSAGE = Off +DEBUG_MESSAGE = Off\(no -DDEBUG\) + +# Define Messages +MSG_INFO = Software: Hosted Flight Software Framework \(FSFW\) example. +MSG_TARGET = Target Build: $(TARGET) +MSG_DEPENDENCY = Collecting dependencies for: +MSG_COMPILING = Compiling: +MSG_LINKING = Linking: +MSG_DEBUG = Debug level: $(DEBUG_LEVEL), FSFW Debugging: $(DEBUG_MESSAGE) + +MSG_OPTIMIZATION = Optimization: $(OPTIMIZATION), $(OPTIMIZATION_MESSAGE) + +#------------------------------------------------------------------------------- +# Rules +#------------------------------------------------------------------------------- +# Makefile rules: https://www.gnu.org/software/make/manual/html_node/Rules.html +# This is the primary section which defines the ruleset to build +# the executable from the sources. + +# Default target +default: all + +all: debug + +# building the different builds. +release debug: executable + +# Target specific variables for release build. +release: OPTIMIZATION = -O2 +release: DEBUG_LEVEL = -g0 +release: TARGET = Release +release: OPTIMIZATION_MESSAGE = On + +# Target specific variables for debug build. +debug: CXXDEFINES += -DDEBUG +debug: DEBUG_MESSAGE = On\(-DDEBUG\) + +# Cleans all files +hardclean: + -rm -rf $(BUILDPATH) + -rm -rf $(OBJECTPATH) + -rm -rf $(DEPENDPATH) + +# Only clean files for current build +clean: + -rm -rf $(CLEANOBJ) + -rm -rf $(CLEANBIN) + -rm -rf $(CLEANDEP) + +# Only clean binaries. Useful for changing the binary type when object +# files are already compiled so complete rebuild is not necessary +cleanbin: + -rm -rf $(BUILDPATH)/$(OUTPUT_FOLDER) + +executable: $(BINDIR)/$(BINARY_NAME).elf + @echo + @echo $(MSG_INFO) + @echo $(MSG_TARGET) + @echo $(MSG_OPTIMIZATION) + @echo $(MSG_DEBUG) + +# For debugging. +# $(info $${C_OBJECTS} is [${C_OBJECTS}]) +# $(info $${CXX_OBJECTS} is [${CXX_OBJECTS}]) + +C_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(C_OBJECTS)) +CXX_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(CXX_OBJECTS)) +ASM_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(ASM_OBJECTS)) +ALL_OBJECTS_PREFIXED = $(ASM_OBJECTS_PREFIXED) $(C_OBJECTS_PREFIXED) \ + $(CXX_OBJECTS_PREFIXED) + +# Useful for debugging the Makefile +# Also see: https://www.oreilly.com/openbook/make3/book/ch12.pdf +# $$(info $${ALL_OBJECTS_PREFIXED} is [${ALL_OBJECTS_PREFIXED}]) + +# Automatic variables are used here extensively. Some of them +# are escaped($$) to suppress immediate evaluation. The most important ones are: +# $@: Name of Target (left side of rule) +# $<: Name of the first prerequisite (right side of rule) +# @^: List of all prerequisite, omitting duplicates +# @D: Directory and file-within-directory part of $@ + +# Generates binary and displays all build properties +# -p with mkdir ignores error and creates directory when needed. + +# SHOW_DETAILS = 1 + +$(BINDIR)/$(BINARY_NAME).elf: $(ALL_OBJECTS_PREFIXED) + @echo $(MSG_LINKING) Target $@ + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CXX) $(LINKFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINKLIB) +else + @$(CXX) $(LINKFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINKLIB) +endif +ifeq ($(BUILD_FOLDER), release) +# With Link Time Optimization, section size is not available + $(SIZE) $@ +else + @$(SIZE) $^ $@ +endif + + +$(OBJDIR)/%.o: %.cpp +$(OBJDIR)/%.o: %.cpp $(DEPENDDIR)/%.d | $(DEPENDDIR) + @echo + @echo $(MSG_COMPILING) $< + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< +else + @$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< +endif + + +$(OBJDIR)/%.o: %.c +$(OBJDIR)/%.o: %.c $(DEPENDDIR)/%.d | $(DEPENDDIR) + @echo + @echo $(MSG_COMPILING) $< + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $< +else + @$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $< +endif +#------------------------------------------------------------------------------- +# Dependency Handling +#------------------------------------------------------------------------------- + +# Dependency Handling according to following guide: +# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ +$(DEPENDDIR): + @mkdir -p $(@D) +DEPENDENCY_RELATIVE = $(CSRC:.c=.d) $(CXXSRC:.cpp=.d) +# This is the list of all dependencies +DEPFILES = $(addprefix $(DEPENDDIR)/, $(DEPENDENCY_RELATIVE)) +# Create subdirectories for dependencies +$(DEPFILES): + @mkdir -p $(@D) +# Include all dependencies +include $(wildcard $(DEPFILES)) + + +.PHONY: release debug hardclean clean binclean all + diff --git a/bsp_linux/CMakeLists.txt b/bsp_linux/CMakeLists.txt new file mode 100644 index 0000000..43fb5a2 --- /dev/null +++ b/bsp_linux/CMakeLists.txt @@ -0,0 +1,14 @@ +target_sources(${TARGET_NAME} + PRIVATE + main.cpp +) + +add_subdirectory(core) +add_subdirectory(fsfwconfig) +add_subdirectory(utility) +add_subdirectory(test) + +target_include_directories(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/bsp_linux/bsp_linux.mk b/bsp_linux/bsp_linux.mk new file mode 100644 index 0000000..00f8c2c --- /dev/null +++ b/bsp_linux/bsp_linux.mk @@ -0,0 +1,7 @@ +CSRC += $(wildcard $(CURRENTPATH)/*.c) +CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp) + +CSRC += $(wildcard $(CURRENTPATH)/core/*.c) +CXXSRC += $(wildcard $(CURRENTPATH)/core/*.cpp) + +CSRC += $(wildcard $(CURRENTPATH)/utility/*.c) \ No newline at end of file diff --git a/bsp_linux/core/CMakeLists.txt b/bsp_linux/core/CMakeLists.txt new file mode 100644 index 0000000..51534b8 --- /dev/null +++ b/bsp_linux/core/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(${TARGET_NAME} + PRIVATE + InitMission.cpp + ObjectFactory.cpp +) diff --git a/bsp_linux/core/InitMission.cpp b/bsp_linux/core/InitMission.cpp new file mode 100644 index 0000000..29470ba --- /dev/null +++ b/bsp_linux/core/InitMission.cpp @@ -0,0 +1,167 @@ +#include "../../bsp_linux/core/InitMission.h" +#include + +#include +#include +#include +#include +#include +#include +#include "../../bsp_linux/fsfwconfig/objects/systemObjectList.h" +#include "../../bsp_linux/fsfwconfig/OBSWConfig.h" +#include "../fsfwconfig/pollingsequence/PollingSequenceArduino.h" + +void InitMission::createTasks(){ + + /* TMTC Distribution */ + PeriodicTaskIF* distributerTask = TaskFactory::instance()-> + createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, + 0.100, nullptr); + ReturnValue_t result = distributerTask->addComponent( + objects::CCSDS_DISTRIBUTOR); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + result = distributerTask->addComponent(objects::PUS_DISTRIBUTOR); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + result = distributerTask->addComponent(objects::TM_FUNNEL); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Object add component failed" << std::endl; + } + + /* UDP bridge */ + PeriodicTaskIF* udpBridgeTask = TaskFactory::instance()->createPeriodicTask( + "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, + 0.2, nullptr); + result = udpBridgeTask->addComponent(objects::UDP_BRIDGE); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Add component UDP Unix Bridge failed" << std::endl; + } + PeriodicTaskIF* udpPollingTask = TaskFactory::instance()-> + createPeriodicTask("UDP_POLLING", 80, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr); + result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Add component UDP Polling failed" << std::endl; + } + + + + PeriodicTaskIF* eventTask = TaskFactory::instance()-> + createPeriodicTask("EVENT", 20, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.100, nullptr); + result = eventTask->addComponent(objects::EVENT_MANAGER); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + + /* PUS Services */ + PeriodicTaskIF* pusVerification = TaskFactory::instance()-> + createPeriodicTask("PUS_VERIF_1", 40, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr); + result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + PeriodicTaskIF* pusEvents = TaskFactory::instance()-> + createPeriodicTask("PUS_VERIF_1", 60, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr); + result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + PeriodicTaskIF* pusHighPrio = TaskFactory::instance()-> + createPeriodicTask("PUS_HIGH_PRIO", 50, + PeriodicTaskIF::MINIMUM_STACK_SIZE, + 0.200, nullptr); + result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + PeriodicTaskIF* pusMedPrio = TaskFactory::instance()-> + createPeriodicTask("PUS_HIGH_PRIO", 40, + PeriodicTaskIF::MINIMUM_STACK_SIZE, + 0.8, nullptr); + result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + PeriodicTaskIF* pusLowPrio = TaskFactory::instance()-> + createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, + 1.6, nullptr); + result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add component failed" << std::endl; + } + + FixedTimeslotTaskIF* arduinoTask = TaskFactory::instance()-> + createFixedTimeslotTask("ARDUINO_TASK",40, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.102, nullptr); + result = pollingSequenceArduinoFunction(arduinoTask); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::createTasks:ArduinoPST initialization failed!" + << std::endl; + } + +#if OBSW_ADD_TEST_CODE == 1 + FixedTimeslotTaskIF* testTimeslotTask = TaskFactory::instance()-> + createFixedTimeslotTask("PST_TEST_TASK", 10, + PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + result = pst::pollingSequenceTestFunction(testTimeslotTask); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::createTasks: Test PST initialization " + << "failed!" << std::endl; + } + + PeriodicTaskIF* testTask = TaskFactory::instance()-> + createPeriodicTask("TEST", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, + 1.0, nullptr); + result = testTask->addComponent(objects::TEST_TASK); + if(result!=HasReturnvaluesIF::RETURN_OK){ + sif::error << "InitMission::createTasks: Adding test task " + << "failed" << std::endl; + } + +#endif + + //Main thread sleep + sif::debug << "Starting Tasks in 2 seconds" << std::endl; + TaskFactory::delayTask(2000); + distributerTask->startTask(); + udpBridgeTask->startTask(); + udpPollingTask->startTask(); + //serializeTask->startTask(); + arduinoTask->startTask(); + + //payloadTask->startTask(); + eventTask->startTask(); + + pusVerification->startTask(); + pusEvents->startTask(); + pusHighPrio->startTask(); + pusMedPrio->startTask(); + pusLowPrio->startTask(); + +#if OBSW_ADD_TEST_CODE == 1 + testTimeslotTask->startTask(); + testTask->startTask(); +#endif + sif::debug << "Tasks started.." << std::endl; +} + + diff --git a/bsp_linux/core/InitMission.h b/bsp_linux/core/InitMission.h new file mode 100644 index 0000000..8c4788d --- /dev/null +++ b/bsp_linux/core/InitMission.h @@ -0,0 +1,8 @@ +#ifndef MISSION_CORE_INITMISSION_H_ +#define MISSION_CORE_INITMISSION_H_ + +namespace InitMission { +void createTasks(); +}; + +#endif /* MISSION_CORE_INITMISSION_H_ */ diff --git a/bsp_linux/core/ObjectFactory.cpp b/bsp_linux/core/ObjectFactory.cpp new file mode 100644 index 0000000..f97bda5 --- /dev/null +++ b/bsp_linux/core/ObjectFactory.cpp @@ -0,0 +1,86 @@ +#include "../../bsp_linux/core/ObjectFactory.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../bsp_linux/fsfwconfig/datapool/dataPoolInit.h" +#include "../../bsp_linux/fsfwconfig/objects/systemObjectList.h" +#include "../../bsp_linux/fsfwconfig/OBSWConfig.h" +#include "../../bsp_linux/fsfwconfig/tmtc/apid.h" +#include "../../bsp_linux/fsfwconfig/tmtc/pusIds.h" + +#if OBSW_ADD_TEST_CODE == 1 +#include +#endif + +void Factory::setStaticFrameworkObjectIds(){ + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + MonitoringReportContent::timeStamperId = objects::TIME_STAMPER; + + TmFunnel::downlinkDestination = objects::UDP_BRIDGE; + // No storage object for now. + TmFunnel::storageDestination = objects::NO_OBJECT; + + 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; + + TmPacketStored::timeStamperId = objects::TIME_STAMPER; +} + + + +void ObjectFactory::produce(){ + Factory::setStaticFrameworkObjectIds(); + + { + static constexpr uint8_t NUMBER_OF_POOLS = 5; + const uint16_t element_sizes[NUMBER_OF_POOLS] = {16, 32, 64, 128, 1024}; + const uint16_t n_elements[NUMBER_OF_POOLS] = {100, 50, 25, 15, 5}; + new PoolManager(objects::TC_STORE, element_sizes, + n_elements); + } + + { + static constexpr uint8_t NUMBER_OF_POOLS = 5; + const uint16_t element_sizes[NUMBER_OF_POOLS] = {16, 32, 64, 128, 1024}; + const uint16_t n_elements[NUMBER_OF_POOLS] = {100, 50, 25, 15, 5}; + new PoolManager(objects::TM_STORE, element_sizes, + n_elements); + } + + { + static constexpr uint8_t NUMBER_OF_POOLS = 6; + const uint16_t element_sizes[NUMBER_OF_POOLS] = {32, 64, 512, + 1024, 2048, 4096}; + const uint16_t n_elements[NUMBER_OF_POOLS] = {200, 100, 50, 25, 15, 5}; + new PoolManager(objects::IPC_STORE, element_sizes, + n_elements); + } + + ObjectFactory::produceGenericObjects(); + + /* TMTC Reception via UDP socket */ + new TmTcUnixUdpBridge(objects::UDP_BRIDGE, objects::CCSDS_DISTRIBUTOR, + objects::TM_STORE, objects::TC_STORE); + new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); + +#if OBSW_ADD_TEST_CODE == 1 + new TestTask(objects::TEST_TASK, false); +#endif + +} diff --git a/bsp_linux/core/ObjectFactory.h b/bsp_linux/core/ObjectFactory.h new file mode 100644 index 0000000..9bf0d68 --- /dev/null +++ b/bsp_linux/core/ObjectFactory.h @@ -0,0 +1,17 @@ +/* + * ObjectFactory.h + * + * Created on: Sep 22, 2020 + * Author: steffen + */ + +#ifndef MISSION_CORE_OBJECTFACTORY_H_ +#define MISSION_CORE_OBJECTFACTORY_H_ + + +namespace ObjectFactory { + void setStatics(); + void produce(); +}; + +#endif /* MISSION_CORE_OBJECTFACTORY_H_ */ diff --git a/bsp_linux/fsfwconfig/CMakeLists.txt b/bsp_linux/fsfwconfig/CMakeLists.txt new file mode 100644 index 0000000..8aae3e5 --- /dev/null +++ b/bsp_linux/fsfwconfig/CMakeLists.txt @@ -0,0 +1,8 @@ +target_sources(${TARGET_NAME} PRIVATE + ipc/missionMessageTypes.cpp +) + +# Add include paths for the executable +target_include_directories(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/bsp_linux/fsfwconfig/FSFWConfig.h b/bsp_linux/fsfwconfig/FSFWConfig.h new file mode 100644 index 0000000..1386bf6 --- /dev/null +++ b/bsp_linux/fsfwconfig/FSFWConfig.h @@ -0,0 +1,57 @@ +#ifndef CONFIG_FSFWCONFIG_H_ +#define CONFIG_FSFWCONFIG_H_ + +#include +#include + +//! Used to determine whether C++ ostreams are used +//! Those can lead to code bloat. +#define FSFW_CPP_OSTREAM_ENABLED 1 + +//! Reduced printout to further decrease code size +//! Be careful, this also turns off most diagnostic prinouts! +#define FSFW_ENHANCED_PRINTOUT 0 + +//! Can be used to enable additional debugging printouts for developing the FSFW +#define FSFW_PRINT_VERBOSITY_LEVEL 0 + +//! Defines the FIFO depth of each commanding service base which +//! also determines how many commands a CSB service can handle in one cycle +//! simulataneously. This will increase the required RAM for +//! each CSB service ! +#define FSFW_CSB_FIFO_DEPTH 6 + +//! If FSFW_OBJ_EVENT_TRANSLATION is set to one, +//! additional output which requires the translation files translateObjects +//! and translateEvents (and their compiled source files) +#define FSFW_OBJ_EVENT_TRANSLATION 0 + +#if FSFW_OBJ_EVENT_TRANSLATION == 1 +#define FSFW_DEBUG_OUTPUT 1 +//! Specify whether info events are printed too. +#define FSFW_DEBUG_INFO 1 +#include +#include +#else +#define FSFW_DEBUG_OUTPUT 0 +#endif + +//! When using the newlib nano library, C99 support for stdio facilities +//! will not be provided. This define should be set to 1 if this is the case. +#define FSFW_NO_C99_IO 1 + +//! Specify whether a special mode store is used for Subsystem components. +#define FSFW_USE_MODESTORE 0 + +namespace fsfwconfig { +//! Default timestamp size. The default timestamp will be an eight byte CDC +//! short timestamp. +static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8; + +//! Configure the allocated pool sizes for the event manager. +static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; +static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120; +static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; +} + +#endif /* CONFIG_FSFWCONFIG_H_ */ diff --git a/bsp_linux/fsfwconfig/OBSWConfig.h b/bsp_linux/fsfwconfig/OBSWConfig.h new file mode 100644 index 0000000..5017008 --- /dev/null +++ b/bsp_linux/fsfwconfig/OBSWConfig.h @@ -0,0 +1,15 @@ +/** + * @brief This file can be used to add preprocessor define for conditional + * code inclusion exclusion or various other project constants and + * properties in one place. + */ +#ifndef FSFWCONFIG_OBSWCONFIG_H_ +#define FSFWCONFIG_OBSWCONFIG_H_ + +#define ADD_TEST_FOLDER 0 +#define OBSW_ADD_TEST_CODE 0 + +// Define not used yet, PUS stack and TMTC tasks are always started +#define ADD_PUS_STACK 1 + +#endif /* FSFWCONFIG_OBSWCONFIG_H_ */ diff --git a/bsp_linux/fsfwconfig/datapool/dataPoolInit.cpp b/bsp_linux/fsfwconfig/datapool/dataPoolInit.cpp new file mode 100644 index 0000000..d204be5 --- /dev/null +++ b/bsp_linux/fsfwconfig/datapool/dataPoolInit.cpp @@ -0,0 +1,46 @@ +/* +* dataPoolInit.cpp +* +* brief: Initialisation function for all variables in the data pool. +* This file was auto-generated by getDataPoolFromFLPmib.py via +* the flpmib database at 2018-06-04T12:02:46+00:00. +*/ +#include "../../../bsp_linux/fsfwconfig/datapool/dataPoolInit.h" + +void dataPoolInit(std::map* pool_map) { + uint32_t testVar[1] = { 0 }; + pool_map->insert( + std::pair(datapool::DUMMY1, + new PoolEntry(testVar, 1))); + pool_map->insert( + std::pair(datapool::DUMMY2, + new PoolEntry(testVar, 1))); + pool_map->insert( + std::pair(datapool::DUMMY3, + new PoolEntry(testVar, 1))); + pool_map->insert( + std::pair(datapool::DUMMY4, + new PoolEntry(testVar, 1))); + pool_map->insert( + std::pair(datapool::DUMMY5, + new PoolEntry(testVar, 1))); + pool_map->insert( + std::pair(datapool::DUMMY6, + new PoolEntry(testVar, 1))); + int32_t testVarSigned[1] = { 0 }; + pool_map->insert( + std::pair(datapool::LIMIT_VAR, + new PoolEntry(testVarSigned, 1))); + + /*float t_Centroid_PoolId[2] = {0,0}; + pool_map->insert( + std::pair(datapool::Centroid_PoolId, + new PoolEntry(t_Centroid_PoolId, 2))); + uint32_t t_CentroidTime_PoolId[2] = {0,0}; + pool_map->insert( + std::pair(datapool::CentroidTime_PoolId, + new PoolEntry(t_CentroidTime_PoolId, 2))); +*/ + + //TODO: define your pool map entries here +} diff --git a/bsp_linux/fsfwconfig/datapool/dataPoolInit.h b/bsp_linux/fsfwconfig/datapool/dataPoolInit.h new file mode 100644 index 0000000..257295c --- /dev/null +++ b/bsp_linux/fsfwconfig/datapool/dataPoolInit.h @@ -0,0 +1,32 @@ +/* +* dataPoolInit.h +* +* brief: Initialisation function for all variables in the data pool. +* This file was auto-generated by getDataPoolFromFLPmib.py via +* the flpmib database at 2018-06-04T12:02:46+00:00. +*/ +#ifndef DATAPOOLINIT_H_ +#define DATAPOOLINIT_H_ + +#include + +namespace datapool { + enum opus_variable_id { + NO_PARAMETER = 0x0, //This PID is used to denote a non-existing param in the OBSW (NOPARAME), Size: 1 + DUMMY1 = 0x100000, + DUMMY2 = 0x100001, + DUMMY3 = 0x100002, + DUMMY4 = 0x100003, + DUMMY5 = 0x100004, + DUMMY6 = 0x100005,//TEST VAR + LIMIT_VAR = 0x100006, + TIME_STAMPER = 0x100007, + //Centroid_PoolId = 0x100008, + //CentroidTime_PoolId = 0x100009 + + //TODO: add your unique datapool Ids here + }; +} + +void dataPoolInit( std::map* pool_map ); +#endif /* DATAPOOLINIT_H_ */ diff --git a/bsp_linux/fsfwconfig/events/subsystemIdRanges.h b/bsp_linux/fsfwconfig/events/subsystemIdRanges.h new file mode 100644 index 0000000..cce3fad --- /dev/null +++ b/bsp_linux/fsfwconfig/events/subsystemIdRanges.h @@ -0,0 +1,20 @@ +/* + * subsystemIdRanges.h + * + * Created on: Jul 27, 2018 + * Author: gaisser + */ + +#ifndef FSFWCONFIG_TMTC_SUBSYSTEMIDRANGES_H_ +#define FSFWCONFIG_TMTC_SUBSYSTEMIDRANGES_H_ + +namespace SUBSYSTEM_ID { +enum { +DUMMY = 10, +//VISIBLE=11 +//TODO: add your subsystem id for your device here +}; +} + + +#endif /* FSFWCONFIG_TMTC_SUBSYSTEMIDRANGES_H_ */ diff --git a/bsp_linux/fsfwconfig/fsfwconfig.mk b/bsp_linux/fsfwconfig/fsfwconfig.mk new file mode 100644 index 0000000..31c4b0c --- /dev/null +++ b/bsp_linux/fsfwconfig/fsfwconfig.mk @@ -0,0 +1,10 @@ +CXXSRC += $(wildcard $(CURRENTPATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(CURRENTPATH)/events/*.cpp) +CXXSRC += $(wildcard $(CURRENTPATH)/ipc/*.cpp) +CXXSRC += $(wildcard $(CURRENTPATH)/objects/*.cpp) +CXXSRC += $(wildcard $(CURRENTPATH)/pollingsequence/*.cpp) + +INCLUDES += $(CURRENTPATH) +INCLUDES += $(CURRENTPATH)/events +INCLUDES += $(CURRENTPATH)/returnvalues +INCLUDES += $(CURRENTPATH)/tmtc \ No newline at end of file diff --git a/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.cpp b/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.cpp new file mode 100644 index 0000000..d962b00 --- /dev/null +++ b/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.cpp @@ -0,0 +1,16 @@ +/* + * MissionMessageTypes.cpp + * + * Created on: 17.06.2016 + * Author: baetz + */ + +#include + +void messagetypes::clearMissionMessage(CommandMessage* message) { + switch((message->getCommand()>>8) & 0xff){ + default: + message->setCommand(CommandMessage::CMD_NONE); + break; + } +} diff --git a/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.h b/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.h new file mode 100644 index 0000000..b84a2d8 --- /dev/null +++ b/bsp_linux/fsfwconfig/ipc/MissionMessageTypes.h @@ -0,0 +1,28 @@ +/* + * MissionMessageTypes.h + * + * Created on: 16.06.2016 + * Author: baetz + */ + +#ifndef FSFWCONFIG_IPC_MISSIONMESSAGETYPES_H_ +#define FSFWCONFIG_IPC_MISSIONMESSAGETYPES_H_ + +#include + +class CommandMessage; + +namespace messagetypes { +//First type must have number MESSAGE_TYPE::FW_MESSAGES_COUNT! +//Remember to add new message types to the clearMissionMessage() function below! +enum MISSION_MESSAGE_TYPE { + COSTUM_MESSAGE = FW_MESSAGES_COUNT, +}; + +void clearMissionMessage(CommandMessage* message); + +} + + + +#endif /* FSFWCONFIG_IPC_MISSIONMESSAGETYPES_H_ */ diff --git a/bsp_linux/fsfwconfig/objects/systemObjectList.h b/bsp_linux/fsfwconfig/objects/systemObjectList.h new file mode 100644 index 0000000..e1f7305 --- /dev/null +++ b/bsp_linux/fsfwconfig/objects/systemObjectList.h @@ -0,0 +1,59 @@ +#ifndef FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ +#define FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ + +#include + +namespace objects { +enum mission_objects { + UDP_BRIDGE = 0x50000300, + UDP_POLLING_TASK = 0x50000400, + TM_FUNNEL = 0x50000500, + + /****************Assembly********************/ + + SOFTWARE = 0x1, + DUMMY_ASS = 0xCAFECAFE, + + + /****************Controller******************/ + + DUMMY_CONTROLLER = 0xCAFEAFFE, + + /****************Device Handler**************/ + + DUMMY1 = 0x01, + DUMMY2 = 0x02, + DUMMY3 = 0x03, + DUMMY4 = 0x04, + DUMMY5 = 0x05, + DUMMY6 = 0x06, + DUMMY7 = 0x07, + DUMMY8 = 0x08, + + /****************MISC*********************/ + TIME_STAMPER = 0x09, + + + /**************TC Handling****************/ + CCSDS_DISTRIBUTOR = 0x10, + PUS_DISTRIBUTOR = 0x11, + + + /****** 0x49 ('I') for Communication Interfaces *****/ + //TEST_ECHO_COM_IF = 0x4900AFFE, + /**************** Test *********************/ + //TEST_DEVICE_HANDLER = 0x4400AFFE, + //TEST_TASK = 0x4400CAFE, + //TEST_DEVICE_SERIALIZE=0x4401CAFE, + /**************** PCO *********************/ + //PCO_HANDLER= 0x12, + //PCO_COMMIF=0x13, + //CENTROID_INJECTOR=0x14, + //CENTROID_WRITER = 0x15 + + //TODO: add the object ids for your device and your communication interface + +}; +} + +#endif /* FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ diff --git a/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduino.h b/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduino.h new file mode 100644 index 0000000..e0ffdf2 --- /dev/null +++ b/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduino.h @@ -0,0 +1,21 @@ +/* + * PollingSequenceCentroid.h + * + * Created on: May 1, 2021 + * Author: mala + */ + +#ifndef BSP_LINUX_FSFWCONFIG_POLLINGSEQUENCE_POLLINGSEQUENCEARDUINO_H_ +#define BSP_LINUX_FSFWCONFIG_POLLINGSEQUENCE_POLLINGSEQUENCEARDUINO_H_ + +#include +#include "../../fsfwconfig/OBSWConfig.h" +class FixedTimeslotTaskIF; + + +ReturnValue_t pollingSequenceArduinoFunction(FixedTimeslotTaskIF *thisSequence); + + + + +#endif /* BSP_LINUX_FSFWCONFIG_POLLINGSEQUENCE_POLLINGSEQUENCEARDUINO_H_ */ diff --git a/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduinoFunction.cpp b/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduinoFunction.cpp new file mode 100644 index 0000000..82afd15 --- /dev/null +++ b/bsp_linux/fsfwconfig/pollingsequence/PollingSequenceArduinoFunction.cpp @@ -0,0 +1,38 @@ +/* + * PollingSequenceCentroidFunction.cpp + * + * Created on: May 1, 2021 + * Author: mala + */ + +#include +#include +#include +#include +#include "../../../bsp_linux/fsfwconfig/objects/systemObjectList.h" +#include "../../../bsp_linux/fsfwconfig/OBSWConfig.h" +#include "PollingSequenceArduino.h" +ReturnValue_t pollingSequenceArduinoFunction( + FixedTimeslotTaskIF* thisSequence){ + uint32_t length = thisSequence->getPeriodMs(); + + //thisSequence->addSlot(objects::CENTROID_INJECTOR, length * 0, 2); + //thisSequence->addSlot(objects::CENTROID_WRITER, length * 0.1, 2); + thisSequence->addSlot(objects::ARDUINO_HANDLER, length * 0, 0); + thisSequence->addSlot(objects::ARDUINO_HANDLER, length * 0.2, 1); + thisSequence->addSlot(objects::ARDUINO_HANDLER, length * 0.4, 2); + thisSequence->addSlot(objects::ARDUINO_HANDLER, length * 0.6, 3); + //thisSequence->addSlot(objects::CENTROID_WRITER, length * 0.1, 2); + + if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + sif::error << "pollingSequenceCentroidFunction::initialize has errors!" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } +} + + + diff --git a/bsp_linux/fsfwconfig/returnvalues/classIds.h b/bsp_linux/fsfwconfig/returnvalues/classIds.h new file mode 100644 index 0000000..e25e19e --- /dev/null +++ b/bsp_linux/fsfwconfig/returnvalues/classIds.h @@ -0,0 +1,22 @@ +/* + * classIds.h + * + * Created on: 30.06.2016 + * Author: baetz + */ + +#ifndef FSFWCONFIG_RETURNVALUES_CLASSIDS_H_ +#define FSFWCONFIG_RETURNVALUES_CLASSIDS_H_ + +#include + +namespace CLASS_ID { +enum { + DUMMY_HANDLER = FW_CLASS_ID_COUNT, //DDH + //VISIBLE_HANDLER_CLASS=FW_CLASS_ID_COUNT+1 +//TODO: add your arduino handler class id +}; +} + + +#endif /* FSFWCONFIG_RETURNVALUES_CLASSIDS_H_ */ diff --git a/bsp_linux/fsfwconfig/tmtc/apid.h b/bsp_linux/fsfwconfig/tmtc/apid.h new file mode 100644 index 0000000..3c9e58d --- /dev/null +++ b/bsp_linux/fsfwconfig/tmtc/apid.h @@ -0,0 +1,19 @@ +/* + * apid.h + * + * Created on: Sep 22, 2020 + * Author: steffen + */ + +#ifndef FSFWCONFIG_TMTC_APID_H_ +#define FSFWCONFIG_TMTC_APID_H_ + +#include + +namespace apid{ +static const uint16_t APID = 0xEF; +}; + + + +#endif /* FSFWCONFIG_TMTC_APID_H_ */ diff --git a/bsp_linux/fsfwconfig/tmtc/pusIds.h b/bsp_linux/fsfwconfig/tmtc/pusIds.h new file mode 100644 index 0000000..f107cee --- /dev/null +++ b/bsp_linux/fsfwconfig/tmtc/pusIds.h @@ -0,0 +1,20 @@ +#ifndef FSFWCONFIG_TMTC_PUSIDS_H_ +#define FSFWCONFIG_TMTC_PUSIDS_H_ + +namespace pus { +enum { + 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_200 = 200 +}; + +} + + + +#endif /* FSFWCONFIG_TMTC_PUSIDS_H_ */ diff --git a/bsp_linux/main.cpp b/bsp_linux/main.cpp new file mode 100644 index 0000000..d8a57dd --- /dev/null +++ b/bsp_linux/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "../bsp_linux/fsfwconfig/datapool/dataPoolInit.h" + +#ifdef WIN32 +static const char* COMPILE_PRINTOUT = "Windows"; +#elif LINUX +static const char* COMPILE_PRINTOUT = "Linux"; +#else +static const char* COMPILE_PRINTOUT = "unknown OS"; +#endif + +// This is configured for linux without \cr +ServiceInterfaceStream sif::debug("DEBUG", false); +ServiceInterfaceStream sif::info("INFO", false); +ServiceInterfaceStream sif::warning("WARNING", false); +ServiceInterfaceStream sif::error("ERROR", false, false, true); + +ObjectManagerIF *objectManager = nullptr; + +//Initialize Data Pool +DataPool dataPool(dataPoolInit); + +#include + +int main() { + + std::cout << "-- FSFW Example (Hosted) --" << std::endl; + std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl; + std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; + + objectManager = new ObjectManager(ObjectFactory::produce); + objectManager->initialize(); + InitMission::createTasks(); + MutexExample::example(); + PusPacketCreator::createPusPacketAndPrint(); + + // Permanent loop. + for(;;) { + // sleep main thread, not needed anymore. + TaskFactory::delayTask(5000); + } + return 0; +} diff --git a/bsp_linux/utility/CMakeLists.txt b/bsp_linux/utility/CMakeLists.txt new file mode 100644 index 0000000..721ba1c --- /dev/null +++ b/bsp_linux/utility/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(${TARGET_NAME} + PUBLIC + printChar.c +) + + + diff --git a/bsp_linux/utility/printChar.c b/bsp_linux/utility/printChar.c new file mode 100644 index 0000000..634347c --- /dev/null +++ b/bsp_linux/utility/printChar.c @@ -0,0 +1,21 @@ +/* + * printChar.c + * + * Created on: Jul 30, 2018 + * Author: gaisser + */ + + + +#include +#include + + +void printChar(const char* character, bool errStream) { + if(errStream) { + fprintf( stderr, "%c", *character); + } else { + printf("%c", *character); + } +} + diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp new file mode 100644 index 0000000..4e8e77b --- /dev/null +++ b/mission/core/GenericFactory.cpp @@ -0,0 +1,67 @@ +#include "GenericFactory.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//TODO: include your headers + +void ObjectFactory::produceGenericObjects() { + /* Framework objects */ + new EventManager(objects::EVENT_MANAGER); + new HealthTable(objects::HEALTH_TABLE); + new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 0, 0, 0); + 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); + + /* PUS stack */ + new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, + apid::APID, pus::PUS_SERVICE_1, objects::TM_FUNNEL); + new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, + apid::APID, pus::PUS_SERVICE_2, 3, 10); + 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 CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, + apid::APID, pus::PUS_SERVICE_200); + + + /* Demo objects */ + + CookieIF* arduinoCookie = new ARDUINOCookie(); +//new handler and commIF + +#if OBSW_ADD_TEST_CODE == 1 + CookieIF* testCookie = new TestCookie(0); + new TestEchoComIF(objects::TEST_ECHO_COM_IF); + new TestDevice(objects::TEST_DEVICE_HANDLER, objects::TEST_ECHO_COM_IF, + testCookie, true); +#endif +} + diff --git a/mission/core/GenericFactory.h b/mission/core/GenericFactory.h new file mode 100644 index 0000000..10c741c --- /dev/null +++ b/mission/core/GenericFactory.h @@ -0,0 +1,16 @@ +#ifndef MISSION_CORE_GENERICFACTORY_H_ +#define MISSION_CORE_GENERICFACTORY_H_ + + +namespace ObjectFactory { + +/** + * @brief Produce hardware independant objects. Called by bsp specific + * object factory. + */ +void produceGenericObjects(); + +} + + +#endif /* MISSION_CORE_GENERICFACTORY_H_ */ diff --git a/mission/mission.mk b/mission/mission.mk new file mode 100644 index 0000000..d679c35 --- /dev/null +++ b/mission/mission.mk @@ -0,0 +1,16 @@ +# add main and others +CXXSRC += $(wildcard $(CURRENTPATH)/*.cpp) +CSRC += $(wildcard $(CURRENTPATH)/*.c) + +CSRC += $(wildcard $(CURRENTPATH)/core/*.c) +CXXSRC += $(wildcard $(CURRENTPATH)/core/*.cpp) + +CXXSRC += $(wildcard $(CURRENTPATH)/devices/*.cpp) +CSRC += $(wildcard $(CURRENTPATH)/devices/*.c) + +CXXSRC += $(wildcard $(CURRENTPATH)/devices/Visible_Instrument/*.cpp) +CSRC += $(wildcard $(CURRENTPATH)/devices/Visible_Instrument/*.c) + +CXXSRC += $(wildcard $(CURRENTPATH)/utility/*.cpp) +CSRC += $(wildcard $(CURRENTPATH)/utility/*.c) + diff --git a/mission/utility/PusPacketCreator.cpp b/mission/utility/PusPacketCreator.cpp new file mode 100644 index 0000000..18ade6b --- /dev/null +++ b/mission/utility/PusPacketCreator.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include +#include + +void PusPacketCreator::createPusPacketAndPrint() { + // TODO: use TC packet stored here instead.. + +// uint8_t packetStore[TcPacketBase::TC_PACKET_MIN_SIZE]; +// TcPacketBase packet(packetStore); +// packet.initSpacePacketHeader(true, true, 0x73, 25); +// packet.initializeTcPacket(0x73, 25, 0, 17, 1); +// packet.setPacketDataLength(sizeof(PUSTcDataFieldHeader) +// + TcPacketBase::CRC_SIZE-1); +// packet.setErrorControl(); +// sif::info << "PUS packet created: " << std::endl; +// arrayprinter::print(packet.getWholeData(), packet.getFullSize()); +} diff --git a/mission/utility/PusPacketCreator.h b/mission/utility/PusPacketCreator.h new file mode 100644 index 0000000..5a1f178 --- /dev/null +++ b/mission/utility/PusPacketCreator.h @@ -0,0 +1,16 @@ +/* + * PusPacketCreator.h + * + * Created on: 21.03.2019 + * Author: gaisser + */ + +#ifndef MISSION_UTILITY_PUSPACKETCREATOR_H_ +#define MISSION_UTILITY_PUSPACKETCREATOR_H_ + +class PusPacketCreator { +public: + static void createPusPacketAndPrint(); +}; + +#endif /* MISSION_UTILITY_PUSPACKETCREATOR_H_ */ diff --git a/mission/utility/TmFunnel.cpp b/mission/utility/TmFunnel.cpp new file mode 100644 index 0000000..263aff8 --- /dev/null +++ b/mission/utility/TmFunnel.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include + +object_id_t TmFunnel::downlinkDestination = objects::NO_OBJECT; +object_id_t TmFunnel::storageDestination = objects::NO_OBJECT; + +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); +} + +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; + } + TmPacketBase 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()); + sif::error << "TmFunnel::handlePacket: Error sending to downlink " + "handler" << std::endl; + return result; + } + + if(storageDestination != objects::NO_OBJECT) { + result = storageQueue->sendToDefault(message); + if(result != HasReturnvaluesIF::RETURN_OK){ + tmPool->deleteData(message->getStorageId()); + sif::error << "TmFunnel::handlePacket: Error sending to storage " + "handler" << std::endl; + return result; + } + } + return result; +} + +ReturnValue_t TmFunnel::initialize() { + + tmPool = objectManager->get(objects::TM_STORE); + if(tmPool == nullptr) { + 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; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + AcceptsTelemetryIF* tmTarget = + objectManager->get(downlinkDestination); + if(tmTarget == nullptr){ + 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; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + tmQueue->setDefaultDestination(tmTarget->getReportReceptionQueue()); + + // Storage destination is optional. + if(storageDestination == objects::NO_OBJECT) { + return SystemObject::initialize(); + } + + AcceptsTelemetryIF* storageTarget = + objectManager->get(storageDestination); + if(storageTarget != nullptr) { + storageQueue->setDefaultDestination( + storageTarget->getReportReceptionQueue()); + } + + return SystemObject::initialize(); +} diff --git a/mission/utility/TmFunnel.h b/mission/utility/TmFunnel.h new file mode 100644 index 0000000..2d4575a --- /dev/null +++ b/mission/utility/TmFunnel.h @@ -0,0 +1,50 @@ +#ifndef MISSION_UTILITY_TMFUNNEL_H_ +#define MISSION_UTILITY_TMFUNNEL_H_ + +#include +#include +#include +#include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} + +/** + * @brief TM Recipient. + * @details + * Main telemetry receiver. All generated telemetry is funneled into + * this object. + * @ingroup utility + * @author J. Meier + */ +class TmFunnel: public AcceptsTelemetryIF, + public ExecutableObjectIF, + public SystemObject { + friend void (Factory::setStaticFrameworkObjectIds)(); +public: + TmFunnel(object_id_t objectId, uint32_t messageDepth = 20); + virtual ~TmFunnel(); + + virtual MessageQueueId_t getReportReceptionQueue( + uint8_t virtualChannel = 0) override; + virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; + virtual ReturnValue_t initialize() override; + +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_ */ diff --git a/unlockRealtime b/unlockRealtime new file mode 100755 index 0000000..9b8f397 --- /dev/null +++ b/unlockRealtime @@ -0,0 +1,31 @@ +#!/bin/bash +# Run this script to unlock all permissions to run the linux binaries +# and create threads + +binaries=$(find $directory -type f -name "*.elf") + +# Set up the soft realtime limit to maximum (99) +# Please note that the hard limit needs to be set to 99 too +# for this to work (check with ulimit -Hr). +# If that has not been done yet, add +# hard rtprio 99 +# to /etc/security/limits.conf +ulimit -Sr 99 + +echo Unlocking real time permissions for binaries... + +for binary in ${binaries}; do + sudo setcap 'cap_sys_nice=eip' ${binary} + result=$? + if [ ${result} = 0 ];then + echo ${binary} was unlocked + fi +done + +# Safety issues, so this should not be done. +# sudo setcap 'cap_sys_nice=eip' /bin/bash +# result=$? +# if [ ${result} = 0 ];then +# echo /bin/bash was unlocked +# fi +