Merge branch 'mohr/rtems' into windows
This commit is contained in:
commit
81c5b2ec95
@ -153,7 +153,7 @@ if(FSFW_BUILD_TESTS)
|
||||
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||
)
|
||||
# Check whether the user has already installed Catch2 first
|
||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
|
||||
# Not installed, so use FetchContent to download and provide Catch2
|
||||
if(NOT Catch2_FOUND)
|
||||
message(
|
||||
@ -174,6 +174,27 @@ if(FSFW_BUILD_TESTS)
|
||||
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
||||
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
message(STATUS "${MSG_PREFIX} Downloading FreeRTOS with FetchContent")
|
||||
include(FetchContent)
|
||||
|
||||
set(FreeRTOS_PORT posix)
|
||||
|
||||
FetchContent_Declare(
|
||||
FreeRTOS
|
||||
GIT_REPOSITORY https://egit.irs.uni-stuttgart.de/fsfw/FreeRTOS-LTS
|
||||
GIT_TAG develop
|
||||
GIT_SUBMODULES FreeRTOS/FreeRTOS-Kernel)
|
||||
|
||||
FetchContent_MakeAvailable(FreeRTOS)
|
||||
|
||||
set(LIB_OS_NAME FreeRTOS)
|
||||
target_include_directories(FreeRTOS PUBLIC unittests/testcfg/freertos)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(FreeRTOS PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
project(${FSFW_TEST_TGT} CXX C)
|
||||
add_executable(${FSFW_TEST_TGT})
|
||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
@ -226,6 +247,7 @@ if(FSFW_FETCH_CONTENT_TARGETS)
|
||||
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
set(FSFW_CORE_INC_PATH "inc")
|
||||
@ -360,6 +382,9 @@ if(FSFW_BUILD_TESTS)
|
||||
endif()
|
||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
||||
${LIB_FSFW_NAME})
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE FreeRTOS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||
|
@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
|
||||
|
||||
#tzdata is a dependency, won't install otherwise
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync
|
||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync wget qemu-system-arm
|
||||
|
||||
RUN python3 -m pip install sphinx breathe
|
||||
|
||||
@ -21,8 +21,12 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||
cmake -B build . && \
|
||||
cmake --install build/
|
||||
|
||||
RUN wget -qO- https://buggy.irs.uni-stuttgart.de/rtems_releases/rtems6-12.2.1.tar.bz2 | tar -xj -C /opt/
|
||||
|
||||
ENV PATH="$PATH:/opt/rtems/6/bin"
|
||||
|
||||
#ssh needs a valid user to work
|
||||
RUN adduser --uid 114 jenkins
|
||||
RUN adduser -q --uid 114 jenkins
|
||||
|
||||
#add documentation server to known hosts
|
||||
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
|
||||
|
65
automation/Jenkinsfile
vendored
65
automation/Jenkinsfile
vendored
@ -1,48 +1,65 @@
|
||||
pipeline {
|
||||
environment {
|
||||
BUILDDIR = 'cmake-build-tests'
|
||||
BUILDDIR_HOST = 'cmake-build-tests-host'
|
||||
BUILDDIR_LINUX = 'cmake-build-tests-linux'
|
||||
BUILDDIR_FREERTOS = 'cmake-build-tests-freertos'
|
||||
BUILDDIR_RTEMS = 'cmake-build-tests-rtems'
|
||||
DOCDDIR = 'cmake-build-documentation'
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'fsfw-ci:d6'
|
||||
args '--network host'
|
||||
image 'fsfw-ci:d7'
|
||||
args '--network host --sysctl fs.mqueue.msg_max=100'
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage('Clean') {
|
||||
stage('Host') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR'
|
||||
}
|
||||
}
|
||||
stage('Configure') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'rm -rf $BUILDDIR_HOST'
|
||||
|
||||
dir(BUILDDIR_HOST) {
|
||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake --build . -j4'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Unittests') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Valgrind') {
|
||||
stage('Linux') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'rm -rf $BUILDDIR_LINUX'
|
||||
|
||||
dir(BUILDDIR_LINUX) {
|
||||
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
sh 'cmake --build . -j4'
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('FreeRTOS') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR_FREERTOS'
|
||||
|
||||
dir(BUILDDIR_FREERTOS) {
|
||||
sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
sh 'cmake --build . -j4'
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||
//sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('rtems') {
|
||||
steps {
|
||||
sh 'rm -rf $BUILDDIR_RTEMS'
|
||||
|
||||
dir(BUILDDIR_RTEMS) {
|
||||
sh 'cmake -DFSFW_OSAL=rtems -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=../unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake ..'
|
||||
sh 'cmake --build . -j4'
|
||||
sh 'qemu-system-aarch64 -no-reboot -nographic -serial mon:stdio -semihosting -machine virt,gic-version=3 -cpu cortex-a72 -m 4000 -kernel fsfw-tests'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Documentation') {
|
||||
when {
|
||||
branch 'development'
|
||||
|
@ -321,8 +321,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
if (mode != currentMode) {
|
||||
break;
|
||||
}
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
uint32_t currentUptime = Clock::getUptime_ms();
|
||||
if (currentUptime - timeoutStart >= childTransitionDelay) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0
|
||||
char printout[60];
|
||||
@ -346,8 +345,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
setMode(_MODE_WAIT_ON);
|
||||
break;
|
||||
case _MODE_WAIT_ON: {
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
uint32_t currentUptime = Clock::getUptime_ms();
|
||||
if (powerSwitcher != nullptr and
|
||||
currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
||||
@ -366,8 +364,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
}
|
||||
} break;
|
||||
case _MODE_WAIT_OFF: {
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
uint32_t currentUptime = Clock::getUptime_ms();
|
||||
|
||||
if (powerSwitcher == nullptr) {
|
||||
setMode(MODE_OFF);
|
||||
@ -577,7 +574,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
modeHelper.modeChanged(newMode, newSubmode);
|
||||
announceMode(false);
|
||||
}
|
||||
Clock::getUptime(&timeoutStart);
|
||||
timeoutStart = Clock::getUptime_ms();
|
||||
|
||||
if (mode == MODE_OFF and thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
|
@ -23,6 +23,7 @@ EventManager::EventManager(object_id_t setObjectId)
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
listenerList.clear();
|
||||
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
@ -61,9 +62,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener,
|
||||
if (!result.second) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t EventManager::unregisterListener(MessageQueueId_t listener) {
|
||||
return listenerList.erase(listener) == 1 ? returnvalue::OK : returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) {
|
||||
return subscribeToEventRange(listener, event);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
||||
MessageQueueId_t getEventReportQueue();
|
||||
|
||||
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
|
||||
ReturnValue_t unregisterListener(MessageQueueId_t listener) override;
|
||||
ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event);
|
||||
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
|
||||
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
|
||||
|
@ -18,6 +18,7 @@ class EventManagerIF {
|
||||
|
||||
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
|
||||
bool forwardAllButSelected = false) = 0;
|
||||
virtual ReturnValue_t unregisterListener(MessageQueueId_t listener) = 0;
|
||||
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
|
||||
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
|
||||
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
|
||||
|
@ -23,7 +23,7 @@ FailureIsolationBase::~FailureIsolationBase() {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
|
||||
manager->unregisterListener(eventQueue->getId());
|
||||
QueueFactory::instance()->deleteMessageQueue(eventQueue);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
||||
MatchTree(iterator root, uint8_t maxDepth = -1)
|
||||
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
||||
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
||||
virtual ~MatchTree() {}
|
||||
virtual ~MatchTree() { clear(); }
|
||||
virtual bool match(T number) override { return matchesTree(number); }
|
||||
bool matchesTree(T number) {
|
||||
iterator iter = this->begin();
|
||||
@ -176,6 +176,45 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
||||
return cleanUpElement(position);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
Node* localRoot = BinaryTree<SerializeableMatcherIF<T>>::rootNode;
|
||||
|
||||
if (localRoot == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* node = localRoot->left;
|
||||
|
||||
while (true) {
|
||||
if (node->left != nullptr) {
|
||||
node = node->left;
|
||||
continue;
|
||||
}
|
||||
if (node->right != nullptr) {
|
||||
node = node->right;
|
||||
continue;
|
||||
}
|
||||
if (node->parent == nullptr) {
|
||||
// this is the root node with no children
|
||||
if (node->value != nullptr) {
|
||||
cleanUpElement(iterator(node));
|
||||
}
|
||||
return;
|
||||
}
|
||||
// leaf
|
||||
{
|
||||
Node* parent = node->parent;
|
||||
if (parent->left == node) {
|
||||
parent->left = nullptr;
|
||||
} else {
|
||||
parent->right = nullptr;
|
||||
}
|
||||
cleanUpElement(iterator(node));
|
||||
node = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; }
|
||||
|
||||
bool matchSubtree(iterator iter, T number) {
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
;
|
||||
|
||||
mapIterator = healthMap.begin();
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,10 @@ InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t m
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||
InternalErrorReporter::~InternalErrorReporter() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
this->diagnosticPrintout = enable;
|
||||
|
@ -23,9 +23,17 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
|
||||
|
||||
ObjectManager::ObjectManager() = default;
|
||||
|
||||
void ObjectManager::clear() {
|
||||
if (objManagerInstance != nullptr) {
|
||||
delete objManagerInstance;
|
||||
objManagerInstance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectManager::~ObjectManager() {
|
||||
for (auto const& iter : objectList) {
|
||||
delete iter.second;
|
||||
teardown = true;
|
||||
for (auto iter = objectList.begin(); iter != objectList.end(); iter = objectList.erase(iter)) {
|
||||
delete iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +61,12 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) {
|
||||
}
|
||||
|
||||
ReturnValue_t ObjectManager::remove(object_id_t id) {
|
||||
// this function is called during destruction of System Objects
|
||||
// disabeld for teardown to avoid iterator invalidation and
|
||||
// double free
|
||||
if (teardown) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (this->getSystemObject(id) != nullptr) {
|
||||
this->objectList.erase(id);
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
|
@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF {
|
||||
using produce_function_t = void (*)(void* args);
|
||||
|
||||
/**
|
||||
* Returns the single instance of TaskFactory.
|
||||
* Returns the single instance of ObjectManager.
|
||||
* The implementation of #instance is found in its subclasses.
|
||||
* Thus, we choose link-time variability of the instance.
|
||||
*/
|
||||
static ObjectManager* instance();
|
||||
|
||||
/**
|
||||
* Deletes the single instance of ObjectManager
|
||||
*/
|
||||
static void clear();
|
||||
|
||||
void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
|
||||
|
||||
template <typename T>
|
||||
@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF {
|
||||
*/
|
||||
std::map<object_id_t, SystemObjectIF*> objectList;
|
||||
static ObjectManager* objManagerInstance;
|
||||
// used when the OM itself is deleted to modify behaviour of remove()
|
||||
// to avoid iterator invalidation and double free
|
||||
bool teardown = false;
|
||||
};
|
||||
|
||||
// Documentation can be found in the class method declaration above
|
||||
|
@ -1,10 +1,13 @@
|
||||
# Check the OS_FSFW variable
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
add_subdirectory(freertos)
|
||||
set(FSFW_OSAL_FREERTOS 1)
|
||||
elseif(FSFW_OSAL MATCHES "rtems")
|
||||
add_subdirectory(rtems)
|
||||
set(FSFW_OSAL_RTEMS 1)
|
||||
elseif(FSFW_OSAL MATCHES "linux")
|
||||
add_subdirectory(linux)
|
||||
set(FSFW_OSAL_LINUX 1)
|
||||
elseif(FSFW_OSAL MATCHES "host")
|
||||
add_subdirectory(host)
|
||||
if(WIN32)
|
||||
@ -13,16 +16,17 @@ elseif(FSFW_OSAL MATCHES "host")
|
||||
# We still need to pull in some Linux specific sources
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
||||
endif()
|
||||
|
||||
set(FSFW_OSAL_HOST 1)
|
||||
else()
|
||||
|
||||
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
||||
# Not set. Assumuing this is a host build, try to determine host OS
|
||||
if(WIN32)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(windows)
|
||||
set(FSFW_OSAL_HOST 1)
|
||||
elseif(UNIX)
|
||||
add_subdirectory(linux)
|
||||
set(FSFW_OSAL_LINUX 1)
|
||||
else()
|
||||
# MacOS or other OSes have not been tested yet / are not supported.
|
||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||
@ -31,3 +35,5 @@ else()
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h)
|
||||
|
@ -40,7 +40,7 @@ class BinarySemaphoreUsingTask : public SemaphoreIF {
|
||||
void refreshTaskHandle();
|
||||
|
||||
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
|
||||
uint32_t timeoutMs = portMAX_DELAY) override;
|
||||
uint32_t timeoutMs = 0) override;
|
||||
ReturnValue_t release() override;
|
||||
uint8_t getSemaphoreCounter() const override;
|
||||
static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle);
|
||||
|
@ -51,7 +51,7 @@ class BinarySemaphore : public SemaphoreIF {
|
||||
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
|
||||
*/
|
||||
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
|
||||
uint32_t timeoutMs = portMAX_DELAY) override;
|
||||
uint32_t timeoutMs = 0) override;
|
||||
|
||||
/**
|
||||
* Same as lockBinarySemaphore() with timeout in FreeRTOS ticks.
|
||||
|
@ -11,19 +11,6 @@
|
||||
// TODO sanitize input?
|
||||
// TODO much of this code can be reused for tick-only systems
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
timeval time_timeval;
|
||||
|
||||
ReturnValue_t result = convertTimeOfDayToTimeval(time, &time_timeval);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return setClock(&time_timeval);
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
timeval uptime = getUptime();
|
||||
|
||||
@ -44,81 +31,15 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
*uptime = getUptime();
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
timeval Clock::getUptime() {
|
||||
TickType_t ticksSinceStart = xTaskGetTickCount();
|
||||
return Timekeeper::ticksToTimeval(ticksSinceStart);
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
timeval uptime = getUptime();
|
||||
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// uint32_t Clock::getUptimeSeconds() {
|
||||
// timeval uptime = getUptime();
|
||||
// return uptime.tv_sec;
|
||||
// }
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval time_timeval;
|
||||
ReturnValue_t result = getClock_timeval(&time_timeval);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*time = time_timeval.tv_sec * 1000000 + time_timeval.tv_usec;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
timeval time_timeval;
|
||||
ReturnValue_t result = getClock_timeval(&time_timeval);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
struct tm time_tm;
|
||||
|
||||
gmtime_r(&time_timeval.tv_sec, &time_tm);
|
||||
|
||||
time->year = time_tm.tm_year + 1900;
|
||||
time->month = time_tm.tm_mon + 1;
|
||||
time->day = time_tm.tm_mday;
|
||||
|
||||
time->hour = time_tm.tm_hour;
|
||||
time->minute = time_tm.tm_min;
|
||||
time->second = time_tm.tm_sec;
|
||||
|
||||
time->usecond = time_timeval.tv_usec;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
||||
struct tm time_tm = {};
|
||||
|
||||
time_tm.tm_year = from->year - 1900;
|
||||
time_tm.tm_mon = from->month - 1;
|
||||
time_tm.tm_mday = from->day;
|
||||
|
||||
time_tm.tm_hour = from->hour;
|
||||
time_tm.tm_min = from->minute;
|
||||
time_tm.tm_sec = from->second;
|
||||
|
||||
time_t seconds = mktime(&time_tm);
|
||||
|
||||
to->tv_sec = seconds;
|
||||
to->tv_usec = from->usecond;
|
||||
// Fails in 2038..
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class CountingSemaphoreUsingTask : public SemaphoreIF {
|
||||
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
|
||||
*/
|
||||
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
|
||||
uint32_t timeoutMs = portMAX_DELAY) override;
|
||||
uint32_t timeoutMs = 0) override;
|
||||
|
||||
/**
|
||||
* Release a semaphore, increasing the number of available counting
|
||||
|
@ -56,7 +56,9 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
// start time for the first entry.
|
||||
auto slotListIter = pollingSeqTable.current;
|
||||
|
||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
ReturnValue_t result = pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
// Ignore returnvalue for now
|
||||
static_cast<void>(result);
|
||||
|
||||
// The start time for the first entry is read.
|
||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||
|
@ -22,7 +22,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
return MutexIF::MUTEX_NOT_FOUND;
|
||||
}
|
||||
// If the timeout type is BLOCKING, this will be the correct value.
|
||||
uint32_t timeout = portMAX_DELAY;
|
||||
TickType_t timeout = portMAX_DELAY;
|
||||
if (timeoutType == TimeoutType::POLLING) {
|
||||
timeout = 0;
|
||||
} else if (timeoutType == TimeoutType::WAITING) {
|
||||
|
@ -3,16 +3,16 @@
|
||||
void TaskManagement::vRequestContextSwitchFromTask() { vTaskDelay(0); }
|
||||
|
||||
void TaskManagement::requestContextSwitch(CallContext callContext = CallContext::TASK) {
|
||||
if (callContext == CallContext::ISR) {
|
||||
// This function depends on the partmacro.h definition for the specific device
|
||||
vRequestContextSwitchFromISR();
|
||||
} else {
|
||||
vRequestContextSwitchFromTask();
|
||||
}
|
||||
// if (callContext == CallContext::ISR) {
|
||||
// // This function depends on the partmacro.h definition for the specific device
|
||||
// vRequestContextSwitchFromISR();
|
||||
// } else {
|
||||
vRequestContextSwitchFromTask();
|
||||
// }
|
||||
}
|
||||
|
||||
TaskHandle_t TaskManagement::getCurrentTaskHandle() { return xTaskGetCurrentTaskHandle(); }
|
||||
|
||||
size_t TaskManagement::getTaskStackHighWatermark(TaskHandle_t task) {
|
||||
return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
|
||||
}
|
||||
// size_t TaskManagement::getTaskStackHighWatermark(TaskHandle_t task) {
|
||||
// return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
|
||||
// }
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Architecture dependant portmacro.h function call.
|
||||
* Should be implemented in bsp.
|
||||
*/
|
||||
extern "C" void vRequestContextSwitchFromISR();
|
||||
// extern "C" void vRequestContextSwitchFromISR();
|
||||
|
||||
/*!
|
||||
* Used by functions to tell if they are being called from
|
||||
@ -53,7 +53,7 @@ TaskHandle_t getCurrentTaskHandle();
|
||||
* @return Smallest value of stack remaining since the task was started in
|
||||
* words.
|
||||
*/
|
||||
size_t getTaskStackHighWatermark(TaskHandle_t task = nullptr);
|
||||
// size_t getTaskStackHighWatermark(TaskHandle_t task = nullptr);
|
||||
|
||||
}; // namespace TaskManagement
|
||||
|
||||
|
@ -15,27 +15,6 @@
|
||||
|
||||
using SystemClock = std::chrono::system_clock;
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
|
||||
#else
|
||||
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
|
||||
#endif
|
||||
/* To avoid division by zero */
|
||||
return 1;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||
host system with internet access so this is not implemented for now. */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
|
||||
#else
|
||||
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||
host system with internet access so this is not implemented for now. */
|
||||
@ -66,6 +45,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
time->tv_usec = timeUnix.tv_nsec / 1000.0;
|
||||
return returnvalue::OK;
|
||||
#else
|
||||
#warning Clock::getClock_timeval() not implemented for your platform
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
|
||||
#else
|
||||
@ -75,15 +55,6 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
if (time == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
using namespace std::chrono;
|
||||
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
timeval Clock::getUptime() {
|
||||
timeval timeval;
|
||||
#if defined(PLATFORM_WIN)
|
||||
@ -100,6 +71,7 @@ timeval Clock::getUptime() {
|
||||
timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6);
|
||||
}
|
||||
#else
|
||||
#warning Clock::getUptime() not implemented for your platform
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
|
||||
#endif
|
||||
@ -107,66 +79,3 @@ timeval Clock::getUptime() {
|
||||
return timeval;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
*uptime = getUptime();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
timeval uptime = getUptime();
|
||||
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
/* Do some magic with chrono (C++20!) */
|
||||
/* Right now, the library doesn't have the new features to get the required values yet.
|
||||
so we work around that for now. */
|
||||
auto now = SystemClock::now();
|
||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||
auto fraction = now - seconds;
|
||||
time_t tt = SystemClock::to_time_t(now);
|
||||
ReturnValue_t result = checkOrCreateClockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
MutexGuard helper(timeMutex);
|
||||
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||
// Therefore we have to use a Mutex here
|
||||
struct tm* timeInfo;
|
||||
timeInfo = gmtime(&tt);
|
||||
time->year = timeInfo->tm_year + 1900;
|
||||
time->month = timeInfo->tm_mon + 1;
|
||||
time->day = timeInfo->tm_mday;
|
||||
time->hour = timeInfo->tm_hour;
|
||||
time->minute = timeInfo->tm_min;
|
||||
time->second = timeInfo->tm_sec;
|
||||
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
||||
time->usecond = usecond.count();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
||||
struct tm time_tm {};
|
||||
|
||||
time_tm.tm_year = from->year - 1900;
|
||||
time_tm.tm_mon = from->month - 1;
|
||||
time_tm.tm_mday = from->day;
|
||||
|
||||
time_tm.tm_hour = from->hour;
|
||||
time_tm.tm_min = from->minute;
|
||||
time_tm.tm_sec = from->second;
|
||||
time_tm.tm_isdst = 0;
|
||||
|
||||
time_t seconds = timegm(&time_tm);
|
||||
|
||||
to->tv_sec = seconds;
|
||||
to->tv_usec = from->usecond;
|
||||
// Fails in 2038..
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -10,26 +10,6 @@
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
uint32_t Clock::getTicksPerSecond() {
|
||||
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
timespec timeUnix{};
|
||||
timeval timeTimeval{};
|
||||
convertTimeOfDayToTimeval(time, &timeTimeval);
|
||||
timeUnix.tv_sec = timeTimeval.tv_sec;
|
||||
timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000;
|
||||
|
||||
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
|
||||
if (status != 0) {
|
||||
// TODO errno
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
timespec timeUnix{};
|
||||
timeUnix.tv_sec = time->tv_sec;
|
||||
@ -53,104 +33,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval timeVal{};
|
||||
ReturnValue_t result = getClock_timeval(&timeVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
timeval Clock::getUptime() {
|
||||
timeval uptime{};
|
||||
auto result = getUptime(&uptime);
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Clock::getUptime: Error getting uptime" << std::endl;
|
||||
#endif
|
||||
}
|
||||
return uptime;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
// TODO This is not posix compatible and delivers only seconds precision
|
||||
// Linux specific file read but more precise.
|
||||
timeval uptime{0,0};
|
||||
double uptimeSeconds;
|
||||
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
|
||||
uptime->tv_sec = uptimeSeconds;
|
||||
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
||||
uptime.tv_sec = uptimeSeconds;
|
||||
uptime.tv_usec = uptimeSeconds * (double)1e6 - (uptime.tv_sec * 1e6);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// Wait for new FSFW Clock function delivering seconds uptime.
|
||||
// uint32_t Clock::getUptimeSeconds() {
|
||||
// //TODO This is not posix compatible and delivers only seconds precision
|
||||
// struct sysinfo sysInfo;
|
||||
// int result = sysinfo(&sysInfo);
|
||||
// if(result != 0){
|
||||
// return returnvalue::FAILED;
|
||||
// }
|
||||
// return sysInfo.uptime;
|
||||
//}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
timeval uptime{};
|
||||
ReturnValue_t result = getUptime(&uptime);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
timespec timeUnix{};
|
||||
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
||||
if (status != 0) {
|
||||
// TODO errno
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = checkOrCreateClockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
MutexGuard helper(timeMutex);
|
||||
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||
// Therefore we have to use a Mutex here
|
||||
struct std::tm* timeInfo;
|
||||
timeInfo = gmtime(&timeUnix.tv_sec);
|
||||
time->year = timeInfo->tm_year + 1900;
|
||||
time->month = timeInfo->tm_mon + 1;
|
||||
time->day = timeInfo->tm_mday;
|
||||
time->hour = timeInfo->tm_hour;
|
||||
time->minute = timeInfo->tm_min;
|
||||
time->second = timeInfo->tm_sec;
|
||||
time->usecond = timeUnix.tv_nsec / 1000.0;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
||||
std::tm fromTm{};
|
||||
// Note: Fails for years before AD
|
||||
fromTm.tm_year = from->year - 1900;
|
||||
fromTm.tm_mon = from->month - 1;
|
||||
fromTm.tm_mday = from->day;
|
||||
fromTm.tm_hour = from->hour;
|
||||
fromTm.tm_min = from->minute;
|
||||
fromTm.tm_sec = from->second;
|
||||
fromTm.tm_isdst = 0;
|
||||
|
||||
to->tv_sec = timegm(&fromTm);
|
||||
to->tv_usec = from->usecond;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return uptime;
|
||||
}
|
@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
|
||||
attributes.mq_msgsize = maxMessageSize;
|
||||
attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open
|
||||
// Set the name of the queue. The slash is mandatory!
|
||||
sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
|
||||
sprintf(name, "/FSFW_MQ%u", queueCounter++);
|
||||
|
||||
// Create a nonblocking queue if the name is available (the queue is read
|
||||
// and writable for the owner as well as the group)
|
||||
|
36
src/fsfw/osal/osal.h.in
Normal file
36
src/fsfw/osal/osal.h.in
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace osal {
|
||||
enum osalTarget{
|
||||
HOST,
|
||||
LINUX,
|
||||
WINDOWS,
|
||||
FREERTOS,
|
||||
RTEMS,
|
||||
};
|
||||
|
||||
#cmakedefine FSFW_OSAL_HOST
|
||||
#cmakedefine FSFW_OSAL_LINUX
|
||||
#cmakedefine FSFW_OSAL_WINDOWS
|
||||
#cmakedefine FSFW_OSAL_FREERTOS
|
||||
#cmakedefine FSFW_OSAL_RTEMS
|
||||
|
||||
|
||||
constexpr osalTarget getTarget() {
|
||||
#ifdef FSFW_OSAL_HOST
|
||||
return HOST;
|
||||
#endif
|
||||
#ifdef FSFW_OSAL_LINUX
|
||||
return LINUX;
|
||||
#endif
|
||||
#ifdef FSFW_OSAL_WINDOWS
|
||||
return WINDOWS;
|
||||
#endif
|
||||
#ifdef FSFW_OSAL_FREERTOS
|
||||
return FREERTOS;
|
||||
#endif
|
||||
#ifdef FSFW_OSAL_RTEMS
|
||||
return RTEMS;
|
||||
#endif
|
||||
}
|
||||
};
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <rtems/rtems/sem.h>
|
||||
|
||||
//TODO
|
||||
|
||||
BinarySemaphore::BinarySemaphore() {}
|
||||
|
||||
BinarySemaphore::~BinarySemaphore() {}
|
||||
|
@ -6,20 +6,21 @@
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void) {
|
||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||
return static_cast<uint32_t>(ticks_per_second);
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
TimeOfDay_t time_tod;
|
||||
ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
rtems_time_of_day timeRtems;
|
||||
timeRtems.year = time->year;
|
||||
timeRtems.month = time->month;
|
||||
timeRtems.day = time->day;
|
||||
timeRtems.hour = time->hour;
|
||||
timeRtems.minute = time->minute;
|
||||
timeRtems.second = time->second;
|
||||
timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6;
|
||||
timeRtems.year = time_tod.year;
|
||||
timeRtems.month = time_tod.month;
|
||||
timeRtems.day = time_tod.day;
|
||||
timeRtems.hour = time_tod.hour;
|
||||
timeRtems.minute = time_tod.minute;
|
||||
timeRtems.second = time_tod.second;
|
||||
timeRtems.ticks = static_cast<uint64_t>(time_tod.usecond) * rtems_clock_get_ticks_per_second() / 1e6;
|
||||
rtems_status_code status = rtems_clock_set(&timeRtems);
|
||||
switch (status) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
@ -33,27 +34,6 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
timespec newTime;
|
||||
newTime.tv_sec = time->tv_sec;
|
||||
if (time->tv_usec < 0) {
|
||||
// better returnvalue.
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
|
||||
|
||||
ISR_lock_Context context;
|
||||
_TOD_Lock();
|
||||
_TOD_Acquire(&context);
|
||||
Status_Control status = _TOD_Set(&newTime, &context);
|
||||
_TOD_Unlock();
|
||||
if (status == STATUS_SUCCESSFUL) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
// better returnvalue
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
// Callable from ISR
|
||||
rtems_status_code status = rtems_clock_get_tod_timeval(time);
|
||||
@ -67,86 +47,13 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
timeval Clock::getUptime() {
|
||||
// According to docs.rtems.org for rtems 5 this method is more accurate than
|
||||
// rtems_clock_get_ticks_since_boot
|
||||
timeval time_timeval;
|
||||
timespec time;
|
||||
rtems_status_code status = rtems_clock_get_uptime(&time);
|
||||
uptime->tv_sec = time.tv_sec;
|
||||
time.tv_nsec = time.tv_nsec / 1000;
|
||||
uptime->tv_usec = time.tv_nsec;
|
||||
switch (status) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return returnvalue::OK;
|
||||
default:
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
// This counter overflows after 50 days
|
||||
*uptimeMs = rtems_clock_get_ticks_since_boot();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval temp_time;
|
||||
rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time);
|
||||
*time = ((uint64_t)temp_time.tv_sec * 1000000) + temp_time.tv_usec;
|
||||
switch (returnValue) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return returnvalue::OK;
|
||||
default:
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
/* For all but the last field, the struct will be filled with the correct values */
|
||||
rtems_time_of_day timeRtems;
|
||||
rtems_status_code status = rtems_clock_get_tod(&timeRtems);
|
||||
switch (status) {
|
||||
case RTEMS_SUCCESSFUL: {
|
||||
/* The last field now contains the RTEMS ticks of the seconds from 0
|
||||
to rtems_clock_get_ticks_per_second() minus one.
|
||||
We calculate the microseconds accordingly */
|
||||
time->day = timeRtems.day;
|
||||
time->hour = timeRtems.hour;
|
||||
time->minute = timeRtems.minute;
|
||||
time->month = timeRtems.month;
|
||||
time->second = timeRtems.second;
|
||||
time->usecond =
|
||||
static_cast<float>(timeRtems.ticks) / rtems_clock_get_ticks_per_second() * 1e6;
|
||||
time->year = timeRtems.year;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case RTEMS_NOT_DEFINED:
|
||||
/* System date and time is not set */
|
||||
return returnvalue::FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
/* time_buffer is NULL */
|
||||
return returnvalue::FAILED;
|
||||
default:
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
||||
// Fails in 2038..
|
||||
rtems_time_of_day timeRtems;
|
||||
timeRtems.year = from->year;
|
||||
timeRtems.month = from->month;
|
||||
timeRtems.day = from->day;
|
||||
timeRtems.hour = from->hour;
|
||||
timeRtems.minute = from->minute;
|
||||
timeRtems.second = from->second;
|
||||
timeRtems.ticks = from->usecond * getTicksPerSecond() / 1e6;
|
||||
to->tv_sec = _TOD_To_seconds(&timeRtems);
|
||||
to->tv_usec = from->usecond;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
time_timeval.tv_sec = time.tv_sec;
|
||||
time_timeval.tv_usec = time.tv_nsec / 1000;
|
||||
return time_timeval;
|
||||
}
|
@ -93,8 +93,8 @@ ReturnValue_t CpuUsage::serialize(uint8_t** buffer, size_t* size, size_t maxSize
|
||||
streamEndianness);
|
||||
}
|
||||
|
||||
uint32_t CpuUsage::getSerializedSize() const {
|
||||
uint32_t size = 0;
|
||||
size_t CpuUsage::getSerializedSize() const {
|
||||
size_t size = 0;
|
||||
|
||||
size += sizeof(timeSinceLastReset);
|
||||
size += SerialArrayListAdapter<ThreadData>::getSerializedSize(&threadData);
|
||||
@ -136,8 +136,8 @@ ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, si
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
uint32_t CpuUsage::ThreadData::getSerializedSize() const {
|
||||
uint32_t size = 0;
|
||||
size_t CpuUsage::ThreadData::getSerializedSize() const {
|
||||
size_t size = 0;
|
||||
|
||||
size += sizeof(id);
|
||||
size += MAX_LENGTH_OF_THREAD_NAME;
|
||||
|
@ -35,10 +35,9 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
|
||||
return OUT_OF_PROXIES;
|
||||
case INTERNAL_ERROR_INVALID_GLOBAL_ID:
|
||||
return INVALID_GLOBAL_ID;
|
||||
#ifndef STM32H743ZI_NUCLEO
|
||||
case INTERNAL_ERROR_BAD_STACK_HOOK:
|
||||
return BAD_STACK_HOOK;
|
||||
#endif
|
||||
//TODO this one is not there anymore in rtems-6 (5 as well?)
|
||||
//case INTERNAL_ERROR_BAD_STACK_HOOK:
|
||||
// return BAD_STACK_HOOK;
|
||||
// case INTERNAL_ERROR_BAD_ATTRIBUTES:
|
||||
// return BAD_ATTRIBUTES;
|
||||
// case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
|
||||
|
@ -18,7 +18,9 @@ SemaphoreFactory* SemaphoreFactory::instance() {
|
||||
}
|
||||
|
||||
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
|
||||
return new BinarySemaphore();
|
||||
return nullptr;
|
||||
//TODO
|
||||
//return new BinarySemaphore();
|
||||
}
|
||||
|
||||
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount,
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
|
||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||
|
||||
@ -180,7 +180,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
||||
if (CRC::crc16ccitt(data, size) != 0) {
|
||||
return CONTAINED_TC_CRC_MISSMATCH;
|
||||
}
|
||||
|
||||
|
||||
// store currentPacket and receive the store address
|
||||
store_address_t addr{};
|
||||
if (tcStore->addData(&addr, data, size) != returnvalue::OK ||
|
||||
|
@ -33,13 +33,12 @@ ReturnValue_t Service9TimeManagement::setTime() {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t formerUptime;
|
||||
Clock::getUptime(&formerUptime);
|
||||
// TODO maybe switch to getClock_usecs to report more meaningful data
|
||||
uint32_t formerUptime = Clock::getUptime_ms();
|
||||
result = Clock::setClock(&timeToSet);
|
||||
|
||||
if (result == returnvalue::OK) {
|
||||
uint32_t newUptime;
|
||||
Clock::getUptime(&newUptime);
|
||||
uint32_t newUptime = Clock::getUptime_ms();
|
||||
triggerEvent(CLOCK_SET, newUptime, formerUptime);
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
|
@ -91,11 +91,10 @@ void Subsystem::performChildOperation() {
|
||||
}
|
||||
if (currentSequenceIterator->getWaitSeconds() != 0) {
|
||||
if (uptimeStartTable == 0) {
|
||||
Clock::getUptime(&uptimeStartTable);
|
||||
uptimeStartTable = Clock::getUptime_ms();
|
||||
return;
|
||||
} else {
|
||||
uint32_t uptimeNow;
|
||||
Clock::getUptime(&uptimeNow);
|
||||
uint32_t uptimeNow = Clock::getUptime_ms();
|
||||
if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) {
|
||||
return;
|
||||
}
|
||||
|
@ -198,10 +198,9 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSw
|
||||
} else {
|
||||
if ((*uptimeOfSwitching == INVALID_UPTIME)) {
|
||||
powerSwitcher->sendSwitchCommand(number, state);
|
||||
Clock::getUptime(uptimeOfSwitching);
|
||||
*uptimeOfSwitching = Clock::getUptime_ms();
|
||||
} else {
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
uint32_t currentUptime = Clock::getUptime_ms();
|
||||
if (currentUptime - *uptimeOfSwitching > powerSwitcher->getSwitchDelayMs()) {
|
||||
*uptimeOfSwitching = INVALID_UPTIME;
|
||||
if (healthHelper.healthTable->isHealthy(getObjectId())) {
|
||||
|
@ -552,10 +552,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short*
|
||||
if (to == nullptr or from == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint16_t days = (from->dayMSB << 8) + from->dayLSB;
|
||||
if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
int32_t days = (from->dayMSB << 8) + from->dayLSB;
|
||||
days -= DAYS_CCSDS_TO_UNIX_EPOCH;
|
||||
to->tv_sec = days * SECONDS_PER_DAY;
|
||||
uint32_t msDay =
|
||||
|
@ -14,8 +14,10 @@
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
// https://xkcd.com/927/
|
||||
typedef struct {
|
||||
uint32_t year; //!< Year, A.D.
|
||||
uint32_t month; //!< Month, 1 .. 12.
|
||||
@ -26,14 +28,6 @@ class Clock {
|
||||
uint32_t usecond; //!< Microseconds, 0 .. 999999
|
||||
} TimeOfDay_t;
|
||||
|
||||
/**
|
||||
* This method returns the number of clock ticks per second.
|
||||
* In RTEMS, this is typically 1000.
|
||||
* @return The number of ticks.
|
||||
*
|
||||
* @deprecated, we should not worry about ticks, but only time
|
||||
*/
|
||||
static uint32_t getTicksPerSecond();
|
||||
/**
|
||||
* This system call sets the system time.
|
||||
* To set the time, it uses a TimeOfDay_t struct.
|
||||
@ -61,13 +55,8 @@ class Clock {
|
||||
/**
|
||||
* Get the time since boot in a timeval struct
|
||||
*
|
||||
* @param[out] time A pointer to a timeval struct where the uptime is stored.
|
||||
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||
*
|
||||
* @deprecated, I do not think this should be able to fail, use timeval getUptime()
|
||||
* @return a timeval struct where the uptime is stored
|
||||
*/
|
||||
static ReturnValue_t getUptime(timeval *uptime);
|
||||
|
||||
static timeval getUptime();
|
||||
|
||||
/**
|
||||
@ -79,7 +68,7 @@ class Clock {
|
||||
* @param ms uptime in ms
|
||||
* @return returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getUptime(uint32_t *uptimeMs);
|
||||
static uint32_t getUptime_ms();
|
||||
|
||||
/**
|
||||
* Returns the time in microseconds since an OS-defined epoch.
|
||||
@ -90,6 +79,7 @@ class Clock {
|
||||
* - Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getClock_usecs(uint64_t *time);
|
||||
|
||||
/**
|
||||
* Returns the time in a TimeOfDay_t struct.
|
||||
* @param time A pointer to a TimeOfDay_t struct.
|
||||
@ -106,6 +96,7 @@ class Clock {
|
||||
* @return
|
||||
*/
|
||||
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
|
||||
|
||||
/**
|
||||
* Converts a time of day struct to POSIX seconds.
|
||||
* @param time The time of day as input
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "fsfw/ipc/MutexGuard.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
@ -53,34 +54,74 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
|
||||
struct tm* timeInfo;
|
||||
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
|
||||
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
|
||||
// this implementation
|
||||
ReturnValue_t result = checkOrCreateClockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||
// Therefore we have to use a Mutex here
|
||||
MutexGuard helper(timeMutex);
|
||||
struct tm time_tm;
|
||||
// WINDOWS does not provide gmtime_r, but gmtime_s
|
||||
#ifdef PLATFORM_WIN
|
||||
time_t time;
|
||||
time = from->tv_sec;
|
||||
timeInfo = gmtime(&time);
|
||||
errno_t result = gmtime_s(&time_tm, &from->tv_sec);
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#else
|
||||
timeInfo = gmtime(&from->tv_sec);
|
||||
void* result = gmtime_r(&from->tv_sec, &time_tm);
|
||||
|
||||
if (result == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
to->year = timeInfo->tm_year + 1900;
|
||||
to->month = timeInfo->tm_mon + 1;
|
||||
to->day = timeInfo->tm_mday;
|
||||
to->hour = timeInfo->tm_hour;
|
||||
to->minute = timeInfo->tm_min;
|
||||
to->second = timeInfo->tm_sec;
|
||||
|
||||
to->year = time_tm.tm_year + 1900;
|
||||
to->month = time_tm.tm_mon + 1;
|
||||
to->day = time_tm.tm_mday;
|
||||
to->hour = time_tm.tm_hour;
|
||||
to->minute = time_tm.tm_min;
|
||||
to->second = time_tm.tm_sec;
|
||||
to->usecond = from->tv_usec;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
||||
struct tm time_tm = {};
|
||||
|
||||
time_tm.tm_year = from->year - 1900;
|
||||
time_tm.tm_mon = from->month - 1;
|
||||
time_tm.tm_mday = from->day;
|
||||
|
||||
time_tm.tm_hour = from->hour;
|
||||
time_tm.tm_min = from->minute;
|
||||
time_tm.tm_sec = from->second;
|
||||
|
||||
time_tm.tm_isdst = 0;
|
||||
|
||||
// Windows:
|
||||
// time_t seconds = _mkgmtime(&time_tm);
|
||||
// Glibc:
|
||||
// time_t seconds = timegm(&time_tm);
|
||||
// Portable (?)
|
||||
char* tz;
|
||||
tz = getenv("TZ");
|
||||
setenv("TZ", "", 1);
|
||||
tzset();
|
||||
time_t seconds = mktime(&time_tm);
|
||||
if (tz)
|
||||
setenv("TZ", tz, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
tzset();
|
||||
to->tv_sec = seconds;
|
||||
to->tv_usec = from->usecond;
|
||||
|
||||
if (seconds == (time_t) -1) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::checkOrCreateClockMutex() {
|
||||
if (timeMutex == nullptr) {
|
||||
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||
@ -94,3 +135,37 @@ ReturnValue_t Clock::checkOrCreateClockMutex() {
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
timeval time_timeval;
|
||||
ReturnValue_t result = getClock_timeval(&time_timeval);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return convertTimevalToTimeOfDay(&time_timeval, time);
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval timeVal{};
|
||||
ReturnValue_t result = getClock_timeval(&timeVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
timeval timeTimeval{};
|
||||
ReturnValue_t result = convertTimeOfDayToTimeval(time, &timeTimeval);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return setClock(&timeTimeval);
|
||||
}
|
||||
uint32_t Clock::getUptime_ms() {
|
||||
timeval uptime = getUptime();
|
||||
// TODO verify that overflow is correct
|
||||
return uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
|
||||
}
|
@ -7,9 +7,9 @@ Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
|
||||
Countdown::~Countdown() {}
|
||||
|
||||
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
|
||||
ReturnValue_t returnValue = Clock::getUptime(&startTime);
|
||||
startTime = Clock::getUptime_ms();
|
||||
timeout = milliseconds;
|
||||
return returnValue;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
bool Countdown::hasTimedOut() const {
|
||||
@ -39,7 +39,5 @@ uint32_t Countdown::getRemainingMillis() const {
|
||||
}
|
||||
|
||||
uint32_t Countdown::getCurrentTime() const {
|
||||
uint32_t currentTime;
|
||||
Clock::getUptime(¤tTime);
|
||||
return currentTime;
|
||||
return Clock::getUptime_ms();
|
||||
}
|
||||
|
@ -9,10 +9,10 @@
|
||||
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
|
||||
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
|
||||
// Measures start time on initialization.
|
||||
Clock::getUptime(&startTime);
|
||||
startTime = Clock::getUptime();
|
||||
}
|
||||
|
||||
void Stopwatch::start() { Clock::getUptime(&startTime); }
|
||||
void Stopwatch::start() { startTime = Clock::getUptime(); }
|
||||
|
||||
dur_millis_t Stopwatch::stop(bool display) {
|
||||
stopInternal();
|
||||
@ -62,7 +62,6 @@ void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) {
|
||||
StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
|
||||
|
||||
void Stopwatch::stopInternal() {
|
||||
timeval endTime;
|
||||
Clock::getUptime(&endTime);
|
||||
timeval endTime = Clock::getUptime();
|
||||
elapsedTime = endTime - startTime;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
#include "fsfw/platform.h"
|
||||
|
||||
|
@ -348,7 +348,7 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt
|
||||
sendResult = commandQueue->sendMessage(iter.value->first, &command);
|
||||
}
|
||||
if (sendResult == returnvalue::OK) {
|
||||
Clock::getUptime(&iter->second.uptimeOfStart);
|
||||
iter->second.uptimeOfStart = Clock::getUptime_ms();
|
||||
iter->second.step = 0;
|
||||
iter->second.subservice = tcReader.getSubService();
|
||||
iter->second.command = command.getCommand();
|
||||
@ -434,8 +434,7 @@ inline void CommandingServiceBase::doPeriodicOperation() {}
|
||||
MessageQueueId_t CommandingServiceBase::getCommandQueue() { return commandQueue->getId(); }
|
||||
|
||||
void CommandingServiceBase::checkTimeout() {
|
||||
uint32_t uptime;
|
||||
Clock::getUptime(&uptime);
|
||||
uint32_t uptime = Clock::getUptime_ms();
|
||||
CommandMapIter iter;
|
||||
for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) {
|
||||
if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {
|
||||
|
@ -20,7 +20,9 @@ add_subdirectory(globalfunctions)
|
||||
add_subdirectory(timemanager)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(cfdp)
|
||||
IF(NOT FSFW_OSAL MATCHES "rtems")
|
||||
add_subdirectory(hal)
|
||||
ENDIF()
|
||||
add_subdirectory(internalerror)
|
||||
add_subdirectory(devicehandler)
|
||||
add_subdirectory(tmtcservices)
|
||||
|
@ -10,16 +10,120 @@
|
||||
|
||||
#define CATCH_CONFIG_COLOUR_WINDOWS
|
||||
|
||||
#include <fsfw/osal/osal.h>
|
||||
|
||||
#include <catch2/catch_session.hpp>
|
||||
|
||||
#ifdef FSFW_OSAL_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
#include "task.h"
|
||||
#endif
|
||||
|
||||
extern int customSetup();
|
||||
extern int customTeardown();
|
||||
|
||||
#ifdef FSFW_OSAL_FREERTOS
|
||||
struct Taskparameters {
|
||||
int argc;
|
||||
char** argv;
|
||||
TaskHandle_t catchTask;
|
||||
} taskParameters;
|
||||
|
||||
void unittestTaskFunction(void* pvParameters) {
|
||||
Taskparameters* parameters = (Taskparameters*)pvParameters;
|
||||
|
||||
int result = Catch::Session().run(parameters->argc, parameters->argv);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
vTaskSuspendAll();
|
||||
vTaskDelete(parameters->catchTask);
|
||||
customTeardown();
|
||||
exit(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FSFW_OSAL_RTEMS
|
||||
#include <signal.h>
|
||||
|
||||
int sigaltstack(const stack_t* ss, stack_t* old_ss) { return 0; }
|
||||
extern "C" {
|
||||
|
||||
void exit_qemu_failing(int error) {
|
||||
asm(/* 0x20026 == ADP_Stopped_ApplicationExit */
|
||||
"mov x1, #0x26\n\t"
|
||||
"movk x1, #2, lsl #16\n\t"
|
||||
"str x1, [sp,#0]\n\t");
|
||||
|
||||
/* Exit status code. Host QEMU process exits with that status. */
|
||||
asm("mov x0, %[error]\n\t" : : [error] "r" (error));
|
||||
asm(
|
||||
"str x0, [sp,#8]\n\t"
|
||||
|
||||
/* x1 contains the address of parameter block.
|
||||
* Any memory address could be used. */
|
||||
"mov x1, sp\n\t"
|
||||
|
||||
/* SYS_EXIT */
|
||||
"mov w0, #0x18\n\t"
|
||||
|
||||
/* Do the semihosting call on A64. */
|
||||
"hlt 0xf000\n\t"
|
||||
);
|
||||
}
|
||||
|
||||
#include <rtemsConfig.h>
|
||||
|
||||
void user_handle_fatal(Internal_errors_Source source, bool internal, Internal_errors_t error_code){
|
||||
if ( source == RTEMS_FATAL_SOURCE_EXIT ) {
|
||||
if (error_code != 0) {
|
||||
printk("*** EXIT STATUS NOT ZERO ***\n");
|
||||
printk("Quitting qemu with exit code %i\n", error_code);
|
||||
exit_qemu_failing(error_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtems_task Init(rtems_task_argument ignored) {
|
||||
rtems_time_of_day now;
|
||||
now.year = 2023;
|
||||
now.month = 1;
|
||||
now.day = 15;
|
||||
now.hour = 0;
|
||||
now.minute = 0;
|
||||
now.second = 0;
|
||||
now.ticks = 0;
|
||||
rtems_clock_set(&now);
|
||||
customSetup();
|
||||
const char* argv[] = {"fsfw-test", ""};
|
||||
int result = Catch::Session().run(1, argv);
|
||||
customTeardown();
|
||||
exit(result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
customSetup();
|
||||
|
||||
int result = 0;
|
||||
|
||||
#ifdef FSFW_OSAL_FREERTOS
|
||||
xTaskCreate(
|
||||
unittestTaskFunction, /* The function that implements the task. */
|
||||
"Unittests", /* The text name assigned to the task - for debug only as it is not used by the
|
||||
kernel. */
|
||||
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
|
||||
&taskParameters, /* The parameter passed to the task - not used in this simple case. */
|
||||
1, /* The priority assigned to the task. */
|
||||
&taskParameters.catchTask); /* The task handle is not required, so NULL is passed. */
|
||||
taskParameters.argc = argc;
|
||||
taskParameters.argv = argv;
|
||||
vTaskStartScheduler();
|
||||
#else
|
||||
// Catch internal function call
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
result = Catch::Session().run(argc, argv);
|
||||
#endif
|
||||
|
||||
// global clean-up
|
||||
customTeardown();
|
||||
|
@ -31,4 +31,7 @@ int customSetup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int customTeardown() { return 0; }
|
||||
int customTeardown() {
|
||||
ObjectManager::clear();
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ DeviceHandlerCommander::DeviceHandlerCommander(object_id_t objectId)
|
||||
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
DeviceHandlerCommander::~DeviceHandlerCommander() {}
|
||||
DeviceHandlerCommander::~DeviceHandlerCommander() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerCommander::performOperation(uint8_t operationCode) {
|
||||
readCommandQueue();
|
||||
|
@ -1,2 +1,5 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestSemaphore.cpp
|
||||
TestClock.cpp)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestClock.cpp)
|
||||
|
||||
if(FSFW_OSAL MATCHES "linux" OR FSFW_OSAL MATCHES "freertos")
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE TestSemaphore.cpp)
|
||||
endif()
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||
#include <fsfw/timemanager/Clock.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <array>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
@ -7,6 +8,8 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
//TODO setClock()
|
||||
|
||||
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
||||
SECTION("Test getClock") {
|
||||
timeval time;
|
||||
@ -21,7 +24,7 @@ TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
||||
// We require timeOfDayAsTimeval to be larger than time as it
|
||||
// was request a few ns later
|
||||
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
|
||||
CHECK(difference >= 0.0);
|
||||
CHECK(difference >= 0);
|
||||
CHECK(difference <= 0.005);
|
||||
|
||||
// Conversion in the other direction
|
||||
|
@ -1,46 +1,34 @@
|
||||
|
||||
#ifdef LINUX
|
||||
|
||||
/*
|
||||
#include <fsfw/osal/osal.h>
|
||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "core/CatchDefinitions.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
TEST_CASE("Binary Semaphore Test" , "[BinSemaphore]") {
|
||||
//perform set-up here
|
||||
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->
|
||||
createBinarySemaphore();
|
||||
REQUIRE(binSemaph != nullptr);
|
||||
SECTION("Simple Test") {
|
||||
// set-up is run for each section
|
||||
REQUIRE(binSemaph->getSemaphoreCounter() == 1);
|
||||
REQUIRE(binSemaph->release() ==
|
||||
static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
|
||||
REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) ==
|
||||
result::OK);
|
||||
{
|
||||
// not precise enough on linux.. should use clock instead..
|
||||
//Stopwatch stopwatch(false);
|
||||
//REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
|
||||
// SemaphoreIF::SEMAPHORE_TIMEOUT);
|
||||
//dur_millis_t time = stopwatch.stop();
|
||||
//CHECK(time == 5);
|
||||
}
|
||||
REQUIRE(binSemaph->getSemaphoreCounter() == 0);
|
||||
REQUIRE(binSemaph->release() == result::OK);
|
||||
}
|
||||
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
|
||||
// perform tear-down here
|
||||
|
||||
TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
|
||||
// perform set-up here
|
||||
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
REQUIRE(binSemaph != nullptr);
|
||||
SECTION("Simple Test") {
|
||||
// set-up is run for each section
|
||||
REQUIRE(binSemaph->getSemaphoreCounter() == 1);
|
||||
REQUIRE(binSemaph->release() == static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
|
||||
REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) == returnvalue::OK);
|
||||
{
|
||||
// not precise enough on linux.. should use clock instead..
|
||||
// Stopwatch stopwatch(false);
|
||||
// REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
|
||||
// SemaphoreIF::SEMAPHORE_TIMEOUT);
|
||||
// dur_millis_t time = stopwatch.stop();
|
||||
// CHECK(time == 5);
|
||||
}
|
||||
REQUIRE(binSemaph->getSemaphoreCounter() == 0);
|
||||
REQUIRE(binSemaph->release() == returnvalue::OK);
|
||||
}
|
||||
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
|
||||
// perform tear-down here
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Counting Semaphore Test" , "[CountingSemaph]") {
|
||||
SECTION("Simple Test") {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") {
|
||||
SECTION("Simple Test") {}
|
||||
}
|
102
unittests/testcfg/freertos/FreeRTOSConfig.h
Normal file
102
unittests/testcfg/freertos/FreeRTOSConfig.h
Normal file
@ -0,0 +1,102 @@
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
#define configUSE_TICKLESS_IDLE 0
|
||||
#define configTICK_RATE_HZ 1000
|
||||
#define configMAX_PRIORITIES 5
|
||||
#define configMINIMAL_STACK_SIZE ((unsigned short)PTHREAD_STACK_MIN)
|
||||
#define configMAX_TASK_NAME_LEN 16
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
#define configUSE_TASK_NOTIFICATIONS 1
|
||||
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_RECURSIVE_MUTEXES 0
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
|
||||
#define configQUEUE_REGISTRY_SIZE 20
|
||||
#define configUSE_QUEUE_SETS 0
|
||||
#define configUSE_TIME_SLICING 0
|
||||
#define configUSE_NEWLIB_REENTRANT 0
|
||||
#define configENABLE_BACKWARD_COMPATIBILITY 1
|
||||
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
|
||||
#define configUSE_MINI_LIST_ITEM 1
|
||||
#define configSTACK_DEPTH_TYPE uint16_t
|
||||
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 1
|
||||
|
||||
/* Memory allocation related definitions. */
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#define configTOTAL_HEAP_SIZE ((size_t)(1024 * 1024))
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 1
|
||||
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
|
||||
|
||||
/* Hook function related definitions. */
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||
#define configUSE_SB_COMPLETED_CALLBACK 0
|
||||
|
||||
/* Run time and task stats gathering related definitions. */
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||
|
||||
/* Co-routine related definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES 1
|
||||
|
||||
/* Software timer related definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY 3
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
/* Interrupt nesting behaviour configuration. */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||
|
||||
/* Define to trap errors during development. */
|
||||
//#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
|
||||
|
||||
/* FreeRTOS MPU specific definitions. */
|
||||
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
|
||||
#define configTOTAL_MPU_REGIONS 8 /* Default value. */
|
||||
#define configTEX_S_C_B_FLASH 0x07UL /* Default value. */
|
||||
#define configTEX_S_C_B_SRAM 0x07UL /* Default value. */
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
|
||||
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
|
||||
#define configENABLE_ERRATA_837070_WORKAROUND 1
|
||||
|
||||
/* ARMv8-M secure side port related definitions. */
|
||||
#define secureconfigMAX_SECURE_CONTEXTS 5
|
||||
|
||||
/* Optional functions - most linkers will remove unused functions anyway. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_xResumeFromISR 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 0
|
||||
#define INCLUDE_eTaskGetState 0
|
||||
#define INCLUDE_xEventGroupSetBitFromISR 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 0
|
||||
#define INCLUDE_xTaskAbortDelay 0
|
||||
#define INCLUDE_xTaskGetHandle 0
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
|
||||
/* A header file that defines trace macro can be included here. */
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
@ -0,0 +1,3 @@
|
||||
add_compile_options("-mcpu=cortex-a72" "-I/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib/include")
|
||||
|
||||
add_link_options("-B/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib" "-qrtems")
|
36
unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake
Normal file
36
unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake
Normal file
@ -0,0 +1,36 @@
|
||||
## the name of the target operating system
|
||||
set(CMAKE_SYSTEM_NAME a72_lp64_qemu)
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR a72)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
set(CMAKE_C_COMPILER aarch64-rtems6-gcc)
|
||||
set(CMAKE_CXX_COMPILER aarch64-rtems6-g++)
|
||||
|
||||
# built in tests fail
|
||||
set(CMAKE_C_COMPILER_WORKS 1)
|
||||
set(CMAKE_CXX_COMPILER_WORKS 1)
|
||||
|
||||
# adjust the default behavior of the FIND_XXX() commands:
|
||||
# search programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
|
||||
# search headers and libraries in the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# ignore host installed libraries
|
||||
# makes find_package() ignore the <package>Config.cmake files
|
||||
set(CMAKE_IGNORE_PATH /usr/local)
|
||||
|
||||
|
||||
# supress errors
|
||||
add_compile_definitions("__STDC_VERSION__")
|
||||
|
||||
# make newlib behave like glib with an intercepted cmath
|
||||
add_compile_options("-I${CMAKE_SOURCE_DIR}/unittests/testcfg/rtems/include")
|
||||
|
||||
# we supply an a72_lp64_qemu.cmake there
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/unittests/testcfg/rtems/cmake")
|
39
unittests/testcfg/rtems/include/cmath
Normal file
39
unittests/testcfg/rtems/include/cmath
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include_next <cmath>
|
||||
|
||||
extern "C++"
|
||||
{
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
|
||||
#undef lround
|
||||
#undef erfc
|
||||
#undef round
|
||||
|
||||
|
||||
using ::lround;
|
||||
|
||||
long
|
||||
lround(float __x);
|
||||
|
||||
constexpr long
|
||||
lround(long double __x);
|
||||
|
||||
using ::erfc;
|
||||
|
||||
constexpr float
|
||||
erfc(float __x);
|
||||
|
||||
constexpr long double
|
||||
erfc(long double __x);
|
||||
|
||||
constexpr float
|
||||
round(float __x);
|
||||
|
||||
using ::round;
|
||||
|
||||
constexpr long double
|
||||
round(long double __x);
|
||||
}
|
||||
}
|
32
unittests/testcfg/rtems/include/rtemsConfig.h
Normal file
32
unittests/testcfg/rtems/include/rtemsConfig.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <rtems/extension.h>
|
||||
#include <rtems/bspIo.h>
|
||||
void user_handle_fatal(Internal_errors_Source source, bool internal, Internal_errors_t error_code);
|
||||
|
||||
#define RTEMS_USE_UNLIMITED_OBJECTS_ALLOCATION 0
|
||||
|
||||
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 20
|
||||
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 30
|
||||
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
|
||||
#define CONFIGURE_MAXIMUM_TIMERS 10
|
||||
//! Required for Rate-Monotonic Scheduling (RMS)
|
||||
#define CONFIGURE_MAXIMUM_PERIODS 15
|
||||
#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 6)
|
||||
//! Around 41 kB extra task stack for now.
|
||||
#define CONFIGURE_EXTRA_TASK_STACKS (10 * RTEMS_MINIMUM_STACK_SIZE)
|
||||
|
||||
#define CONFIGURE_INITIAL_EXTENSIONS { NULL, NULL, NULL, NULL, NULL, NULL, NULL, user_handle_fatal, NULL }
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/confdefs.h>
|
Loading…
x
Reference in New Issue
Block a user