Merge branch 'mueller/reboot-file-handling' into mueller/master
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit

This commit is contained in:
Robin Müller 2022-03-01 15:19:00 +01:00
commit b98a24373e
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
83 changed files with 6517 additions and 1549 deletions

2
.gitignore vendored
View File

@ -9,7 +9,7 @@
!misc/eclipse/**/.project
#vscode
.vscode
/.vscode
# Python
__pycache__

View File

@ -99,7 +99,7 @@ pre_source_hw_os_config()
if(TGT_BSP)
if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/raspberrypi"
OR TGT_BSP MATCHES "arm/beagleboneblack"
OR TGT_BSP MATCHES "arm/beagleboneblack" OR TGT_BSP MATCHES "arm/egse"
)
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
if(NOT BUILD_Q7S_SIMPLE_MODE)
@ -109,12 +109,18 @@ if(TGT_BSP)
endif()
endif()
if(TGT_BSP MATCHES "arm/raspberrypi")
if(TGT_BSP MATCHES "arm/raspberrypi" )
# Used by configure file
set(RASPBERRY_PI ON)
set(FSFW_HAL_ADD_RASPBERRY_PI ON)
endif()
if(TGT_BSP MATCHES "arm/egse")
# Used by configure file
set(EGSE ON)
set(FSFW_HAL_LINUX_ADD_LIBGPIOD OFF)
endif()
if(TGT_BSP MATCHES "arm/beagleboneblack")
# Used by configure file
set(BEAGLEBONEBLACK ON)
@ -140,7 +146,7 @@ configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
if(TGT_BSP MATCHES "arm/q7s")
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
elseif(TGT_BSP MATCHES "arm/raspberrypi")
elseif(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/egse")
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
endif()
@ -266,7 +272,11 @@ if(TGT_BSP MATCHES "arm/q7s")
)
endif()
if(TGT_BSP MATCHES "arm/egse")
target_link_libraries(${OBSW_NAME} PRIVATE
${LIB_ARCSEC}
)
endif()
if(ADD_CSP_LIB)
target_link_libraries(${OBSW_NAME} PRIVATE
@ -305,7 +315,7 @@ target_include_directories(${LIB_EIVE_MISSION} PUBLIC
${LIB_ARCSEC_PATH}
)
if(TGT_BSP MATCHES "arm/q7s")
if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/egse")
target_include_directories(${LIB_EIVE_MISSION} PUBLIC
${ARCSEC_LIB_PATH}
)

View File

@ -19,9 +19,10 @@
12. [Static Code Analysis](#static-code-analysis)
13. [Eclipse](#eclipse)
14. [Running the OBSW on a Raspberry Pi](#rpi)
15. [Manually preparing sysroots to compile gpsd](#gpsd)
16. [FSFW](#fsfw)
17. [Coding Style](#coding-style)
15. [Running OBSW on EGSE](#egse)
16. [Manually preparing sysroots to compile gpsd](#gpsd)
17. [FSFW](#fsfw)
18. [Coding Style](#coding-style)
# <a id="general"></a> General information
@ -1152,6 +1153,35 @@ sudo apt-get install gpiod libgpiod-dev
to install the required GPIO libraries before cloning the system root folder.
# <a id="egse"></a> Running OBSW on EGSE
The EGSE is a test system from arcsec build arround a raspberry pi 4 to test the star tracker. The IP address of the EGSE (raspberry pi) is 192.168.18.31. An ssh session can be opened with
````
ssh pi@192.168.18.31
````
Password: raspberry
To run the obsw perform the following steps:
1. Build the cmake EGSE Configuration
* the sysroots for the EGSE can be found [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/egse&fileid=1190471)
* toolchain for linux host can be downloaded from [here](https://github.com/Pro/raspi-toolchain)
* toolchain for windows host from [here](https://gnutoolchains.com/raspberry/) (the raspios-buster-armhf toolchain is the right one for the EGSE)
2. Disable the ser2net systemd service on the EGSE
````sh
$ sudo systemctl stop ser2net.service
````
3. Power on the star tracker by running
````sh
$ ~/powerctrl/enable0.sh`
````
4. Run portforwarding script for tmtc tcp connection and tcf agent on host PC
````sh
$ ./scripts/egse-port.sh
````
5. The star tracker can be powered off by running
````sh
$ ~/powerctrl/disable0.sh
````
# <a id="gpsd"></a> Manually preparing sysroots to compile gpsd
Copy all header files from [here](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/gpsd&fileid=1189985) to the /usr/include directory and all static libraries to /usr/lib.

7
bsp_egse/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
target_sources(${OBSW_NAME} PUBLIC
InitMission.cpp
main.cpp
ObjectFactory.cpp
)
add_subdirectory(boardconfig)

192
bsp_egse/InitMission.cpp Normal file
View File

@ -0,0 +1,192 @@
#include "InitMission.h"
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/utility/InitMission.h>
#include <iostream>
#include "OBSWConfig.h"
#include "ObjectFactory.h"
#include "objects/systemObjectList.h"
#include "pollingsequence/pollingSequenceFactory.h"
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR");
ObjectManagerIF* objectManager = nullptr;
void initmission::initMission() {
sif::info << "Make sure the systemd service ser2net on the egse has been stopped "
<< "(alias stop-ser2net)" << std::endl;
sif::info << "Make sure the power lines of the star tracker have been enabled "
<< "(alias enable-startracker)" << std::endl;
sif::info << "Building global objects.." << std::endl;
/* Instantiate global object manager and also create all objects */
ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr);
sif::info << "Initializing all objects.." << std::endl;
ObjectManager::instance()->initialize();
/* This function creates and starts all tasks */
initTasks();
}
void initmission::initTasks() {
TaskFactory* factory = TaskFactory::instance();
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (factory == nullptr) {
/* Should never happen ! */
return;
}
#if OBSW_PRINT_MISSED_DEADLINES == 1
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
#else
void (*missedDeadlineFunc)(void) = nullptr;
#endif
/* TMTC Distribution */
PeriodicTaskIF* tmtcDistributor = factory->createPeriodicTask(
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcDistributor->addComponent(objects::CCSDS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
result = tmtcDistributor->addComponent(objects::TM_FUNNEL);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Bridge failed" << std::endl;
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component TMTC Polling failed" << std::endl;
}
/* PUS Services */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
std::vector<PeriodicTaskIF*> pstTasks;
FixedTimeslotTaskIF* pst = factory->createFixedTimeslotTask(
"STAR_TRACKER_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc);
result = pst::pstUart(pst);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
}
pstTasks.push_back(pst);
PeriodicTaskIF* strHelperTask = factory->createPeriodicTask(
"STR_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = strHelperTask->addComponent(objects::STR_HELPER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("STR_HELPER", objects::STR_HELPER);
}
pstTasks.push_back(strHelperTask);
auto taskStarter = [](std::vector<PeriodicTaskIF*>& taskVector, std::string name) {
for (const auto& task : taskVector) {
if (task != nullptr) {
task->startTask();
} else {
sif::error << "Task in vector " << name << " is invalid!" << std::endl;
}
}
};
sif::info << "Starting tasks.." << std::endl;
tmtcDistributor->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
taskStarter(pstTasks, "PST Tasks");
taskStarter(pusTasks, "PUS Tasks");
sif::info << "Tasks started.." << std::endl;
}
void initmission::createPusTasks(TaskFactory& factory,
TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
PeriodicTaskIF* pusVerification = factory.createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Object add component failed" << std::endl;
}
taskVec.push_back(pusVerification);
PeriodicTaskIF* pusEvents = factory.createPeriodicTask(
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusEvents->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_EVENTS", objects::PUS_SERVICE_5_EVENT_REPORTING);
}
result = pusEvents->addComponent(objects::EVENT_MANAGER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS_MGMT", objects::EVENT_MANAGER);
}
taskVec.push_back(pusEvents);
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
taskVec.push_back(pusMedPrio);
PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
result = pusLowPrio->addComponent(objects::INTERNAL_ERROR_REPORTER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("INT_ERR_RPRT", objects::INTERNAL_ERROR_REPORTER);
}
taskVec.push_back(pusLowPrio);
}

21
bsp_egse/InitMission.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef BSP_LINUX_INITMISSION_H_
#define BSP_LINUX_INITMISSION_H_
#include <vector>
#include "fsfw/tasks/Typedef.h"
class PeriodicTaskIF;
class TaskFactory;
namespace initmission {
void initMission();
void initTasks();
void createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
void createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc,
std::vector<PeriodicTaskIF*>& taskVec);
}; // namespace initmission
#endif /* BSP_LINUX_INITMISSION_H_ */

View File

@ -0,0 +1,49 @@
#include "ObjectFactory.h"
#include <devConf.h>
#include <fsfw_hal/linux/uart/UartComIF.h>
#include <fsfw_hal/linux/uart/UartCookie.h>
#include <mission/devices/GPSHyperionHandler.h>
#include "OBSWConfig.h"
#include "busConf.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
#include "fsfw/tmtcservices/PusServiceBase.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "linux/devices/startracker/StarTrackerHandler.h"
#include "mission/core/GenericFactory.h"
#include "mission/utility/TmFunnel.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
ObjectFactory::produceGenericObjects();
UartCookie* starTrackerCookie =
new UartCookie(objects::STAR_TRACKER, egse::STAR_TRACKER_UART, UartModes::NON_CANONICAL,
uart::STAR_TRACKER_BAUD, startracker::MAX_FRAME_SIZE * 2 + 2);
new UartComIF(objects::UART_COM_IF);
starTrackerCookie->setNoFixedSizeReply();
StrHelper* strHelper = new StrHelper(objects::STR_HELPER);
StarTrackerHandler* starTrackerHandler = new StarTrackerHandler(
objects::STAR_TRACKER, objects::UART_COM_IF, starTrackerCookie, strHelper);
starTrackerHandler->setStartUpImmediately();
}

8
bsp_egse/ObjectFactory.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef BSP_LINUX_OBJECTFACTORY_H_
#define BSP_LINUX_OBJECTFACTORY_H_
namespace ObjectFactory {
void produce(void* args);
}; // namespace ObjectFactory
#endif /* BSP_LINUX_OBJECTFACTORY_H_ */

View File

@ -0,0 +1,7 @@
target_sources(${OBSW_NAME} PRIVATE
print.c
)
target_include_directories(${OBSW_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -0,0 +1,8 @@
#ifndef BSP_EGSE_BOARDCONFIG_BUSCONF_H_
#define BSP_EGSE_BOARDCONFIG_BUSCONF_H_
namespace egse {
static constexpr char STAR_TRACKER_UART[] = "/dev/serial0";
}
#endif /* BSP_EGSE_BOARDCONFIG_BUSCONF_H_ */

View File

@ -0,0 +1,38 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2019 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_PROFILE_H__
#define __ETL_PROFILE_H__
#define ETL_CHECK_PUSH_POP
#define ETL_CPP11_SUPPORTED 1
#define ETL_NO_NULLPTR_SUPPORT 0
#endif

View File

@ -0,0 +1,15 @@
#ifndef LINUX_GCOV_H_
#define LINUX_GCOV_H_
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
#ifdef GCOV
extern "C" void __gcov_flush();
#else
void __gcov_flush() {
sif::info << "GCC GCOV: Please supply GCOV=1 in Makefile if "
"coverage information is desired.\n"
<< std::flush;
}
#endif
#endif /* LINUX_GCOV_H_ */

View File

@ -0,0 +1,10 @@
#include <bsp_egse/boardconfig/print.h>
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}

View File

@ -0,0 +1,8 @@
#ifndef HOSTED_BOARDCONFIG_PRINT_H_
#define HOSTED_BOARDCONFIG_PRINT_H_
#include <stdbool.h>
void printChar(const char* character, bool errStream);
#endif /* HOSTED_BOARDCONFIG_PRINT_H_ */

View File

@ -0,0 +1,6 @@
#ifndef BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
#define BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
#include <cstdint>
#endif /* BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_ */

28
bsp_egse/main.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <iostream>
#include "InitMission.h"
#include "OBSWConfig.h"
#include "OBSWVersion.h"
#include "fsfw/FSFWVersion.h"
#include "fsfw/tasks/TaskFactory.h"
/**
* @brief This is the main program entry point for the egse (raspberry pi 4)
* @return
*/
int main(void) {
std::cout << "-- EIVE OBSW --" << std::endl;
std::cout << "-- Compiled for EGSE from Arcsec"
<< " --" << std::endl;
std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION << "."
<< SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << FSFW_REVISION
<< "--" << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
initmission::initMission();
for (;;) {
/* Suspend main thread by sleeping it. */
TaskFactory::delayTask(5000);
}
}

View File

@ -64,17 +64,17 @@ void initmission::initTasks() {
}
/* UDP bridge */
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = udpBridgeTask->addComponent(objects::TMTC_BRIDGE);
PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask(
"TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
sif::error << "Add component TMTC Bridge failed" << std::endl;
}
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = udpPollingTask->addComponent(objects::TMTC_POLLING_TASK);
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Add component UDP Polling failed" << std::endl;
sif::error << "Add component TMTC Polling failed" << std::endl;
}
/* PUS Services */
@ -100,8 +100,8 @@ void initmission::initTasks() {
sif::info << "Starting tasks.." << std::endl;
tmTcDistributor->startTask();
udpBridgeTask->startTask();
udpPollingTask->startTask();
tmtcBridgeTask->startTask();
tmtcPollingTask->startTask();
taskStarter(pusTasks, "PUS Tasks");
#if OBSW_ADD_TEST_CODE == 1

View File

@ -1,4 +1,4 @@
#include <bsp_q7s/boardconfig/print.h>
#include <bsp_linux_board/boardconfig/print.h>
#include <stdio.h>
void printChar(const char* character, bool errStream) {

View File

@ -59,7 +59,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) {
void CoreController::performControlOperation() {
performWatchdogControlOperation();
sdStateMachine();
performRebootFileHandling(false);
performMountedSdCardOperations();
}
ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
@ -94,7 +94,7 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
}
}
sdStateMachine();
result = initVersionFile();
performMountedSdCardOperations();
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::initialize: Version initialization failed" << std::endl;
}
@ -131,24 +131,37 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
}
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_ALL_REBOOT_COUNTERS): {
resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
case (RESET_REBOOT_COUNTERS): {
if (size == 0) {
resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
} else if (size == 2) {
if (data[0] > 1 or data[1] > 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
resetRebootCount(static_cast<xsc::Chip>(data[0]), static_cast<xsc::Copy>(data[1]));
}
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_00): {
resetRebootCount(xsc::CHIP_0, xsc::COPY_0);
case (SWITCH_IMG_LOCK): {
if (size != 3) {
return HasActionsIF::INVALID_PARAMETERS;
}
if (data[1] > 1 or data[2] > 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
setRebootMechanismLock(data[0], static_cast<xsc::Chip>(data[1]),
static_cast<xsc::Copy>(data[2]));
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_01): {
resetRebootCount(xsc::CHIP_0, xsc::COPY_1);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_10): {
resetRebootCount(xsc::CHIP_1, xsc::COPY_0);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_11): {
resetRebootCount(xsc::CHIP_1, xsc::COPY_1);
case (SET_MAX_REBOOT_CNT): {
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
rebootFile.maxCount = data[0];
rewriteRebootFile(rebootFile);
return HasActionsIF::EXECUTION_FINISHED;
}
case (REBOOT_OBC): {
@ -1173,104 +1186,129 @@ void CoreController::performWatchdogControlOperation() {
}
}
void CoreController::performRebootFileHandling(bool recreateFile) {
bool sdCardMounted = false;
if (not recreateFile and doPerformRebootFileHandling) {
void CoreController::performMountedSdCardOperations() {
if (doPerformMountedSdCardOps) {
bool sdCardMounted = false;
sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref);
if (sdCardMounted) {
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER;
if (not std::filesystem::exists(path)) {
std::filesystem::create_directory(path);
}
initVersionFile();
performRebootFileHandling(false);
doPerformMountedSdCardOps = false;
}
}
if ((doPerformRebootFileHandling and sdCardMounted) or recreateFile) {
using namespace std;
if (recreateFile) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
#endif
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
if (not std::filesystem::exists(path) or recreateFile) {
rebootFile.enabled = true;
rebootFile.img00Cnt = 0;
rebootFile.img01Cnt = 0;
rebootFile.img10Cnt = 0;
rebootFile.img11Cnt = 0;
rebootFile.lastChip = xsc::Chip::CHIP_0;
rebootFile.lastCopy = xsc::Copy::COPY_0;
rebootFile.bootFlag = false;
rewriteRebootFile(rebootFile);
} else {
if (not parseRebootFile(path, rebootFile)) {
performRebootFileHandling(true);
}
}
}
if (rebootFile.bootFlag) {
// Trigger event to inform ground that a reboot was triggered
uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy;
uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 |
rebootFile.img10Cnt << 8 | rebootFile.img11Cnt;
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
// Clear the boot flag
rebootFile.bootFlag = false;
}
switch (CURRENT_CHIP) {
case (xsc::CHIP_0): {
switch (CURRENT_COPY) {
case (xsc::COPY_0): {
rebootFile.img00Cnt++;
break;
}
case (xsc::COPY_1): {
rebootFile.img01Cnt++;
break;
}
default: {
break;
}
}
break;
}
case (xsc::CHIP_1): {
switch (CURRENT_COPY) {
case (xsc::COPY_0): {
rebootFile.img10Cnt++;
break;
}
case (xsc::COPY_1): {
rebootFile.img11Cnt++;
break;
}
default: {
break;
}
}
break;
}
default: {
break;
}
}
if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) {
}
if (rebootFile.relevantBootCnt > rebootFile.maxCount) {
// Reboot to other image
bool doReboot = false;
determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy);
if (doReboot) {
rebootFile.bootFlag = true;
void CoreController::performRebootFileHandling(bool recreateFile) {
using namespace std;
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
if (not std::filesystem::exists(path) or recreateFile) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
<< "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy
<< std::endl;
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
#endif
rewriteRebootFile(rebootFile);
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(rebootFile.lastChip),
static_cast<xsc_libnor_copy_t>(rebootFile.lastCopy));
}
} else {
rewriteRebootFile(rebootFile);
rebootFile.enabled = true;
rebootFile.img00Cnt = 0;
rebootFile.img01Cnt = 0;
rebootFile.img10Cnt = 0;
rebootFile.img11Cnt = 0;
rebootFile.lastChip = xsc::Chip::CHIP_0;
rebootFile.lastCopy = xsc::Copy::COPY_0;
rebootFile.img00Lock = false;
rebootFile.img01Lock = false;
rebootFile.img10Lock = false;
rebootFile.img11Lock = false;
rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
rebootFile.bootFlag = false;
rewriteRebootFile(rebootFile);
} else {
if (not parseRebootFile(path, rebootFile)) {
performRebootFileHandling(true);
}
doPerformRebootFileHandling = false;
}
if (CURRENT_CHIP == xsc::CHIP_0) {
if (CURRENT_COPY == xsc::COPY_0) {
rebootFile.img00Cnt++;
} else {
rebootFile.img01Cnt++;
}
} else {
if (CURRENT_COPY == xsc::COPY_0) {
rebootFile.img10Cnt++;
} else {
rebootFile.img11Cnt++;
}
}
if (rebootFile.bootFlag) {
// Trigger event to inform ground that a reboot was triggered
uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy;
uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 | rebootFile.img10Cnt << 8 |
rebootFile.img11Cnt;
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
// Clear the boot flag
rebootFile.bootFlag = false;
}
if (rebootFile.mechanismNextChip != xsc::NO_CHIP and
rebootFile.mechanismNextCopy != xsc::NO_COPY) {
if (CURRENT_CHIP != rebootFile.mechanismNextChip or
CURRENT_COPY != rebootFile.mechanismNextCopy) {
std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " +
std::to_string(rebootFile.mechanismNextCopy);
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
<< infoString << " but currently on other image. Locking " << infoString
<< std::endl;
// Firmware or other component might be corrupt and we are on another image then the target
// image specified by the mechanism. We can't really trust the target image anymore.
// Lock it for now
if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
rebootFile.img00Lock = true;
} else {
rebootFile.img01Lock = true;
}
} else {
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
rebootFile.img10Lock = true;
} else {
rebootFile.img11Lock = true;
}
}
}
}
rebootFile.lastChip = CURRENT_CHIP;
rebootFile.lastCopy = CURRENT_COPY;
// Only reboot if the reboot functionality is enabled.
// The handler will still increment the boot counts
if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) {
// Reboot to other image
bool doReboot = false;
xsc::Chip tgtChip = xsc::NO_CHIP;
xsc::Copy tgtCopy = xsc::NO_COPY;
determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy);
if (doReboot) {
rebootFile.bootFlag = true;
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
#endif
rebootFile.mechanismNextChip = tgtChip;
rebootFile.mechanismNextCopy = tgtCopy;
rewriteRebootFile(rebootFile);
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
static_cast<xsc_libnor_copy_t>(tgtCopy));
}
} else {
rebootFile.mechanismNextChip = xsc::NO_CHIP;
rebootFile.mechanismNextCopy = xsc::NO_COPY;
}
rewriteRebootFile(rebootFile);
}
void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
@ -1278,85 +1316,87 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_0;
needsReboot = false;
if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_0) and
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_0) and
(rf.img00Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img01Cnt >= rf.maxCount) {
if (rf.img10Cnt >= rf.maxCount) {
if (rf.img11Cnt >= rf.maxCount) {
// Can't really do much here. Stay on image
sif::warning << "All reboot counts too high, but already on fallback image" << std::endl;
return;
} else {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
}
} else {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_1;
}
} else {
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
return;
}
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
return;
}
// Can't really do much here. Stay on image
sif::warning
<< "All reboot counts too high or all fallback images locked, already on fallback image"
<< std::endl;
needsReboot = false;
return;
}
if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_1) and
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and
(rf.img01Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img00Cnt >= rf.maxCount) {
if (rf.img10Cnt >= rf.maxCount) {
if (rf.img11Cnt >= rf.maxCount) {
// Reboot to fallback image
} else {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
}
} else {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_0;
}
} else {
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
// Reboot on fallback image
return;
}
}
if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) and
(rf.img10Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img11Cnt >= rf.maxCount) {
if (rf.img00Cnt >= rf.maxCount) {
if (rf.img01Cnt >= rf.maxCount) {
// Reboot to fallback image
} else {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_1;
}
} else {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_0;
}
} else {
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
return;
}
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and
(rf.img10Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
return;
}
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and
(rf.img11Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img10Cnt >= rf.maxCount) {
if (rf.img00Cnt >= rf.maxCount) {
if (rf.img01Cnt >= rf.maxCount) {
// Reboot to fallback image
} else {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_1;
}
} else {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_0;
}
} else {
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_0;
return;
}
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
return;
}
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
}
@ -1407,7 +1447,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
iss >> rf.img00Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = rf.img00Cnt;
rf.relevantBootCnt = &rf.img00Cnt;
}
break;
}
@ -1418,7 +1458,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
iss >> rf.img01Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = rf.img01Cnt;
rf.relevantBootCnt = &rf.img01Cnt;
}
break;
}
@ -1429,7 +1469,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
iss >> rf.img10Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = rf.img10Cnt;
rf.relevantBootCnt = &rf.img10Cnt;
}
break;
}
@ -1440,11 +1480,43 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
iss >> rf.img11Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = rf.img11Cnt;
rf.relevantBootCnt = &rf.img11Cnt;
}
break;
}
case 6: {
iss >> word;
if (word.find("img00lock:") == string::npos) {
return false;
}
iss >> rf.img00Lock;
break;
}
case 7: {
iss >> word;
if (word.find("img01lock:") == string::npos) {
return false;
}
iss >> rf.img01Lock;
break;
}
case 8: {
iss >> word;
if (word.find("img10lock:") == string::npos) {
return false;
}
iss >> rf.img10Lock;
break;
}
case 9: {
iss >> word;
if (word.find("img11lock:") == string::npos) {
return false;
}
iss >> rf.img11Lock;
break;
}
case 10: {
iss >> word;
if (word.find("bootflag:") == string::npos) {
return false;
@ -1452,17 +1524,10 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
iss >> rf.bootFlag;
break;
}
case 7: {
case 11: {
iss >> word;
if (word.find("bootflag:") == string::npos) {
return false;
}
break;
}
case 8: {
iss >> word;
uint8_t copyRaw = 0;
uint8_t chipRaw = 0;
int copyRaw = 0;
int chipRaw = 0;
if (word.find("last:") == string::npos) {
return false;
}
@ -1480,6 +1545,30 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
rf.lastChip = static_cast<xsc::Chip>(chipRaw);
rf.lastCopy = static_cast<xsc::Copy>(copyRaw);
break;
}
case 12: {
iss >> word;
int copyRaw = 0;
int chipRaw = 0;
if (word.find("next:") == string::npos) {
return false;
}
iss >> chipRaw;
if (iss.fail()) {
return false;
}
iss >> copyRaw;
if (iss.fail()) {
return false;
}
if (chipRaw > 2 or copyRaw > 2) {
return false;
}
rf.mechanismNextChip = static_cast<xsc::Chip>(chipRaw);
rf.mechanismNextCopy = static_cast<xsc::Copy>(copyRaw);
break;
}
}
if (iss.fail()) {
@ -1487,7 +1576,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
}
lineIdx++;
}
if (lineIdx < 8) {
if (lineIdx < 12) {
return false;
}
return true;
@ -1528,7 +1617,31 @@ void CoreController::rewriteRebootFile(RebootFile file) {
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
<< "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
<< "\nbootflag: " << file.bootFlag << "\nlast: " << file.lastChip << " "
<< file.lastCopy << "\n";
<< "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock
<< "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock
<< "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast<int>(file.lastChip)
<< " " << static_cast<int>(file.lastCopy)
<< "\nnext: " << static_cast<int>(file.mechanismNextChip) << " "
<< static_cast<int>(file.mechanismNextCopy) << "\n";
}
}
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
if (tgtChip == xsc::CHIP_0) {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img00Lock = lock;
} else {
rebootFile.img01Lock = lock;
}
} else {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img10Lock = lock;
} else {
rebootFile.img11Lock = lock;
}
}
rewriteRebootFile(rebootFile);
}

View File

@ -15,24 +15,30 @@ class SdCardManager;
namespace xsc {
enum Chip : uint8_t { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : uint8_t { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
} // namespace xsc
struct RebootFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
bool enabled = false;
bool enabled = true;
size_t maxCount = DEFAULT_MAX_BOOT_CNT;
uint8_t img00Cnt = 0;
uint8_t img01Cnt = 0;
uint8_t img10Cnt = 0;
uint8_t img11Cnt = 0;
uint8_t relevantBootCnt = 0;
uint32_t img00Cnt = 0;
uint32_t img01Cnt = 0;
uint32_t img10Cnt = 0;
uint32_t img11Cnt = 0;
bool img00Lock = false;
bool img01Lock = false;
bool img10Lock = false;
bool img11Lock = false;
uint32_t* relevantBootCnt = &img00Cnt;
bool bootFlag = false;
xsc::Chip lastChip = xsc::Chip::CHIP_0;
xsc::Copy lastCopy = xsc::Copy::COPY_0;
xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP;
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};
class CoreController : public ExtendedControllerBase {
@ -43,17 +49,19 @@ class CoreController : public ExtendedControllerBase {
static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh";
static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt";
static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
static constexpr char VERSION_FILE[] = "/conf/version.txt";
static constexpr char REBOOT_FILE[] = "/conf/reboot.txt";
static constexpr char CONF_FOLDER[] = "conf";
static constexpr char VERSION_FILE_NAME[] = "version.txt";
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
const std::string VERSION_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
const std::string REBOOT_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_ALL_REBOOT_COUNTERS = 6;
static constexpr ActionId_t RESET_REBOOT_COUNTER_00 = 7;
static constexpr ActionId_t RESET_REBOOT_COUNTER_01 = 8;
static constexpr ActionId_t RESET_REBOOT_COUNTER_10 = 9;
static constexpr ActionId_t RESET_REBOOT_COUNTER_11 = 10;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 11;
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
static constexpr ActionId_t REBOOT_OBC = 32;
static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
@ -160,10 +168,9 @@ class CoreController : public ExtendedControllerBase {
sd::SdState currentlyCommandedState = sd::SdState::OFF;
sd::SdCard commandedCard = sd::SdCard::NONE;
sd::SdState commandedState = sd::SdState::OFF;
};
SdInfo sdInfo;
} sdInfo;
RebootFile rebootFile = {};
bool doPerformRebootFileHandling = true;
bool doPerformMountedSdCardOps = true;
/**
* Index 0: Chip 0 Copy 0
@ -178,7 +185,7 @@ class CoreController : public ExtendedControllerBase {
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t* msToReachTheMode);
void performMountedSdCardOperations();
ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
@ -190,6 +197,7 @@ class CoreController : public ExtendedControllerBase {
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true);
ReturnValue_t sdColdRedundantBlockingInit();
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
void determinePreferredSdCard();
void executeNextExternalSdCommand();
@ -209,6 +217,7 @@ class CoreController : public ExtendedControllerBase {
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
bool parseRebootFile(std::string path, RebootFile& file);
void rewriteRebootFile(RebootFile file);
};

View File

@ -86,7 +86,7 @@ void initmission::initTasks() {
"TCPIP_TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("UDP_BRIDGE", objects::TMTC_BRIDGE);
initmission::printAddObjectError("TMTC_BRIDGE", objects::TMTC_BRIDGE);
}
PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask(
"TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
@ -135,9 +135,9 @@ void initmission::initTasks() {
}
#if OBSW_ADD_STAR_TRACKER == 1
PeriodicTaskIF* strImgLoaderTask = factory->createPeriodicTask(
PeriodicTaskIF* strHelperTask = factory->createPeriodicTask(
"STR_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
result = strImgLoaderTask->addComponent(objects::STR_HELPER);
result = strHelperTask->addComponent(objects::STR_HELPER);
if (result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("STR_HELPER", objects::STR_HELPER);
}
@ -204,7 +204,7 @@ void initmission::initTasks() {
#if BOARD_TE0720 == 0
fsTask->startTask();
#if OBSW_ADD_STAR_TRACKER == 1
strImgLoaderTask->startTask();
strHelperTask > startTask();
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
#endif

View File

@ -16,9 +16,6 @@
#include "bsp_q7s/devices/PlocMemoryDumper.h"
#include "bsp_q7s/devices/PlocSupervisorHandler.h"
#include "bsp_q7s/devices/PlocUpdater.h"
#include "bsp_q7s/devices/startracker/StarTrackerDefinitions.h"
#include "bsp_q7s/devices/startracker/StarTrackerHandler.h"
#include "bsp_q7s/devices/startracker/StrHelper.h"
#include "bsp_q7s/memory/FileSystemHandler.h"
#include "busConf.h"
#include "ccsdsConfig.h"
@ -58,6 +55,13 @@
#include "linux/boardtest/SpiTestClass.h"
#include "linux/csp/CspComIF.h"
#include "linux/csp/CspCookie.h"
<<<<<<< HEAD
=======
#include "linux/devices/GPSHyperionLinuxController.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "linux/devices/startracker/StarTrackerHandler.h"
#include "linux/devices/startracker/StrHelper.h"
>>>>>>> mueller/reboot-file-handling
#include "mission/core/GenericFactory.h"
#include "mission/devices/ACUHandler.h"
#include "mission/devices/BpxBatteryHandler.h"

View File

@ -3,5 +3,3 @@ target_sources(${OBSW_NAME} PRIVATE
PlocUpdater.cpp
PlocMemoryDumper.cpp
)
add_subdirectory(startracker)

View File

@ -47,7 +47,7 @@ if(CMAKE_CROSSCOMPILING)
set_property(CACHE TGT_BSP
PROPERTY STRINGS
"arm/q7s" "arm/raspberrypi"
"arm/q7s" "arm/raspberrypi" "arm/egse"
)
endif()
@ -57,6 +57,8 @@ if(TGT_BSP)
set(BSP_PATH "bsp_linux_board")
elseif(TGT_BSP MATCHES "arm/q7s")
set(BSP_PATH "bsp_q7s")
elseif(TGT_BSP MATCHES "arm/egse")
set(BSP_PATH "bsp_egse")
else()
message(WARNING "CMake not configured for this target!")
message(FATAL_ERROR "Target: ${TGT_BSP}!")

View File

@ -17,8 +17,7 @@ if(FSFW_OSAL MATCHES linux AND TGT_BSP)
"${CMAKE_SCRIPT_PATH}/Q7SCrossCompileConfig.cmake"
PARENT_SCOPE
)
elseif(TGT_BSP MATCHES "arm/raspberrypi")
elseif(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/egse")
if(NOT DEFINED ENV{LINUX_ROOTFS})
if(NOT DEFINED LINUX_ROOTFS)
message(WARNING "No LINUX_ROOTFS environmental or CMake variable set!")

View File

@ -1,5 +1,49 @@
#!/bin/sh
export PATH=$PATH:"/c/Xilinx/SDK/2018.2/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin"
export CROSS_COMPILE="arm-linux-gnueabihf"
# Run with: source q7s-env-win-sh [OPTIONS]
function help () {
echo "source q7s-env-win-sh [options] -t|--toolchain=<toolchain path> -s|--sysroot=<sysroot path>"
}
export Q7S_SYSROOT="/c/Users/${USER}/Documents/EIVE/cortexa9hf-neon-xiphos-linux-gnueabi"
TOOLCHAIN_PATH="/c/Xilinx/Vitis/2019.2/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin"
SYSROOT="/c/Users/${USER}/eive-software/cortexa9hf-neon-xiphos-linux-gnueabi"
for i in "$@"; do
case $i in
-t=*|--toolchain=*)
TOOLCHAIN_PATH="${i#*=}"
shift
;;
-s=*|--sysroot=*)
SYSROOT="${i#*=}"
shift
;;
-h|--help)
help
shift
;;
-*|--*)
echo "Unknown option $i"
help
return
;;
*)
;;
esac
done
if [ -d "$TOOLCHAIN_PATH" ]; then
export PATH=$PATH:"/c/Xilinx/Vitis/2019.2/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin"
export CROSS_COMPILE="arm-linux-gnueabihf"
echo "Set toolchain path to /c/Xilinx/Vitis/2019.2/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin"
else
echo "Toolchain path $TOOLCHAIN_PATH does not exist"
return
fi
if [ -d "$SYSROOT" ]; then
export Q7S_SYSROOT=$SYSROOT
echo "Set sysroot path to $SYSROOT"
else
echo "Sysroot path $SYSROOT does not exist"
return
fi

View File

@ -0,0 +1,13 @@
#!/bin/sh
# Script to set path to raspberry pi toolchain
# Run script with: source egse_path_helper_win.sh
TOOLCHAIN_PATH="/c/SysGCC/raspberry/bin"
if [ $# -eq 1 ];then
export PATH=$PATH:"$1"
else
export PATH=$PATH:$TOOLCHAIN_PATH
fi
echo "Path of toolchain set to $TOOLCHAIN_PATH"
export CROSS_COMPILE="arm-linux-gnueabihf"
export RASPBERRY_VERSION="4"

View File

@ -0,0 +1,34 @@
#!/bin/sh
counter=0
cfg_script_name="cmake-build-cfg.py"
while [ ${counter} -lt 5 ]
do
cd ..
if [ -f ${cfg_script_name} ];then
break
fi
counter=$((counter=counter + 1))
done
if [ "${counter}" -ge 5 ];then
echo "${cfg_script_name} not found in upper directories!"
exit 1
fi
os_fsfw="linux"
tgt_bsp="arm/egse"
build_generator="make"
build_dir="build-Debug-egse"
if [ "${OS}" = "Windows_NT" ]; then
python="py"
# Could be other OS but this works for now.
else
python="python3"
fi
echo "Running command (without the leading +):"
set -x # Print command
${python} ${cfg_script_name} -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \
-l"${build_dir}"
# set +x

View File

@ -48,9 +48,9 @@ namespace uart {
static constexpr size_t HYPERION_GPS_REPLY_MAX_BUFFER = 1024;
static constexpr uint32_t SYRLINKS_BAUD = 38400;
static constexpr uint32_t GNSS_BAUD = 9600;
static constexpr uint32_t PLOC_MPSOC_BAUD = 115200;
static constexpr uint32_t PLOC_MPSOC_BAUD = 921600;
static constexpr uint32_t PLOC_SUPERVISOR_BAUD = 115200;
static constexpr uint32_t STAR_TRACKER_BAUD = 115200;
static constexpr uint32_t STAR_TRACKER_BAUD = 921600;
}

View File

@ -6,9 +6,9 @@
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_HOME" value="C:\Users\jakob\AppData\Local\Programs\Python\Python39\python.exe" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />

View File

@ -100,12 +100,14 @@
11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW;Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;./mission/devices/IMTQHandler.h
11208;INVALID_ERROR_BYTE;LOW;Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC.;./mission/devices/IMTQHandler.h
11301;ERROR_STATE;HIGH;Reaction wheel signals an error state;./mission/devices/RwHandler.h
11401;BOOTING_FIRMWARE_FAILED;LOW;Failed to boot firmware;./linux/devices/startracker/StarTrackerHandler.h
11402;BOOTING_BOOTLOADER_FAILED;LOW;Failed to boot star tracker into bootloader mode;./linux/devices/startracker/StarTrackerHandler.h
11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;./bsp_q7s/devices/PlocSupervisorHandler.h
11502;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;./bsp_q7s/devices/PlocSupervisorHandler.h
11503;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;./bsp_q7s/devices/PlocSupervisorHandler.h
11504;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;./bsp_q7s/devices/PlocSupervisorHandler.h
11600;SANITIZATION_FAILED;LOW;;./bsp_q7s/memory/SdCardManager.h
11601;MOUNTED_SD_CARD;INFO;;./bsp_q7s/memory/SdCardManager.h
11600;ALLOC_FAILURE;MEDIUM;;./bsp_q7s/core/CoreController.h
11601;REBOOT_SW;MEDIUM; Software reboot occured. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;./bsp_q7s/core/CoreController.h
11603;REBOOT_HW;MEDIUM;;./bsp_q7s/core/CoreController.h
11700;UPDATE_FILE_NOT_EXISTS;LOW;;./bsp_q7s/devices/PlocUpdater.h
11701;ACTION_COMMANDING_FAILED;LOW;Failed to send command to supervisor handler P1: Return value of CommandActionHelper::commandAction P2: Action ID of command to send;./bsp_q7s/devices/PlocUpdater.h
@ -120,26 +122,23 @@
11902;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;./linux/obc/PdecHandler.h
11903;CARRIER_LOCK;INFO;Carrier lock detected;./linux/obc/PdecHandler.h
11904;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);./linux/obc/PdecHandler.h
12000;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;./bsp_q7s/devices/startracker/StrHelper.h
12001;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;./bsp_q7s/devices/startracker/StrHelper.h
12002;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;./bsp_q7s/devices/startracker/StrHelper.h
12003;IMAGE_DOWNLOAD_SUCCESSFUL;LOW;Image download was successful;./bsp_q7s/devices/startracker/StrHelper.h
12004;FLASH_WRITE_SUCCESSFUL;LOW;Finished flash write procedure successfully;./bsp_q7s/devices/startracker/StrHelper.h
12005;FLASH_READ_SUCCESSFUL;LOW;Finished flash read procedure successfully;./bsp_q7s/devices/startracker/StrHelper.h
12006;FLASH_WRITE_FAILED;LOW;Flash write procedure failed;./bsp_q7s/devices/startracker/StrHelper.h
12007;FLASH_READ_FAILED;LOW;Flash read procedure failed;./bsp_q7s/devices/startracker/StrHelper.h
12008;FPGA_DOWNLOAD_SUCCESSFUL;LOW;Download of FPGA image successful;./bsp_q7s/devices/startracker/StrHelper.h
12009;FPGA_DOWNLOAD_FAILED;LOW;Download of FPGA image failed;./bsp_q7s/devices/startracker/StrHelper.h
12010;FPGA_UPLOAD_SUCCESSFUL;LOW;Upload of FPGA image successful;./bsp_q7s/devices/startracker/StrHelper.h
12011;FPGA_UPLOAD_FAILED;LOW;Upload of FPGA image failed;./bsp_q7s/devices/startracker/StrHelper.h
12012;STR_HELPER_READING_REPLY_FAILED;LOW;Failed to read communication interface reply data P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed;./bsp_q7s/devices/startracker/StrHelper.h
12013;STR_HELPER_COM_ERROR;LOW;Unexpected stop of decoding sequence P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed;./bsp_q7s/devices/startracker/StrHelper.h
12014;STR_HELPER_NO_REPLY;LOW;Star tracker did not send replies (maybe device is powered off) P1: Position of upload or download packet for which no reply was sent;./bsp_q7s/devices/startracker/StrHelper.h
12015;STR_HELPER_DEC_ERROR;LOW;Error during decoding of received reply occurred P1: Return value of decoding function P2: Position of upload/download packet, or address of flash write/read request;./bsp_q7s/devices/startracker/StrHelper.h
12016;POSITION_MISMATCH;LOW;Position mismatch P1: The expected position and thus the position for which the image upload/download failed;./bsp_q7s/devices/startracker/StrHelper.h
12017;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not exist P1: Internal state of str helper;./bsp_q7s/devices/startracker/StrHelper.h
12018;STR_HELPER_SENDING_PACKET_FAILED;LOW;;./bsp_q7s/devices/startracker/StrHelper.h
12019;STR_HELPER_REQUESTING_MSG_FAILED;LOW;;./bsp_q7s/devices/startracker/StrHelper.h
12000;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;./linux/devices/startracker/StrHelper.h
12001;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;./linux/devices/startracker/StrHelper.h
12002;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;./linux/devices/startracker/StrHelper.h
12003;IMAGE_DOWNLOAD_SUCCESSFUL;LOW;Image download was successful;./linux/devices/startracker/StrHelper.h
12004;FLASH_WRITE_SUCCESSFUL;LOW;Finished flash write procedure successfully;./linux/devices/startracker/StrHelper.h
12005;FLASH_READ_SUCCESSFUL;LOW;Finished flash read procedure successfully;./linux/devices/startracker/StrHelper.h
12006;FLASH_READ_FAILED;LOW;Flash read procedure failed;./linux/devices/startracker/StrHelper.h
12007;FIRMWARE_UPDATE_SUCCESSFUL;LOW;Firmware update was successful;./linux/devices/startracker/StrHelper.h
12008;FIRMWARE_UPDATE_FAILED;LOW;Firmware update failed;./linux/devices/startracker/StrHelper.h
12009;STR_HELPER_READING_REPLY_FAILED;LOW;Failed to read communication interface reply data P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed;./linux/devices/startracker/StrHelper.h
12010;STR_HELPER_COM_ERROR;LOW;Unexpected stop of decoding sequence P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed;./linux/devices/startracker/StrHelper.h
12011;STR_HELPER_NO_REPLY;LOW;Star tracker did not send replies (maybe device is powered off) P1: Position of upload or download packet for which no reply was sent;./linux/devices/startracker/StrHelper.h
12012;STR_HELPER_DEC_ERROR;LOW;Error during decoding of received reply occurred P1: Return value of decoding function P2: Position of upload/download packet, or address of flash write/read request;./linux/devices/startracker/StrHelper.h
12013;POSITION_MISMATCH;LOW;Position mismatch P1: The expected position and thus the position for which the image upload/download failed;./linux/devices/startracker/StrHelper.h
12014;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not exist P1: Internal state of str helper;./linux/devices/startracker/StrHelper.h
12015;STR_HELPER_SENDING_PACKET_FAILED;LOW;;./linux/devices/startracker/StrHelper.h
12016;STR_HELPER_REQUESTING_MSG_FAILED;LOW;;./linux/devices/startracker/StrHelper.h
12101;NEG_V_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;./mission/devices/PayloadPcduHandler.h
12102;U_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;./mission/devices/PayloadPcduHandler.h
12103;I_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;./mission/devices/PayloadPcduHandler.h

1 2200 STORE_SEND_WRITE_FAILED LOW ./fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h
100 11207 SELF_TEST_COIL_CURRENT_FAILURE LOW Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA ./mission/devices/IMTQHandler.h
101 11208 INVALID_ERROR_BYTE LOW Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC. ./mission/devices/IMTQHandler.h
102 11301 ERROR_STATE HIGH Reaction wheel signals an error state ./mission/devices/RwHandler.h
103 11401 BOOTING_FIRMWARE_FAILED LOW Failed to boot firmware ./linux/devices/startracker/StarTrackerHandler.h
104 11402 BOOTING_BOOTLOADER_FAILED LOW Failed to boot star tracker into bootloader mode ./linux/devices/startracker/StarTrackerHandler.h
105 11501 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet ./bsp_q7s/devices/PlocSupervisorHandler.h
106 11502 SUPV_ACK_FAILURE LOW PLOC supervisor received acknowledgment failure report ./bsp_q7s/devices/PlocSupervisorHandler.h
107 11503 SUPV_EXE_FAILURE LOW PLOC received execution failure report ./bsp_q7s/devices/PlocSupervisorHandler.h
108 11504 SUPV_CRC_FAILURE_EVENT LOW PLOC supervisor reply has invalid crc ./bsp_q7s/devices/PlocSupervisorHandler.h
109 11600 SANITIZATION_FAILED ALLOC_FAILURE LOW MEDIUM ./bsp_q7s/memory/SdCardManager.h ./bsp_q7s/core/CoreController.h
110 11601 MOUNTED_SD_CARD REBOOT_SW INFO MEDIUM Software reboot occured. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy ./bsp_q7s/memory/SdCardManager.h ./bsp_q7s/core/CoreController.h
111 11603 REBOOT_HW MEDIUM ./bsp_q7s/core/CoreController.h
112 11700 UPDATE_FILE_NOT_EXISTS LOW ./bsp_q7s/devices/PlocUpdater.h
113 11701 ACTION_COMMANDING_FAILED LOW Failed to send command to supervisor handler P1: Return value of CommandActionHelper::commandAction P2: Action ID of command to send ./bsp_q7s/devices/PlocUpdater.h
122 11902 INVALID_FAR HIGH Read invalid FAR from PDEC after startup ./linux/obc/PdecHandler.h
123 11903 CARRIER_LOCK INFO Carrier lock detected ./linux/obc/PdecHandler.h
124 11904 BIT_LOCK_PDEC INFO Bit lock detected (data valid) ./linux/obc/PdecHandler.h
125 12000 IMAGE_UPLOAD_FAILED LOW Image upload failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
126 12001 IMAGE_DOWNLOAD_FAILED LOW Image download failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
127 12002 IMAGE_UPLOAD_SUCCESSFUL LOW Uploading image to star tracker was successfulop ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
128 12003 IMAGE_DOWNLOAD_SUCCESSFUL LOW Image download was successful ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
129 12004 FLASH_WRITE_SUCCESSFUL LOW Finished flash write procedure successfully ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
130 12005 FLASH_READ_SUCCESSFUL LOW Finished flash read procedure successfully ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
131 12006 FLASH_WRITE_FAILED FLASH_READ_FAILED LOW Flash write procedure failed Flash read procedure failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
132 12007 FLASH_READ_FAILED FIRMWARE_UPDATE_SUCCESSFUL LOW Flash read procedure failed Firmware update was successful ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
133 12008 FPGA_DOWNLOAD_SUCCESSFUL FIRMWARE_UPDATE_FAILED LOW Download of FPGA image successful Firmware update failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
134 12009 FPGA_DOWNLOAD_FAILED STR_HELPER_READING_REPLY_FAILED LOW Download of FPGA image failed Failed to read communication interface reply data P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
135 12010 FPGA_UPLOAD_SUCCESSFUL STR_HELPER_COM_ERROR LOW Upload of FPGA image successful Unexpected stop of decoding sequence P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
136 12011 FPGA_UPLOAD_FAILED STR_HELPER_NO_REPLY LOW Upload of FPGA image failed Star tracker did not send replies (maybe device is powered off) P1: Position of upload or download packet for which no reply was sent ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
137 12012 STR_HELPER_READING_REPLY_FAILED STR_HELPER_DEC_ERROR LOW Failed to read communication interface reply data P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed Error during decoding of received reply occurred P1: Return value of decoding function P2: Position of upload/download packet, or address of flash write/read request ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
138 12013 STR_HELPER_COM_ERROR POSITION_MISMATCH LOW Unexpected stop of decoding sequence P1: Return code of failed communication interface read call P1: Upload/download position for which the read call failed Position mismatch P1: The expected position and thus the position for which the image upload/download failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
139 12014 STR_HELPER_NO_REPLY STR_HELPER_FILE_NOT_EXISTS LOW Star tracker did not send replies (maybe device is powered off) P1: Position of upload or download packet for which no reply was sent Specified file does not exist P1: Internal state of str helper ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
140 12015 STR_HELPER_DEC_ERROR STR_HELPER_SENDING_PACKET_FAILED LOW Error during decoding of received reply occurred P1: Return value of decoding function P2: Position of upload/download packet, or address of flash write/read request ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
141 12016 POSITION_MISMATCH STR_HELPER_REQUESTING_MSG_FAILED LOW Position mismatch P1: The expected position and thus the position for which the image upload/download failed ./bsp_q7s/devices/startracker/StrHelper.h ./linux/devices/startracker/StrHelper.h
12017 STR_HELPER_FILE_NOT_EXISTS LOW Specified file does not exist P1: Internal state of str helper ./bsp_q7s/devices/startracker/StrHelper.h
12018 STR_HELPER_SENDING_PACKET_FAILED LOW ./bsp_q7s/devices/startracker/StrHelper.h
12019 STR_HELPER_REQUESTING_MSG_FAILED LOW ./bsp_q7s/devices/startracker/StrHelper.h
142 12101 NEG_V_OUT_OF_BOUNDS MEDIUM P1: 0 -> too low, 1 -> too high P2: Float value ./mission/devices/PayloadPcduHandler.h
143 12102 U_DRO_OUT_OF_BOUNDS MEDIUM P1: 0 -> too low, 1 -> too high P2: Float value ./mission/devices/PayloadPcduHandler.h
144 12103 I_DRO_OUT_OF_BOUNDS MEDIUM P1: 0 -> too low, 1 -> too high P2: Float value ./mission/devices/PayloadPcduHandler.h

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 153 translations.
* @brief Auto-generated event translation file. Contains 152 translations.
* @details
* Generated on: 2022-02-26 13:53:13
* Generated on: 2022-03-01 15:17:49
*/
#include "translateEvents.h"
@ -107,12 +107,14 @@ const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE";
const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE";
const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE";
const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *BOOTING_FIRMWARE_FAILED_STRING = "BOOTING_FIRMWARE_FAILED";
const char *BOOTING_BOOTLOADER_FAILED_STRING = "BOOTING_BOOTLOADER_FAILED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE";
const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE";
const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT";
const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED";
const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD";
const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS";
const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED";
@ -133,12 +135,9 @@ const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
const char *IMAGE_DOWNLOAD_SUCCESSFUL_STRING = "IMAGE_DOWNLOAD_SUCCESSFUL";
const char *FLASH_WRITE_SUCCESSFUL_STRING = "FLASH_WRITE_SUCCESSFUL";
const char *FLASH_READ_SUCCESSFUL_STRING = "FLASH_READ_SUCCESSFUL";
const char *FLASH_WRITE_FAILED_STRING = "FLASH_WRITE_FAILED";
const char *FLASH_READ_FAILED_STRING = "FLASH_READ_FAILED";
const char *FPGA_DOWNLOAD_SUCCESSFUL_STRING = "FPGA_DOWNLOAD_SUCCESSFUL";
const char *FPGA_DOWNLOAD_FAILED_STRING = "FPGA_DOWNLOAD_FAILED";
const char *FPGA_UPLOAD_SUCCESSFUL_STRING = "FPGA_UPLOAD_SUCCESSFUL";
const char *FPGA_UPLOAD_FAILED_STRING = "FPGA_UPLOAD_FAILED";
const char *FIRMWARE_UPDATE_SUCCESSFUL_STRING = "FIRMWARE_UPDATE_SUCCESSFUL";
const char *FIRMWARE_UPDATE_FAILED_STRING = "FIRMWARE_UPDATE_FAILED";
const char *STR_HELPER_READING_REPLY_FAILED_STRING = "STR_HELPER_READING_REPLY_FAILED";
const char *STR_HELPER_COM_ERROR_STRING = "STR_HELPER_COM_ERROR";
const char *STR_HELPER_NO_REPLY_STRING = "STR_HELPER_NO_REPLY";
@ -365,6 +364,10 @@ const char *translateEvents(Event event) {
return INVALID_ERROR_BYTE_STRING;
case (11301):
return ERROR_STATE_STRING;
case (11401):
return BOOTING_FIRMWARE_FAILED_STRING;
case (11402):
return BOOTING_BOOTLOADER_FAILED_STRING;
case (11501):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (11502):
@ -374,9 +377,9 @@ const char *translateEvents(Event event) {
case (11504):
return SUPV_CRC_FAILURE_EVENT_STRING;
case (11600):
return SANITIZATION_FAILED_STRING;
return ALLOC_FAILURE_STRING;
case (11601):
return MOUNTED_SD_CARD_STRING;
return REBOOT_SW_STRING;
case (11603):
return REBOOT_HW_STRING;
case (11700):
@ -418,32 +421,26 @@ const char *translateEvents(Event event) {
case (12005):
return FLASH_READ_SUCCESSFUL_STRING;
case (12006):
return FLASH_WRITE_FAILED_STRING;
case (12007):
return FLASH_READ_FAILED_STRING;
case (12007):
return FIRMWARE_UPDATE_SUCCESSFUL_STRING;
case (12008):
return FPGA_DOWNLOAD_SUCCESSFUL_STRING;
return FIRMWARE_UPDATE_FAILED_STRING;
case (12009):
return FPGA_DOWNLOAD_FAILED_STRING;
case (12010):
return FPGA_UPLOAD_SUCCESSFUL_STRING;
case (12011):
return FPGA_UPLOAD_FAILED_STRING;
case (12012):
return STR_HELPER_READING_REPLY_FAILED_STRING;
case (12013):
case (12010):
return STR_HELPER_COM_ERROR_STRING;
case (12014):
case (12011):
return STR_HELPER_NO_REPLY_STRING;
case (12015):
case (12012):
return STR_HELPER_DEC_ERROR_STRING;
case (12016):
case (12013):
return POSITION_MISMATCH_STRING;
case (12017):
case (12014):
return STR_HELPER_FILE_NOT_EXISTS_STRING;
case (12018):
case (12015):
return STR_HELPER_SENDING_PACKET_FAILED_STRING;
case (12019):
case (12016):
return STR_HELPER_REQUESTING_MSG_FAILED_STRING;
case (12101):
return NEG_V_OUT_OF_BOUNDS_STRING;

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 112 translations.
* Generated on: 2022-02-26 14:03:55
* Generated on: 2022-03-01 15:17:56
*/
#include "translateObjects.h"

View File

@ -337,6 +337,8 @@ void SpiTestClass::performMax1227Test() {
std::string deviceName = q7s::SPI_DEFAULT_DEV;
#elif defined(RASPBERRY_PI)
std::string deviceName = "";
#elif defined(EGSE)
std::string deviceName = "";
#endif
int fd = 0;
UnixFileGuard fileHelper(deviceName, &fd, O_RDWR, "SpiComIF::initializeInterface");

View File

@ -3,3 +3,5 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER)
GPSHyperionLinuxController.cpp
)
endif()
add_subdirectory(startracker)

View File

@ -6,7 +6,7 @@ ArcsecDatalinkLayer::~ArcsecDatalinkLayer() {}
void ArcsecDatalinkLayer::slipInit() {
slipInfo.buffer = rxBuffer;
slipInfo.maxlength = StarTracker::MAX_FRAME_SIZE;
slipInfo.maxlength = startracker::MAX_FRAME_SIZE;
slipInfo.length = 0;
slipInfo.unescape_next = 0;
slipInfo.prev_state = SLIP_COMPLETE;

View File

@ -1,8 +1,8 @@
#ifndef BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
#define BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
#include "StarTrackerDefinitions.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
extern "C" {
#include "common/misc.h"
@ -79,12 +79,12 @@ class ArcsecDatalinkLayer : public HasReturnvaluesIF {
static const uint8_t STATUS_OFFSET = 2;
// Used by arcsec slip decoding function process received data
uint8_t rxBuffer[StarTracker::MAX_FRAME_SIZE];
uint8_t rxBuffer[startracker::MAX_FRAME_SIZE];
// Decoded frame will be copied to this buffer
uint8_t decodedFrame[StarTracker::MAX_FRAME_SIZE];
uint8_t decodedFrame[startracker::MAX_FRAME_SIZE];
// Buffer where encoded frames will be stored. First byte of encoded frame represents type of
// reply
uint8_t encBuffer[StarTracker::MAX_FRAME_SIZE * 2 + 2];
uint8_t encBuffer[startracker::MAX_FRAME_SIZE * 2 + 2];
// Size of decoded frame
uint32_t decFrameSize = 0;
// Size of encoded frame

View File

@ -28,6 +28,13 @@ static const char qx[] = "qx";
static const char qy[] = "qy";
static const char qz[] = "qz";
static const char IMAGE_PROCESSOR[] = "imageprocessor";
static const char IMAGE_PROCESSOR_MODE[] = "mode";
static const char STORE[] = "store";
static const char SIGNAL_THRESHOLD[] = "signalThreshold";
static const char IMAGE_PROCESSOR_DARK_THRESHOLD[] = "darkThreshold";
static const char BACKGROUND_COMPENSATION[] = "backgroundcompensation";
static const char CAMERA[] = "camera";
static const char MODE[] = "mode";
static const char FOCALLENGTH[] = "focallength";
@ -53,7 +60,6 @@ static const char VAL_7[] = "val7";
static const char REG_8[] = "reg8";
static const char VAL_8[] = "val8";
static const char FREQ_1[] = "freq1";
static const char FREQ_2[] = "freq2";
static const char BLOB[] = "blob";
static const char MIN_VALUE[] = "minValue";
@ -65,8 +71,8 @@ static const char MAX_TOTAL_VALUE[] = "maxTotalValue";
static const char MIN_BRIGHT_NEIGHBOURS[] = "minBrightNeighbours";
static const char MAX_BRIGHT_NEIGHBOURS[] = "maxBrightNeighbours";
static const char MAX_PIXEL_TO_CONSIDER[] = "maxPixelsToConsider";
static const char SIGNAL_THRESHOLD[] = "signalThreshold";
static const char DARK_THRESHOLD[] = "darkThreshold";
// static const char SIGNAL_THRESHOLD[] = "signalThreshold";
static const char BLOB_DARK_THRESHOLD[] = "darkThreshold";
static const char ENABLE_HISTOGRAM[] = "enableHistogram";
static const char ENABLE_CONTRAST[] = "enableContrast";
static const char BIN_MODE[] = "binMode";
@ -74,6 +80,7 @@ static const char BIN_MODE[] = "binMode";
static const char CENTROIDING[] = "centroiding";
static const char ENABLE_FILTER[] = "enableFilter";
static const char MAX_QUALITY[] = "maxquality";
static const char DARK_THRESHOLD[] = "darkthreshold";
static const char MIN_QUALITY[] = "minquality";
static const char MAX_INTENSITY[] = "maxintensity";
static const char MIN_INTENSITY[] = "minintensity";
@ -86,6 +93,7 @@ static const char TRANSMATRIX_10[] = "transmatrix10";
static const char TRANSMATRIX_11[] = "transmatrix11";
static const char LISA[] = "lisa";
static const char LISA_MODE[] = "mode";
static const char PREFILTER_DIST_THRESHOLD[] = "prefilterDistThreshold";
static const char PREFILTER_ANGLE_THRESHOLD[] = "prefilterAngleThreshold";
static const char FOV_WIDTH[] = "fov_width";
@ -118,9 +126,56 @@ static const char TRACKER_CHOICE[] = "trackerChoice";
static const char ALGO[] = "algo";
static const char L2T_MIN_CONFIDENCE[] = "l2t_minConfidence";
static const char L2T_MIN_MATCHED[] = "l2t_minConfidence";
static const char L2T_MIN_MATCHED[] = "l2t_minMatched";
static const char T2L_MIN_CONFIDENCE[] = "t2l_minConfidence";
static const char T2L_MIN_MATCHED[] = "t2l_minMatched";
static const char LOGLEVEL[] = "loglevel";
static const char LOGLEVEL1[] = "loglevel1";
static const char LOGLEVEL2[] = "loglevel2";
static const char LOGLEVEL3[] = "loglevel3";
static const char LOGLEVEL4[] = "loglevel4";
static const char LOGLEVEL5[] = "loglevel5";
static const char LOGLEVEL6[] = "loglevel6";
static const char LOGLEVEL7[] = "loglevel7";
static const char LOGLEVEL8[] = "loglevel8";
static const char LOGLEVEL9[] = "loglevel9";
static const char LOGLEVEL10[] = "loglevel10";
static const char LOGLEVEL11[] = "loglevel11";
static const char LOGLEVEL12[] = "loglevel12";
static const char LOGLEVEL13[] = "loglevel13";
static const char LOGLEVEL14[] = "loglevel14";
static const char LOGLEVEL15[] = "loglevel15";
static const char LOGLEVEL16[] = "loglevel16";
static const char SUBSCRIPTION[] = "subscription";
static const char TELEMETRY_1[] = "telemetry1";
static const char TELEMETRY_2[] = "telemetry2";
static const char TELEMETRY_3[] = "telemetry3";
static const char TELEMETRY_4[] = "telemetry4";
static const char TELEMETRY_5[] = "telemetry5";
static const char TELEMETRY_6[] = "telemetry6";
static const char TELEMETRY_7[] = "telemetry7";
static const char TELEMETRY_8[] = "telemetry8";
static const char TELEMETRY_9[] = "telemetry9";
static const char TELEMETRY_10[] = "telemetry10";
static const char TELEMETRY_11[] = "telemetry11";
static const char TELEMETRY_12[] = "telemetry12";
static const char TELEMETRY_13[] = "telemetry13";
static const char TELEMETRY_14[] = "telemetry14";
static const char TELEMETRY_15[] = "telemetry15";
static const char TELEMETRY_16[] = "telemetry16";
static const char LOG_SUBSCRIPTION[] = "logsubscription";
static const char LEVEL1[] = "level1";
static const char MODULE1[] = "module1";
static const char LEVEL2[] = "level2";
static const char MODULE2[] = "module2";
static const char DEBUG_CAMERA[] = "debugcamera";
static const char TIMING[] = "timing";
static const char TEST[] = "test";
} // namespace arcseckeys
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ */

View File

@ -8,9 +8,15 @@ ReturnValue_t ArcsecJsonParamBase::create(std::string fullname, uint8_t* buffer)
ReturnValue_t result = RETURN_OK;
result = init(fullname);
if (result != RETURN_OK) {
sif::warning << "ArcsecJsonParamBase::create: Failed to init parameter command for set "
<< setName << std::endl;
return result;
}
result = createCommand(buffer);
if (result != RETURN_OK) {
sif::warning << "ArcsecJsonParamBase::create: Failed to create parameter command for set "
<< setName << std::endl;
}
return result;
}
@ -91,5 +97,7 @@ ReturnValue_t ArcsecJsonParamBase::initSet() {
return RETURN_OK;
}
}
sif::warning << "ArcsecJsonParamBase::initSet: Set " << setName << "not present in json file"
<< std::endl;
return SET_NOT_EXISTS;
}

View File

@ -5,8 +5,8 @@
#include <fstream>
#include <nlohmann/json.hpp>
#include "StarTrackerDefinitions.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
extern "C" {
#include "thirdparty/arcsec_star_tracker/common/generated/tmtcstructs.h"

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,12 @@
#include "ArcsecDatalinkLayer.h"
#include "ArcsecJsonParamBase.h"
#include "StarTrackerDefinitions.h"
#include "OBSWConfig.h"
#include "StrHelper.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/src/fsfw/serialize/SerializeAdapter.h"
#include "fsfw/timemanager/Countdown.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "thirdparty/arcsec_star_tracker/common/SLIP.h"
/**
@ -47,6 +48,11 @@ class StarTrackerHandler : public DeviceHandlerBase {
void performOperationHook() override;
Submode_t getInitialSubmode() override;
static const Submode_t SUBMODE_BOOTLOADER = 1;
static const Submode_t SUBMODE_FIRMWARE = 2;
protected:
void doStartUp() override;
void doShutDown() override;
@ -56,6 +62,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData,
size_t commandDataLen) override;
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
@ -68,78 +75,76 @@ class StarTrackerHandler : public DeviceHandlerBase {
*/
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
virtual ReturnValue_t doSendReadHook() override;
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER;
//! [EXPORT] : [COMMENT] Received reply is too short
static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xB0);
//! [EXPORT] : [COMMENT] Received reply with invalid CRC
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xB1);
//! [EXPORT] : [COMMENT] Image loader executing
static const ReturnValue_t IMAGE_LOADER_EXECUTING = MAKE_RETURN_CODE(0xB2);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER;
//! [EXPORT] : [COMMENT] Status in temperature reply signals error
static const ReturnValue_t TEMPERATURE_REQ_FAILED = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Ping command failed
static const ReturnValue_t PING_FAILED = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Status in version reply signals error
static const ReturnValue_t VERSION_REQ_FAILED = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t VERSION_REQ_FAILED = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Status in interface reply signals error
static const ReturnValue_t INTERFACE_REQ_FAILED = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t INTERFACE_REQ_FAILED = MAKE_RETURN_CODE(0xA3);
//! [EXPORT] : [COMMENT] Status in power reply signals error
static const ReturnValue_t POWER_REQ_FAILED = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t POWER_REQ_FAILED = MAKE_RETURN_CODE(0xA4);
//! [EXPORT] : [COMMENT] Status of reply to parameter set command signals error
static const ReturnValue_t SET_PARAM_FAILED = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t SET_PARAM_FAILED = MAKE_RETURN_CODE(0xA5);
//! [EXPORT] : [COMMENT] Status of reply to action command signals error
static const ReturnValue_t ACTION_FAILED = MAKE_RETURN_CODE(0xA7);
//! [EXPORT] : [COMMENT] Received upload image command with invalid length
static const ReturnValue_t UPLOAD_TOO_SHORT = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Received upload image command with invalid position field
static const ReturnValue_t UPLOAD_INVALID_POSITION = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Position value in upload image reply not matching sent position
static const ReturnValue_t UPLOAD_IMAGE_FAILED = MAKE_RETURN_CODE(0xA9);
//! [EXPORT] : [COMMENT] Received upload image command with invalid length
static const ReturnValue_t INVALID_UPLOAD_COMMAND = MAKE_RETURN_CODE(0xAA);
static const ReturnValue_t ACTION_FAILED = MAKE_RETURN_CODE(0xA6);
//! [EXPORT] : [COMMENT] Received invalid path string. Exceeds allowed length
static const ReturnValue_t FILE_PATH_TOO_LONG = MAKE_RETURN_CODE(0xAB);
static const ReturnValue_t FILE_PATH_TOO_LONG = MAKE_RETURN_CODE(0xA7);
//! [EXPORT] : [COMMENT] Name of file received with command is too long
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xAC);
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Received version reply with invalid program ID
static const ReturnValue_t INVALID_PROGRAM = MAKE_RETURN_CODE(0xAD);
static const ReturnValue_t INVALID_PROGRAM = MAKE_RETURN_CODE(0xA9);
//! [EXPORT] : [COMMENT] Status field reply signals error
static const ReturnValue_t REPLY_ERROR = MAKE_RETURN_CODE(0xAE);
//! [EXPORT] : [COMMENT] Status field of contrast reply signals error
static const ReturnValue_t CONTRAST_REQ_FAILED = MAKE_RETURN_CODE(0xAE);
static const ReturnValue_t REPLY_ERROR = MAKE_RETURN_CODE(0xAA);
//! [EXPORT] : [COMMENT] Received command which is too short (some data is missing for proper
//! execution)
static const ReturnValue_t COMMAND_TOO_SHORT = MAKE_RETURN_CODE(0xAF);
static const ReturnValue_t COMMAND_TOO_SHORT = MAKE_RETURN_CODE(0xAB);
//! [EXPORT] : [COMMENT] Received command with invalid length (too few or too many parameters)
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xAC);
//! [EXPORT] : [COMMENT] Region mismatch between send and received data
static const ReturnValue_t REGION_MISMATCH = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t REGION_MISMATCH = MAKE_RETURN_CODE(0xAD);
//! [EXPORT] : [COMMENT] Address mismatch between send and received data
static const ReturnValue_t ADDRESS_MISMATCH = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t ADDRESS_MISMATCH = MAKE_RETURN_CODE(0xAE);
//! [EXPORT] : [COMMENT] Length field mismatch between send and received data
static const ReturnValue_t lENGTH_MISMATCH = MAKE_RETURN_CODE(0xB3);
static const ReturnValue_t lENGTH_MISMATCH = MAKE_RETURN_CODE(0xAF);
//! [EXPORT] : [COMMENT] Specified file does not exist
static const ReturnValue_t FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xB4);
//! [EXPORT] : [COMMENT] Reply to upload centroid does not match commanded centroid id
static const ReturnValue_t UPLOAD_CENTROID_ID_MISMATCH = MAKE_RETURN_CODE(0xB5);
static const ReturnValue_t FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xB0);
//! [EXPORT] : [COMMENT] Download blob pixel command has invalid type field
static const ReturnValue_t INVALID_TYPE = MAKE_RETURN_CODE(0xB6);
static const ReturnValue_t INVALID_TYPE = MAKE_RETURN_CODE(0xB1);
//! [EXPORT] : [COMMENT] Received FPGA action command with invalid ID
static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE(0xB7);
static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE(0xB2);
//! [EXPORT] : [COMMENT] Received reply is too short
static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xB3);
//! [EXPORT] : [COMMENT] Received reply with invalid CRC
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xB4);
//! [EXPORT] : [COMMENT] Star tracker handler currently executing a command and using the
//! communication interface
static const ReturnValue_t STR_HELPER_EXECUTING = MAKE_RETURN_CODE(0xB5);
//! [EXPORT] : [COMMENT] Star tracker is already in firmware mode
static const ReturnValue_t STARTRACKER_ALREADY_BOOTED = MAKE_RETURN_CODE(0xB6);
//! [EXPORT] : [COMMENT] Star tracker is in firmware mode but must be in bootloader mode to
//! execute this command
static const ReturnValue_t STARTRACKER_RUNNING_FIRMWARE = MAKE_RETURN_CODE(0xB7);
//! [EXPORT] : [COMMENT] Star tracker is in bootloader mode but must be in firmware mode to
//! execute this command
static const ReturnValue_t STARTRACKER_RUNNING_BOOTLOADER = MAKE_RETURN_CODE(0xB8);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER;
//! [EXPORT] : [COMMENT] Failed to boot firmware
static const Event BOOTING_FIRMWARE_FAILED = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
static const Event BOOTING_BOOTLOADER_FAILED = MAKE_EVENT(2, severity::LOW);
static const size_t MAX_PATH_SIZE = 50;
static const size_t MAX_FILE_NAME = 30;
// position (uint32) + 1024 image data
static const size_t UPLOAD_COMMAND_LEN = 1028;
// Max valid position value in upload image command
static const uint16_t MAX_POSITION = 4095;
static const uint8_t STATUS_OFFSET = 1;
static const uint8_t PARAMS_OFFSET = 1;
static const uint8_t TICKS_OFFSET = 2;
@ -154,37 +159,14 @@ class StarTrackerHandler : public DeviceHandlerBase {
static const MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
static const uint32_t MUTEX_TIMEOUT = 20;
static const uint32_t BOOT_TIMEOUT = 1000;
static const uint32_t DEFAULT_TRANSITION_DELAY = 15000;
class WriteCmd {
class FlashReadCmd {
public:
static const uint8_t ADDRESS_OFFSET = 1;
static const uint8_t FILE_OFFSET = 5;
// Minimum length of a write command (region, address and filename)
// Minimum length of a read command (region, length and filename)
static const size_t MIN_LENGTH = 7;
};
class ReadCmd {
public:
static const uint8_t ADDRESS_OFFSET = 1;
static const uint8_t LENGTH_OFFSET = 5;
static const uint8_t FILE_OFFSET = 9;
// Minimum length of a read command (region, address, length and filename)
static const size_t MIN_LENGTH = 11;
};
class EraseCmd {
public:
static const uint8_t LENGTH = 1;
uint8_t rememberRegion = 0;
};
EraseCmd eraseCmd;
class UnlockCmd {
public:
static const uint8_t CODE_OFFSET = 1;
};
class ChecksumCmd {
public:
static const uint8_t ADDRESS_OFFSET = 1;
@ -198,94 +180,69 @@ class StarTrackerHandler : public DeviceHandlerBase {
ChecksumCmd checksumCmd;
class SetTimeCmd {
public:
static const uint8_t LENGTH = 8;
};
class DownloadCentroidCmd {
public:
static const uint8_t LENGTH = 1;
};
class UploadCentroid {
public:
uint8_t rememberId = 0;
};
UploadCentroid uploadCentroid;
class DownloadMatchedStarCmd {
public:
static const uint8_t LENGTH = 1;
};
class DownloadDbImageCmd {
public:
static const uint8_t LENGTH = 1;
};
class DownloadBlobPixCmd {
public:
static const uint8_t LENGTH = 2;
static const uint8_t NORMAL = 0;
static const uint8_t FAST = 1;
};
class FpgaDownloadCmd {
public:
static const uint8_t MIN_LENGTH = 10;
};
class FpgaActionCmd {
public:
static const uint8_t LENGTH = 1;
static const uint8_t ID = 3;
};
MessageQueueIF* eventQueue = nullptr;
ArcsecDatalinkLayer dataLinkLayer;
StarTracker::TemperatureSet temperatureSet;
StarTracker::VersionSet versionSet;
StarTracker::PowerSet powerSet;
StarTracker::InterfaceSet interfaceSet;
StarTracker::TimeSet timeSet;
StarTracker::SolutionSet solutionSet;
StarTracker::HistogramSet histogramSet;
StarTracker::ContrastSet contrastSet;
StarTracker::ChecksumSet checksumSet;
StarTracker::DownloadCentroidSet downloadCentroidSet;
StarTracker::DownloadMatchedStar downloadMatchedStar;
StarTracker::DownloadDBImage downloadDbImage;
StarTracker::DownloadBlobPixel downloadBlobPixel;
StarTracker::CameraSet cameraSet;
StarTracker::LimitsSet limitsSet;
StarTracker::BlobSet blobSet;
startracker::TemperatureSet temperatureSet;
startracker::VersionSet versionSet;
startracker::PowerSet powerSet;
startracker::InterfaceSet interfaceSet;
startracker::TimeSet timeSet;
startracker::SolutionSet solutionSet;
startracker::HistogramSet histogramSet;
startracker::ChecksumSet checksumSet;
startracker::CameraSet cameraSet;
startracker::LimitsSet limitsSet;
startracker::LogLevelSet loglevelSet;
startracker::MountingSet mountingSet;
startracker::ImageProcessorSet imageProcessorSet;
startracker::CentroidingSet centroidingSet;
startracker::LisaSet lisaSet;
startracker::MatchingSet matchingSet;
startracker::TrackingSet trackingSet;
startracker::ValidationSet validationSet;
startracker::AlgoSet algoSet;
startracker::SubscriptionSet subscriptionSet;
startracker::LogSubscriptionSet logSubscriptionSet;
startracker::DebugCameraSet debugCameraSet;
// Pointer to object responsible for uploading and downloading images to/from the star tracker
StrHelper* strHelper = nullptr;
uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE];
uint8_t commandBuffer[startracker::MAX_FRAME_SIZE];
// Countdown to insert delay for star tracker to switch from bootloader to firmware program
// Loading firmware requires some time and the command will not trigger a reply when executed
Countdown bootCountdown;
std::string paramJsonFile = "/mnt/sd0/startracker/full.json";
#ifdef EGSE
std::string paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
#else
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
std::string paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
#else
std::string paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
#endif
#endif
enum class InternalState { TEMPERATURE_REQUEST };
enum class NormalState { TEMPERATURE_REQUEST, SOLUTION_REQUEST };
InternalState internalState = InternalState::TEMPERATURE_REQUEST;
NormalState normalState = NormalState::TEMPERATURE_REQUEST;
enum class StartupState {
enum class InternalState {
IDLE,
CHECK_BOOT_STATE,
BOOT,
REQ_VERSION,
VERIFY_BOOT,
STARTUP_CHECK,
BOOT_DELAY,
FIRMWARE_CHECK,
LOGLEVEL,
LIMITS,
TRACKING,
MOUNTING,
IMAGE_PROCESSOR,
CAMERA,
BLOB,
CENTROIDING,
@ -293,10 +250,20 @@ class StarTrackerHandler : public DeviceHandlerBase {
MATCHING,
VALIDATION,
ALGO,
LOG_SUBSCRIPTION,
DEBUG_CAMERA,
WAIT_FOR_EXECUTION,
DONE
DONE,
FAILED_FIRMWARE_BOOT,
BOOT_BOOTLOADER,
BOOTLOADER_CHECK,
BOOTING_BOOTLOADER_FAILED
};
InternalState internalState = InternalState::IDLE;
enum class StartupState { IDLE, CHECK_PROGRAM, WAIT_CHECK_PROGRAM, BOOT_BOOTLOADER, DONE };
StartupState startupState = StartupState::IDLE;
bool strHelperExecuting = false;
@ -338,24 +305,6 @@ class StarTrackerHandler : public DeviceHandlerBase {
*/
void handleEvent(EventMessage* eventMessage);
/**
* @brief Executes the write command
*
* @param commandData Pointer to received command data
* @param commandDataLen Size of received command data
*
* @return RETURN_OK if start of execution was successful, otherwise error return value
*/
ReturnValue_t executeWriteCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Starts the execution of the fpga download command
*
* @param commandData Pointer to buffer with command data
* @param commandDataLen Size of received command
*/
ReturnValue_t executeFpgaDownloadCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Extracts information for flash-read-command from TC data and starts execution of
* flash-read-procedure
@ -365,7 +314,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
*
* @return RETURN_OK if start of execution was successful, otherwise error return value
*/
ReturnValue_t executeReadCommand(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t executeFlashReadCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with data to boot image (works only when star tracker is
@ -373,36 +322,11 @@ class StarTrackerHandler : public DeviceHandlerBase {
*/
void prepareBootCommand();
/**
* @brief Fills command buffer with command to erase a flash region
*/
ReturnValue_t prepareEraseCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with command to unlock flash region
*/
ReturnValue_t prepareUnlockCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with command to get the checksum of a flash part
*/
ReturnValue_t prepareChecksumCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with command to set the unix time
*/
ReturnValue_t prepareSetTimeCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with command to request a centroid
*/
ReturnValue_t prepareDownloadCentroidCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with command to upload a centroid for testing purpose
*/
ReturnValue_t prepareUploadCentroidCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills the command buffer with the command to take an image.
*/
@ -426,7 +350,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
/**
* @brief Fills command buffer with data to reboot star tracker.
*/
void prepareRebootCommand();
void prepareSwitchToBootloaderCmd();
/**
* @brief Fills command buffer with data to subscribe to a telemetry packet.
@ -451,13 +375,6 @@ class StarTrackerHandler : public DeviceHandlerBase {
*/
void prepareHistogramRequest();
void prepareContrastRequest();
/**
* @brief Fills command buffer with command to reset the error signal of the star tracker
*/
void prepareErrorResetRequest();
/**
* @brief Reads parameters from json file specified by string in commandData and
* prepares the command to apply the parameter set to the star tracker
@ -472,40 +389,23 @@ class StarTrackerHandler : public DeviceHandlerBase {
ArcsecJsonParamBase& paramSet);
/**
* @brief Fills command buffer with data to request matched star.
*/
ReturnValue_t prepareDownloadMatchedStarCommand(const uint8_t* commandData,
size_t commandDataLen);
/**
* @brief Fills command buffer with data to request matched star coordinates.
*/
ReturnValue_t prepareDownloadDbImageCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Fills command buffer with data to request output of the blob filter algorithm.
*/
ReturnValue_t prepareDownloadBlobPixelCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief With this command the FPGA update will be applied to the star tracker
*/
ReturnValue_t prepareFpgaActionCommand(const uint8_t* commandData, size_t commandDataLen);
/**
* @brief Will fill the command buffer with the command to request the set camera parameters.
* @brief The following function will fill the command buffer with the command to request
* a parameter set.
*/
ReturnValue_t prepareRequestCameraParams();
/**
* @brief Will fill the command buffer with the command to request the set limits.
*/
ReturnValue_t prepareRequestLimitsParams();
/**
* @brief Will fill the command buffer with the command to request the set blob parameters.
*/
ReturnValue_t prepareRequestBlobParams();
ReturnValue_t prepareRequestLogLevelParams();
ReturnValue_t prepareRequestMountingParams();
ReturnValue_t prepareRequestImageProcessorParams();
ReturnValue_t prepareRequestCentroidingParams();
ReturnValue_t prepareRequestLisaParams();
ReturnValue_t prepareRequestMatchingParams();
ReturnValue_t prepareRequestTrackingParams();
ReturnValue_t prepareRequestValidationParams();
ReturnValue_t prepareRequestAlgoParams();
ReturnValue_t prepareRequestSubscriptionParams();
ReturnValue_t prepareRequestLogSubscriptionParams();
ReturnValue_t prepareRequestDebugCameraParams();
/**
* @brief Handles action replies with datasets.
@ -522,11 +422,6 @@ class StarTrackerHandler : public DeviceHandlerBase {
*/
ReturnValue_t handleUploadCentroidReply();
/**
* @brief Handles reply to erase command
*/
ReturnValue_t handleEraseReply();
/**
* @brief Handles reply to checksum command
*/
@ -560,6 +455,20 @@ class StarTrackerHandler : public DeviceHandlerBase {
* @return RETURN_OK if successful, otherwise error return value
*/
ReturnValue_t handleTm(LocalPoolDataSetBase& dataset, size_t size);
/**
* @brief Checks if star tracker is in valid mode for executing the received command.
*
* @param actioId Id of received command
*
* @return RETURN_OK if star tracker is in valid mode, otherwise error return value
*/
ReturnValue_t checkCommand(ActionId_t actionId);
void doOnTransition(Submode_t subModeFrom);
void doNormalTransition(Mode_t modeFrom, Submode_t subModeFrom);
void bootFirmware(Mode_t toMode);
void bootBootloader();
};
#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */

View File

@ -10,7 +10,7 @@ ReturnValue_t Limits::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::LIMITS);
addSetParamHeader(buffer, startracker::ID::LIMITS);
offset = 2;
result = getParam(arcseckeys::ACTION, param);
if (result != RETURN_OK) {
@ -88,7 +88,7 @@ ReturnValue_t Tracking::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::TRACKING);
addSetParamHeader(buffer, startracker::ID::TRACKING);
offset = 2;
result = getParam(arcseckeys::THIN_LIMIT, param);
if (result != RETURN_OK) {
@ -124,7 +124,7 @@ ReturnValue_t Mounting::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::MOUNTING);
addSetParamHeader(buffer, startracker::ID::MOUNTING);
offset = 2;
result = getParam(arcseckeys::qw, param);
if (result != RETURN_OK) {
@ -152,6 +152,48 @@ ReturnValue_t Mounting::createCommand(uint8_t* buffer) {
return RETURN_OK;
}
ImageProcessor::ImageProcessor() : ArcsecJsonParamBase(arcseckeys::IMAGE_PROCESSOR) {}
size_t ImageProcessor::getSize() { return COMMAND_SIZE; }
ReturnValue_t ImageProcessor::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::IMAGE_PROCESSOR);
offset = 2;
result = getParam(arcseckeys::IMAGE_PROCESSOR_MODE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::STORE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::SIGNAL_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::IMAGE_PROCESSOR_DARK_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::BACKGROUND_COMPENSATION, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
return RETURN_OK;
}
Camera::Camera() : ArcsecJsonParamBase(arcseckeys::CAMERA) {}
size_t Camera::getSize() { return COMMAND_SIZE; }
@ -160,7 +202,7 @@ ReturnValue_t Camera::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::CAMERA);
addSetParamHeader(buffer, startracker::ID::CAMERA);
offset = 2;
result = getParam(arcseckeys::MODE, param);
if (result != RETURN_OK) {
@ -304,116 +346,7 @@ ReturnValue_t Camera::createCommand(uint8_t* buffer) {
if (result != RETURN_OK) {
return result;
}
addfloat(param, buffer + offset);
offset += sizeof(float);
result = getParam(arcseckeys::FREQ_2, param);
if (result != RETURN_OK) {
return result;
}
addfloat(param, buffer + offset);
return RETURN_OK;
}
Blob::Blob() : ArcsecJsonParamBase(arcseckeys::BLOB) {}
size_t Blob::getSize() { return COMMAND_SIZE; }
ReturnValue_t Blob::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::BLOB);
offset = 2;
result = getParam(arcseckeys::MODE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::MIN_VALUE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::MIN_DISTANCE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::NEIGHBOUR_DISTANCE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::NEIGHBOUR_BRIGHT_PIXELS, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::MIN_TOTAL_VALUE, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::MAX_TOTAL_VALUE, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::MIN_BRIGHT_NEIGHBOURS, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::MAX_BRIGHT_NEIGHBOURS, param);
if (result != RETURN_OK) {
return result;
}
adduint16(param, buffer + offset);
offset += sizeof(uint16_t);
result = getParam(arcseckeys::MAX_PIXEL_TO_CONSIDER, param);
if (result != RETURN_OK) {
return result;
}
adduint32(param, buffer + offset);
offset += sizeof(uint32_t);
result = getParam(arcseckeys::SIGNAL_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::DARK_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::ENABLE_HISTOGRAM, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::ENABLE_CONTRAST, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::BIN_MODE, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
return RETURN_OK;
}
@ -425,7 +358,7 @@ ReturnValue_t Centroiding::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::CENTROIDING);
addSetParamHeader(buffer, startracker::ID::CENTROIDING);
offset = 2;
result = getParam(arcseckeys::ENABLE_FILTER, param);
if (result != RETURN_OK) {
@ -439,6 +372,12 @@ ReturnValue_t Centroiding::createCommand(uint8_t* buffer) {
}
addfloat(param, buffer + offset);
offset += sizeof(float);
result = getParam(arcseckeys::DARK_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
}
addfloat(param, buffer + offset);
offset += sizeof(float);
result = getParam(arcseckeys::MIN_QUALITY, param);
if (result != RETURN_OK) {
return result;
@ -509,8 +448,14 @@ ReturnValue_t Lisa::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::LISA);
addSetParamHeader(buffer, startracker::ID::LISA);
offset = 2;
result = getParam(arcseckeys::LISA_MODE, param);
if (result != RETURN_OK) {
return result;
}
adduint32(param, buffer + offset);
offset += sizeof(uint32_t);
result = getParam(arcseckeys::PREFILTER_DIST_THRESHOLD, param);
if (result != RETURN_OK) {
return result;
@ -559,6 +504,12 @@ ReturnValue_t Lisa::createCommand(uint8_t* buffer) {
}
addfloat(param, buffer + offset);
offset += sizeof(float);
result = getParam(arcseckeys::RATING_WEIGHT_MEAN_SUM, param);
if (result != RETURN_OK) {
return result;
}
addfloat(param, buffer + offset);
offset += sizeof(float);
result = getParam(arcseckeys::RATING_WEIGHT_DB_STAR_COUNT, param);
if (result != RETURN_OK) {
return result;
@ -594,7 +545,7 @@ ReturnValue_t Matching::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::MATCHING);
addSetParamHeader(buffer, startracker::ID::MATCHING);
offset = 2;
result = getParam(arcseckeys::SQUARED_DISTANCE_LIMIT, param);
if (result != RETURN_OK) {
@ -618,7 +569,7 @@ ReturnValue_t Validation::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::VALIDATION);
addSetParamHeader(buffer, startracker::ID::VALIDATION);
offset = 2;
result = getParam(arcseckeys::STABLE_COUNT, param);
if (result != RETURN_OK) {
@ -654,7 +605,7 @@ ReturnValue_t Algo::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, StarTracker::ID::ALGO);
addSetParamHeader(buffer, startracker::ID::ALGO);
offset = 2;
result = getParam(arcseckeys::MODE, param);
if (result != RETURN_OK) {
@ -687,3 +638,280 @@ ReturnValue_t Algo::createCommand(uint8_t* buffer) {
adduint8(param, buffer + offset);
return RETURN_OK;
}
LogLevel::LogLevel() : ArcsecJsonParamBase(arcseckeys::LOGLEVEL) {}
size_t LogLevel::getSize() { return COMMAND_SIZE; }
ReturnValue_t LogLevel::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::LOG_LEVEL);
offset = 2;
result = getParam(arcseckeys::LOGLEVEL1, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL2, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL3, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL4, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL5, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL6, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL7, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL8, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL9, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL10, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL11, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL12, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL13, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL14, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL15, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LOGLEVEL16, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
return RETURN_OK;
}
Subscription::Subscription() : ArcsecJsonParamBase(arcseckeys::SUBSCRIPTION) {}
size_t Subscription::getSize() { return COMMAND_SIZE; }
ReturnValue_t Subscription::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::SUBSCRIPTION);
offset = 2;
result = getParam(arcseckeys::TELEMETRY_1, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_2, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_3, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_4, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_5, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_6, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_7, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_8, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_9, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_10, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_11, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_12, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_13, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_14, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_15, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::TELEMETRY_16, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
return RETURN_OK;
}
LogSubscription::LogSubscription() : ArcsecJsonParamBase(arcseckeys::LOG_SUBSCRIPTION) {}
size_t LogSubscription::getSize() { return COMMAND_SIZE; }
ReturnValue_t LogSubscription::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::LOG_SUBSCRIPTION);
offset = 2;
result = getParam(arcseckeys::LEVEL1, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::MODULE1, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::LEVEL2, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
offset += sizeof(uint8_t);
result = getParam(arcseckeys::MODULE2, param);
if (result != RETURN_OK) {
return result;
}
adduint8(param, buffer + offset);
return RETURN_OK;
}
DebugCamera::DebugCamera() : ArcsecJsonParamBase(arcseckeys::DEBUG_CAMERA) {}
size_t DebugCamera::getSize() { return COMMAND_SIZE; }
ReturnValue_t DebugCamera::createCommand(uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::DEBUG_CAMERA);
offset = 2;
result = getParam(arcseckeys::TIMING, param);
if (result != RETURN_OK) {
return result;
}
adduint32(param, buffer + offset);
offset += sizeof(uint32_t);
result = getParam(arcseckeys::TEST, param);
if (result != RETURN_OK) {
return result;
}
adduint32(param, buffer + offset);
return RETURN_OK;
}

View File

@ -60,6 +60,22 @@ class Mounting : public ArcsecJsonParamBase {
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates the command to configure the image processor
*
*/
class ImageProcessor : public ArcsecJsonParamBase {
public:
ImageProcessor();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 9;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates the command to set the mounting quaternion
*
@ -71,23 +87,7 @@ class Camera : public ArcsecJsonParamBase {
size_t getSize();
private:
static const size_t COMMAND_SIZE = 43;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates the command to configure the blob algorithm
*
*/
class Blob : public ArcsecJsonParamBase {
public:
Blob();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 24;
static const size_t COMMAND_SIZE = 39;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
@ -103,7 +103,7 @@ class Centroiding : public ArcsecJsonParamBase {
size_t getSize();
private:
static const size_t COMMAND_SIZE = 47;
static const size_t COMMAND_SIZE = 51;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
@ -119,7 +119,7 @@ class Lisa : public ArcsecJsonParamBase {
size_t getSize();
private:
static const size_t COMMAND_SIZE = 48;
static const size_t COMMAND_SIZE = 52;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
@ -173,4 +173,68 @@ class Algo : public ArcsecJsonParamBase {
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to configure the log level parameters.
*
*/
class LogLevel : public ArcsecJsonParamBase {
public:
LogLevel();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 18;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set subscription parameters.
*
*/
class Subscription : public ArcsecJsonParamBase {
public:
Subscription();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 18;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set log subscription parameters.
*
*/
class LogSubscription : public ArcsecJsonParamBase {
public:
LogSubscription();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 6;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set debug camera parameters
*
*/
class DebugCamera : public ArcsecJsonParamBase {
public:
DebugCamera();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 10;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_STARTRACKERJSONCOMMANDS_H_ */

View File

@ -3,6 +3,9 @@
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
#include "fsfw/timemanager/Countdown.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "mission/utility/Timestamp.h"
StrHelper::StrHelper(object_id_t objectId) : SystemObject(objectId) {}
@ -10,11 +13,13 @@ StrHelper::StrHelper(object_id_t objectId) : SystemObject(objectId) {}
StrHelper::~StrHelper() {}
ReturnValue_t StrHelper::initialize() {
#ifdef XIPHOS_Q7S
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "StrHelper::initialize: Invalid SD Card Manager" << std::endl;
return RETURN_FAILED;
}
#endif
return RETURN_OK;
}
@ -47,16 +52,6 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
internalState = InternalState::IDLE;
break;
}
case InternalState::FLASH_WRITE: {
result = performFlashWrite();
if (result == RETURN_OK) {
triggerEvent(FLASH_WRITE_SUCCESSFUL);
} else {
triggerEvent(FLASH_WRITE_FAILED);
}
internalState = InternalState::IDLE;
break;
}
case InternalState::FLASH_READ: {
result = performFlashRead();
if (result == RETURN_OK) {
@ -67,22 +62,12 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
internalState = InternalState::IDLE;
break;
}
case InternalState::DOWNLOAD_FPGA_IMAGE: {
result = performFpgaDownload();
case InternalState::FIRMWARE_UPDATE: {
result = performFirmwareUpdate();
if (result == RETURN_OK) {
triggerEvent(FPGA_DOWNLOAD_SUCCESSFUL);
triggerEvent(FIRMWARE_UPDATE_SUCCESSFUL);
} else {
triggerEvent(FPGA_DOWNLOAD_FAILED);
}
internalState = InternalState::IDLE;
break;
}
case InternalState::UPLOAD_FPGA_IMAGE: {
result = performFpgaUpload();
if (result == RETURN_OK) {
triggerEvent(FPGA_UPLOAD_SUCCESSFUL);
} else {
triggerEvent(FPGA_UPLOAD_FAILED);
triggerEvent(FIRMWARE_UPDATE_FAILED);
}
internalState = InternalState::IDLE;
break;
@ -106,10 +91,12 @@ ReturnValue_t StrHelper::setComIF(DeviceCommunicationIF* communicationInterface_
void StrHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(fullname);
if (result != RETURN_OK) {
return result;
}
#endif
uploadImage.uploadFile = fullname;
if (not std::filesystem::exists(fullname)) {
return FILE_NOT_EXISTS;
@ -121,10 +108,12 @@ ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
}
ReturnValue_t StrHelper::startImageDownload(std::string path) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(path);
if (result != RETURN_OK) {
return result;
}
#endif
if (not std::filesystem::exists(path)) {
return PATH_NOT_EXISTS;
}
@ -141,37 +130,37 @@ void StrHelper::setDownloadImageName(std::string filename) { downloadImage.filen
void StrHelper::setFlashReadFilename(std::string filename) { flashRead.filename = filename; }
void StrHelper::setDownloadFpgaImage(std::string filename) { fpgaDownload.fileName = filename; }
ReturnValue_t StrHelper::startFlashWrite(std::string fullname, uint8_t region, uint32_t address) {
ReturnValue_t StrHelper::startFirmwareUpdate(std::string fullname) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(fullname);
if (result != RETURN_OK) {
return result;
}
#endif
flashWrite.fullname = fullname;
if (not std::filesystem::exists(flashWrite.fullname)) {
return FILE_NOT_EXISTS;
}
flashWrite.address = address;
flashWrite.region = region;
internalState = InternalState::FLASH_WRITE;
flashWrite.firstRegion = static_cast<uint8_t>(startracker::FirmwareRegions::FIRST);
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST);
internalState = InternalState::FIRMWARE_UPDATE;
semaphore.release();
terminate = false;
return RETURN_OK;
}
ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t region, uint32_t address,
uint32_t length) {
ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t startRegion, uint32_t length) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(path);
if (result != RETURN_OK) {
return result;
}
#endif
flashRead.path = path;
if (not std::filesystem::exists(flashRead.path)) {
return FILE_NOT_EXISTS;
}
flashRead.address = address;
flashRead.region = region;
flashRead.startRegion = startRegion;
flashRead.size = length;
internalState = InternalState::FLASH_READ;
semaphore.release();
@ -179,39 +168,24 @@ ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t region, uint32
return RETURN_OK;
}
ReturnValue_t StrHelper::startFpgaDownload(std::string path, uint32_t startPosition,
uint32_t length) {
fpgaDownload.path = path;
fpgaDownload.startPosition = startPosition;
fpgaDownload.length = length;
internalState = InternalState::DOWNLOAD_FPGA_IMAGE;
semaphore.release();
terminate = false;
return RETURN_OK;
}
void StrHelper::disableTimestamping() { timestamping = false; }
ReturnValue_t StrHelper::startFpgaUpload(std::string uploadFile) {
fpgaUpload.uploadFile = uploadFile;
internalState = InternalState::UPLOAD_FPGA_IMAGE;
semaphore.release();
terminate = false;
return RETURN_OK;
}
void StrHelper::enableTimestamping() { timestamping = true; }
ReturnValue_t StrHelper::performImageDownload() {
ReturnValue_t result;
struct DownloadActionRequest downloadReq;
uint32_t size = 0;
uint32_t retries = 0;
Timestamp timestamp;
std::string image = downloadImage.path + "/" + timestamp.str() + downloadImage.filename;
std::ofstream file(image, std::ios_base::app | std::ios_base::out);
std::string image = makeFullFilename(downloadImage.path, downloadImage.filename);
std::ofstream file(image, std::ios_base::out);
if (not std::filesystem::exists(image)) {
return FILE_CREATION_FAILED;
}
downloadReq.position = 0;
while (downloadReq.position < ImageDownload::LAST_POSITION) {
if (terminate) {
file.close();
return RETURN_OK;
}
arc_pack_download_action_req(&downloadReq, commandBuffer, &size);
@ -246,8 +220,11 @@ ReturnValue_t StrHelper::performImageDownload() {
return result;
}
file.write(reinterpret_cast<const char*>(datalinkLayer.getReply() + IMAGE_DATA_OFFSET),
IMAGE_DATA_SIZE);
CHUNK_SIZE);
downloadReq.position++;
#if OBSW_DEBUG_STARTRACKER == 1
printProgress(downloadReq.position, ImageDownload::LAST_POSITION);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
retries = 0;
}
file.close();
@ -273,6 +250,7 @@ ReturnValue_t StrHelper::performImageUpload() {
imageSize = file.tellg();
while ((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) {
if (terminate) {
file.close();
return RETURN_OK;
}
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
@ -280,12 +258,17 @@ ReturnValue_t StrHelper::performImageUpload() {
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
result = sendAndRead(size, uploadReq.position);
if (result != RETURN_OK) {
file.close();
return RETURN_FAILED;
}
result = checkActionReply();
if (result != RETURN_OK) {
file.close();
return result;
}
#if OBSW_DEBUG_STARTRACKER == 1
printProgress((uploadReq.position + 1) * SIZE_IMAGE_PART, imageSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
uploadReq.position++;
}
std::memset(uploadReq.data, 0, sizeof(uploadReq.data));
@ -303,13 +286,28 @@ ReturnValue_t StrHelper::performImageUpload() {
if (result != RETURN_OK) {
return result;
}
#if OBSW_DEBUG_STARTRACKER == 1
printProgress((uploadReq.position + 1) * SIZE_IMAGE_PART, imageSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
return RETURN_OK;
}
ReturnValue_t StrHelper::performFirmwareUpdate() {
using namespace startracker;
ReturnValue_t result = RETURN_OK;
result = unlockAndEraseRegions(static_cast<uint32_t>(startracker::FirmwareRegions::FIRST),
static_cast<uint32_t>(startracker::FirmwareRegions::LAST));
if (result != RETURN_OK) {
return result;
}
result = performFlashWrite();
return result;
}
ReturnValue_t StrHelper::performFlashWrite() {
ReturnValue_t result = RETURN_OK;
uint32_t size = 0;
uint32_t remainingBytes = 0;
uint32_t bytesWritten = 0;
uint32_t fileSize = 0;
struct WriteActionRequest req;
if (not std::filesystem::exists(flashWrite.fullname)) {
@ -320,36 +318,55 @@ ReturnValue_t StrHelper::performFlashWrite() {
std::ifstream file(flashWrite.fullname, std::ifstream::binary);
file.seekg(0, file.end);
fileSize = file.tellg();
remainingBytes = fileSize;
req.region = flashWrite.region;
req.address = flashWrite.address;
req.length = MAX_FLASH_DATA;
while (remainingBytes >= MAX_FLASH_DATA) {
if (fileSize > FLASH_REGION_SIZE * (flashWrite.lastRegion - flashWrite.firstRegion)) {
sif::warning << "StrHelper::performFlashWrite: Invalid file" << std::endl;
return RETURN_FAILED;
}
uint32_t fileChunks = fileSize / CHUNK_SIZE;
bytesWritten = 0;
req.region = flashWrite.firstRegion;
req.length = CHUNK_SIZE;
for (uint32_t idx = 0; idx < fileChunks; idx++) {
if (terminate) {
file.close();
return RETURN_OK;
}
file.seekg(fileSize - remainingBytes, file.beg);
file.read(reinterpret_cast<char*>(req.data), MAX_FLASH_DATA);
file.seekg(idx * CHUNK_SIZE, file.beg);
file.read(reinterpret_cast<char*>(req.data), CHUNK_SIZE);
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
req.region++;
bytesWritten = 0;
}
req.address = bytesWritten;
arc_pack_write_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
return RETURN_FAILED;
}
result = checkFlashActionReply(req.region, req.address, req.length);
if (result != RETURN_OK) {
file.close();
return result;
}
remainingBytes = remainingBytes - MAX_FLASH_DATA;
result = checkActionReply();
if (result != RETURN_OK) {
file.close();
return result;
}
bytesWritten += CHUNK_SIZE;
}
file.seekg(fileSize - remainingBytes, file.beg);
uint32_t remainingBytes = fileSize - fileChunks * CHUNK_SIZE;
file.seekg((fileChunks - 1) * CHUNK_SIZE, file.beg);
file.read(reinterpret_cast<char*>(req.data), remainingBytes);
file.close();
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
req.region++;
bytesWritten = 0;
}
req.address = bytesWritten;
req.length = remainingBytes;
arc_pack_write_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
return RETURN_FAILED;
return result;
}
result = checkFlashActionReply(req.region, req.address, req.length);
result = checkActionReply();
if (result != RETURN_OK) {
return result;
}
@ -363,22 +380,22 @@ ReturnValue_t StrHelper::performFlashRead() {
uint32_t size = 0;
uint32_t retries = 0;
Timestamp timestamp;
std::string fullname = flashRead.path + "/" + timestamp.str() + flashRead.filename;
std::string fullname = makeFullFilename(flashRead.path, flashRead.filename);
std::ofstream file(fullname, std::ios_base::app | std::ios_base::out);
if (not std::filesystem::exists(fullname)) {
return FILE_CREATION_FAILED;
}
req.region = flashRead.region;
req.region = flashRead.startRegion;
req.address = 0;
while (bytesRead < flashRead.size) {
if (terminate) {
return RETURN_OK;
}
if ((flashRead.size - bytesRead) < MAX_FLASH_DATA) {
if ((flashRead.size - bytesRead) < CHUNK_SIZE) {
req.length = flashRead.size - bytesRead;
} else {
req.length = MAX_FLASH_DATA;
req.length = CHUNK_SIZE;
}
req.address = flashRead.address + bytesRead;
arc_pack_read_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
@ -400,117 +417,24 @@ ReturnValue_t StrHelper::performFlashRead() {
file.close();
return result;
}
result = checkFlashActionReply(req.region, req.address, req.length);
if (result != RETURN_OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
continue;
}
file.close();
return result;
}
file.write(reinterpret_cast<const char*>(datalinkLayer.getReply() + FLASH_READ_DATA_OFFSET),
req.length);
bytesRead += req.length;
req.address += req.length;
if (req.address >= FLASH_REGION_SIZE) {
req.address = 0;
req.region++;
}
retries = 0;
#if OBSW_DEBUG_STARTRACKER == 1
printProgress(bytesRead, flashRead.size);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
}
file.close();
return RETURN_OK;
}
ReturnValue_t StrHelper::performFpgaDownload() {
ReturnValue_t result;
struct DownloadFPGAImageActionRequest req;
uint32_t size = 0;
uint32_t retries = 0;
Timestamp timestamp;
std::string image = fpgaDownload.path + "/" + timestamp.str() + fpgaDownload.fileName;
std::ofstream file(image, std::ios_base::app | std::ios_base::out);
if (not std::filesystem::exists(image)) {
return FILE_CREATION_FAILED;
}
req.pos = fpgaDownload.startPosition;
while (req.pos < fpgaDownload.length) {
if (terminate) {
return RETURN_OK;
}
if (fpgaDownload.length - req.pos >= FpgaDownload::MAX_DATA) {
req.length = FpgaDownload::MAX_DATA;
} else {
req.length = fpgaDownload.length - req.pos;
}
arc_pack_downloadfpgaimage_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.pos);
if (result != RETURN_OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
continue;
}
file.close();
return result;
}
result = checkFpgaActionReply(req.pos, req.length);
if (result != RETURN_OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
continue;
}
file.close();
return result;
}
file.write(reinterpret_cast<const char*>(datalinkLayer.getReply() + FpgaDownload::DATA_OFFSET),
req.length);
req.pos += req.length;
retries = 0;
}
file.close();
return RETURN_OK;
}
ReturnValue_t StrHelper::performFpgaUpload() {
ReturnValue_t result = RETURN_OK;
uint32_t commandSize = 0;
uint32_t bytesUploaded = 0;
uint32_t fileSize = 0;
struct UploadFPGAImageActionRequest req;
if (not std::filesystem::exists(fpgaUpload.uploadFile)) {
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
internalState = InternalState::IDLE;
return RETURN_FAILED;
}
std::ifstream file(flashWrite.fullname, std::ifstream::binary);
file.seekg(0, file.end);
fileSize = file.tellg();
req.pos = 0;
while (bytesUploaded <= fileSize) {
if (terminate) {
return RETURN_OK;
}
if (fileSize - bytesUploaded > FpgaUpload::MAX_DATA) {
req.length = FpgaUpload::MAX_DATA;
} else {
req.length = fileSize - bytesUploaded;
}
file.seekg(bytesUploaded, file.beg);
file.read(reinterpret_cast<char*>(req.data), req.length);
arc_pack_uploadfpgaimage_action_req(&req, commandBuffer, &commandSize);
result = sendAndRead(commandSize, req.pos);
if (result != RETURN_OK) {
return RETURN_FAILED;
}
result = checkFpgaActionReply(req.pos, req.length);
if (result != RETURN_OK) {
return result;
}
bytesUploaded += req.length;
}
return RETURN_OK;
}
ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter) {
ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t decResult = RETURN_OK;
size_t receivedDataLen = 0;
@ -527,7 +451,11 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter) {
}
decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS;
while (decResult == ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
result = uartComIF->requestReceiveMessage(comCookie, StarTracker::MAX_FRAME_SIZE * 2 + 2);
Countdown delay(delayMs);
delay.resetTimer();
while (delay.isBusy()) {
}
result = uartComIF->requestReceiveMessage(comCookie, startracker::MAX_FRAME_SIZE * 2 + 2);
if (result != RETURN_OK) {
sif::warning << "StrHelper::sendAndRead: Failed to request reply" << std::endl;
triggerEvent(STR_HELPER_REQUESTING_MSG_FAILED, result, parameter);
@ -588,72 +516,7 @@ ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) {
return RETURN_OK;
}
ReturnValue_t StrHelper::checkFlashActionReply(uint8_t region_, uint32_t address_,
uint16_t length_) {
ReturnValue_t result = RETURN_OK;
result = checkActionReply();
if (result != RETURN_OK) {
return result;
}
const uint8_t* data = datalinkLayer.getReply();
uint8_t region = *(data + REGION_OFFSET);
uint32_t address;
const uint8_t* addressData = data + ADDRESS_OFFSET;
size_t size = sizeof(address);
result =
SerializeAdapter::deSerialize(&address, &addressData, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
sif::warning << "StrHelper::checkFlashActionReply: Deserialization of address failed"
<< std::endl;
return result;
}
uint16_t length = 0;
size = sizeof(length);
const uint8_t* lengthData = data + LENGTH_OFFSET;
result =
SerializeAdapter::deSerialize(&length, lengthData, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
sif::warning << "StrHelper::checkFlashActionReply: Deserialization of length failed"
<< std::endl;
}
if (region != region_) {
return REGION_MISMATCH;
}
if (address != address_) {
return ADDRESS_MISMATCH;
}
if (length != length_) {
return LENGTH_MISMATCH;
}
return RETURN_OK;
}
ReturnValue_t StrHelper::checkFpgaActionReply(uint32_t expectedPosition, uint32_t expectedLength) {
ReturnValue_t result = RETURN_OK;
result = checkActionReply();
if (result != RETURN_OK) {
return result;
}
const uint8_t* data = datalinkLayer.getReply() + ACTION_DATA_OFFSET;
uint32_t position;
size_t size = sizeof(position);
result = SerializeAdapter::deSerialize(&position, &data, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
sif::warning << "StrHelper::checkFpgaActionReply: Deserialization of position failed"
<< std::endl;
return result;
}
uint32_t length;
size = sizeof(length);
result = SerializeAdapter::deSerialize(&length, &data, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
sif::warning << "StrHelper::checkFpgaActionReply: Deserialization of length failed"
<< std::endl;
return result;
}
return result;
}
#ifdef XIPHOS_Q7S
ReturnValue_t StrHelper::checkPath(std::string name) {
if (name.substr(0, sizeof(SdCardManager::SD_0_MOUNT_POINT)) ==
std::string(SdCardManager::SD_0_MOUNT_POINT)) {
@ -670,3 +533,55 @@ ReturnValue_t StrHelper::checkPath(std::string name) {
}
return RETURN_OK;
}
#endif
void StrHelper::printProgress(uint32_t itemsTransferred, uint32_t fullNumItems) {
float progressInPercent =
static_cast<float>(itemsTransferred) / static_cast<float>(fullNumItems) * 100;
if (static_cast<uint32_t>(progressInPercent) == nextProgressPrint) {
sif::info << "Str Helper Progress: " << progressInPercent << " %" << std::endl;
nextProgressPrint += FIVE_PERCENT;
}
if (nextProgressPrint > 100) {
nextProgressPrint = 0;
}
}
ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
ReturnValue_t result = RETURN_OK;
struct UnlockActionRequest unlockReq;
struct EraseActionRequest eraseReq;
uint32_t size = 0;
for (uint8_t idx = from; idx <= to; idx++) {
unlockReq.region = idx;
unlockReq.code = startracker::region_secrets::secret[idx];
arc_pack_unlock_action_req(&unlockReq, commandBuffer, &size);
sendAndRead(size, unlockReq.region);
result = checkActionReply();
if (result != RETURN_OK) {
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to unlock region with id "
<< static_cast<unsigned int>(unlockReq.region) << std::endl;
return result;
}
eraseReq.region = idx;
arc_pack_erase_action_req(&eraseReq, commandBuffer, &size);
result = sendAndRead(size, eraseReq.region, FLASH_ERASE_DELAY);
if (result != RETURN_OK) {
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to erase region with id "
<< static_cast<unsigned int>(eraseReq.region) << std::endl;
return result;
}
}
return result;
}
std::string StrHelper::makeFullFilename(std::string path, std::string filename) {
std::string image;
Timestamp timestamp;
if (timestamping) {
image = path + "/" + timestamp.str() + filename;
} else {
image = path + "/" + filename;
}
return image;
}

View File

@ -4,7 +4,12 @@
#include <string>
#include "ArcsecDatalinkLayer.h"
#include "OBSWConfig.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/SdCardManager.h"
#endif
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
@ -19,6 +24,8 @@ extern "C" {
/**
* @brief Helper class for the star tracker handler to accelerate large data transfers.
*
* @author J. Meier
*/
class StrHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
public:
@ -36,49 +43,43 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
static const Event FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Finished flash read procedure successfully
static const Event FLASH_READ_SUCCESSFUL = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] Flash write procedure failed
static const Event FLASH_WRITE_FAILED = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Flash read procedure failed
static const Event FLASH_READ_FAILED = MAKE_EVENT(7, severity::LOW);
//! [EXPORT] : [COMMENT] Download of FPGA image successful
static const Event FPGA_DOWNLOAD_SUCCESSFUL = MAKE_EVENT(8, severity::LOW);
//! [EXPORT] : [COMMENT] Download of FPGA image failed
static const Event FPGA_DOWNLOAD_FAILED = MAKE_EVENT(9, severity::LOW);
//! [EXPORT] : [COMMENT] Upload of FPGA image successful
static const Event FPGA_UPLOAD_SUCCESSFUL = MAKE_EVENT(10, severity::LOW);
//! [EXPORT] : [COMMENT] Upload of FPGA image failed
static const Event FPGA_UPLOAD_FAILED = MAKE_EVENT(11, severity::LOW);
static const Event FLASH_READ_FAILED = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Firmware update was successful
static const Event FIRMWARE_UPDATE_SUCCESSFUL = MAKE_EVENT(7, severity::LOW);
//! [EXPORT] : [COMMENT] Firmware update failed
static const Event FIRMWARE_UPDATE_FAILED = MAKE_EVENT(8, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to read communication interface reply data
//! P1: Return code of failed communication interface read call
//! P1: Upload/download position for which the read call failed
static const Event STR_HELPER_READING_REPLY_FAILED = MAKE_EVENT(12, severity::LOW);
static const Event STR_HELPER_READING_REPLY_FAILED = MAKE_EVENT(9, severity::LOW);
//! [EXPORT] : [COMMENT] Unexpected stop of decoding sequence
//! P1: Return code of failed communication interface read call
//! P1: Upload/download position for which the read call failed
static const Event STR_HELPER_COM_ERROR = MAKE_EVENT(13, severity::LOW);
static const Event STR_HELPER_COM_ERROR = MAKE_EVENT(10, severity::LOW);
//! [EXPORT] : [COMMENT] Star tracker did not send replies (maybe device is powered off)
//! P1: Position of upload or download packet for which no reply was sent
static const Event STR_HELPER_NO_REPLY = MAKE_EVENT(14, severity::LOW);
static const Event STR_HELPER_NO_REPLY = MAKE_EVENT(11, severity::LOW);
//! [EXPORT] : [COMMENT] Error during decoding of received reply occurred
// P1: Return value of decoding function
// P2: Position of upload/download packet, or address of flash write/read request
static const Event STR_HELPER_DEC_ERROR = MAKE_EVENT(15, severity::LOW);
static const Event STR_HELPER_DEC_ERROR = MAKE_EVENT(12, severity::LOW);
//! [EXPORT] : [COMMENT] Position mismatch
//! P1: The expected position and thus the position for which the image upload/download failed
static const Event POSITION_MISMATCH = MAKE_EVENT(16, severity::LOW);
static const Event POSITION_MISMATCH = MAKE_EVENT(13, severity::LOW);
//! [EXPORT] : [COMMENT] Specified file does not exist
//! P1: Internal state of str helper
static const Event STR_HELPER_FILE_NOT_EXISTS = MAKE_EVENT(17, severity::LOW);
static const Event STR_HELPER_FILE_NOT_EXISTS = MAKE_EVENT(14, severity::LOW);
//! [EXPORT] : [COMMENT] Sending packet to star tracker failed
//! P1: Return code of communication interface sendMessage function
//! P2: Position of upload/download packet, or address of flash write/read request for which
//! sending failed
static const Event STR_HELPER_SENDING_PACKET_FAILED = MAKE_EVENT(18, severity::LOW);
static const Event STR_HELPER_SENDING_PACKET_FAILED = MAKE_EVENT(15, severity::LOW);
//! [EXPORT] : [COMMENT] Communication interface requesting reply failed
//! P1: Return code of failed request
//! P1: Upload/download position, or address of flash write/read request for which transmission
//! failed
static const Event STR_HELPER_REQUESTING_MSG_FAILED = MAKE_EVENT(19, severity::LOW);
static const Event STR_HELPER_REQUESTING_MSG_FAILED = MAKE_EVENT(16, severity::LOW);
StrHelper(object_id_t objectId);
virtual ~StrHelper();
@ -105,40 +106,21 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
ReturnValue_t startImageDownload(std::string path);
/**
* @brief Starts the flash write procedure
* @brief Will start the firmware update
*
* @param fullname Full name including absolute path of file to write to flash
* @param region Region ID of flash region to write to
* @param address Start address of flash write procedure
* @param fullname Full name including absolute path of file containing firmware
* update.
*/
ReturnValue_t startFlashWrite(std::string fullname, uint8_t region, uint32_t address);
ReturnValue_t startFirmwareUpdate(std::string fullname);
/**
* @brief Starts the flash read procedure
*
* @param path Path where file with read flash data will be created
* @param region Region ID of flash region to read from
* @param address Start address of flash section to read
* @param startRegion Region form where to start reading
* @param length Number of bytes to read from flash
*/
ReturnValue_t startFlashRead(std::string path, uint8_t region, uint32_t address, uint32_t length);
/**
* @brief Starts the download of the FPGA image
*
* @param path The path where the file with the downloaded data will be created
* @param startPosition Offset in fpga image to read from
* @param length Number of bytes to dwonload from the FPGA image
*
*/
ReturnValue_t startFpgaDownload(std::string path, uint32_t startPosition, uint32_t length);
/**
* @brief Starts upload of new image to FPGA
*
* @param uploadFile Full name of file containing FPGA image data
*/
ReturnValue_t startFpgaUpload(std::string uploadFile);
ReturnValue_t startFlashRead(std::string path, uint8_t startRegion, uint32_t length);
/**
* @brief Can be used to interrupt a running data transfer.
@ -156,9 +138,14 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
void setFlashReadFilename(std::string filename);
/**
* @brief Set download FPGA image name
* @brief Disables timestamp generation when new file is created
*/
void setDownloadFpgaImage(std::string filename);
void disableTimestamping();
/**
* @brief Enables timestamp generation when new file is created
*/
void enableTimestamping();
private:
static const uint8_t INTERFACE_ID = CLASS_ID::STR_HELPER;
@ -184,35 +171,14 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
// Size of one image part which can be sent per action request
static const size_t SIZE_IMAGE_PART = 1024;
static constexpr uint32_t FIVE_PERCENT = 5;
static const uint32_t FLASH_REGION_SIZE = 0x20000;
class ImageDownload {
public:
static const uint32_t LAST_POSITION = 4095;
};
class FpgaDownload {
public:
static const uint16_t MAX_DATA = 1024;
static const uint8_t DATA_OFFSET = 10;
// Start position of fpga image part to download
uint32_t startPosition = 0;
// Length of image part to download
uint32_t length = 0;
// Path where downloaded FPGA image will be stored
std::string path;
// Name of file containing downloaded FPGA image
std::string fileName = "fpgaimage.bin";
};
FpgaDownload fpgaDownload;
class FpgaUpload {
public:
static const uint32_t MAX_DATA = 1024;
// Full name of file to upload
std::string uploadFile;
};
FpgaUpload fpgaUpload;
static const uint32_t MAX_POLLS = 10000;
static const uint8_t ACTION_DATA_OFFSET = 2;
@ -222,19 +188,11 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
static const uint8_t REGION_OFFSET = 2;
static const uint8_t ADDRESS_OFFSET = 3;
static const uint8_t LENGTH_OFFSET = 7;
static const size_t IMAGE_DATA_SIZE = 1024;
static const size_t MAX_FLASH_DATA = 1024;
static const size_t CHUNK_SIZE = 1024;
static const size_t CONFIG_MAX_DOWNLOAD_RETRIES = 3;
static const uint32_t FLASH_ERASE_DELAY = 500;
enum class InternalState {
IDLE,
UPLOAD_IMAGE,
DOWNLOAD_IMAGE,
FLASH_WRITE,
FLASH_READ,
DOWNLOAD_FPGA_IMAGE,
UPLOAD_FPGA_IMAGE
};
enum class InternalState { IDLE, UPLOAD_IMAGE, DOWNLOAD_IMAGE, FLASH_READ, FIRMWARE_UPDATE };
InternalState internalState = InternalState::IDLE;
@ -262,8 +220,10 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
public:
// File which contains data to write when executing the flash write command
std::string fullname;
// Will be set with the flash write command
uint8_t region = 0;
// The first region to write to
uint8_t firstRegion = 0;
// Maximum region the flash write command is allowed to write to
uint8_t lastRegion = 0;
// Will be set with the flash write command and specifies the start address where to write the
// flash data to
uint32_t address = 0;
@ -277,21 +237,28 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
// Default name of file containing the data read from flash, can be changed via command
std::string filename = "flashread.bin";
// Will be set with the flash read command
uint8_t region = 0;
// Will be set with the flash read command and specifies the start address of the flash section
// to read
uint32_t address = 0;
uint8_t startRegion = 0;
// Number of bytes to read from flash
uint32_t size = 0;
};
FlashRead flashRead;
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif
uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE];
uint8_t commandBuffer[startracker::MAX_FRAME_SIZE];
bool terminate = false;
uint32_t nextProgressPrint = 0;
#ifdef EGSE
bool timestamping = false;
#else
bool timestamping = true;
#endif
/**
* UART communication object responsible for low level access of star tracker
* Must be set by star tracker handler
@ -308,6 +275,13 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
*/
ReturnValue_t performImageUpload();
/**
* @brief Performs firmware update
*
* @return RETURN_OK if successful, otherwise error return value
*/
ReturnValue_t performFirmwareUpdate();
/**
* @brief Performs download of last taken image from the star tracker.
*
@ -321,6 +295,8 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
/**
* @brief Handles flash write procedure
*
* @param ID of first region to write to
*
* @return RETURN_OK if successful, otherwise RETURN_FAILED
*/
ReturnValue_t performFlashWrite();
@ -331,28 +307,17 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
*/
ReturnValue_t performFlashRead();
/**
* @brief Performs the download of the FPGA image which requires to be slip over multiple
* action requests.
*/
ReturnValue_t performFpgaDownload();
/**
* @brief Performs upload of new FPGA image. Upload sequence split over multiple commands
* because one command can only transport 1024 bytes of image data.
*/
ReturnValue_t performFpgaUpload();
/**
* @brief Sends packet to the star tracker and reads reply by using the communication
* interface
*
* @param size Size of data beforehand written to the commandBuffer
* @param parameter Parameter 2 of trigger event function
* @param delayMs Delay in milliseconds between send and receive call
*
* @return RETURN_OK if successful, otherwise RETURN_FAILED
*/
ReturnValue_t sendAndRead(size_t size, uint32_t parameter);
ReturnValue_t sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs = 0);
/**
* @brief Checks the header (type id and status fields) of the action reply
@ -370,28 +335,41 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
*/
ReturnValue_t checkReplyPosition(uint32_t expectedPosition);
/**
* @brief Checks the region, address and length value of a flash write or read reply.
*
* @return RETURN_OK if values match expected values, otherwise appropriate error return
* value.
*/
ReturnValue_t checkFlashActionReply(uint8_t region_, uint32_t address_, uint16_t length_);
/**
* @brief Checks the reply to the fpga download and upload request
*
* @param expectedPosition The expected position value in the reply
* @param expectedLength The expected length field in the reply
*/
ReturnValue_t checkFpgaActionReply(uint32_t expectedPosition, uint32_t expectedLength);
#ifdef XIPHOS_Q7S
/**
* @brief Checks if a path points to an sd card and whether the SD card is monuted.
*
* @return SD_NOT_MOUNTED id SD card is not mounted, otherwise RETURN_OK
*/
ReturnValue_t checkPath(std::string name);
#endif
/**
* @brief Prints progress of transfer which can be useful for large data transfers
*
* @param itemsTransferred Number of items transferred
* @param fullNumItems Full number of items to transfer
*/
void printProgress(uint32_t itemsTransferred, uint32_t fullNumItems);
/**
* @brief Unlocks a range of flash regions
*
* @param from First region in range to unlock
* @param to Last region in range to unlock
*
*/
ReturnValue_t unlockAndEraseRegions(uint32_t from, uint32_t to);
/**
* @brief Creates full filename either with timestamp or without
*
* @param path Path where to create the file
* @param filename Name fo the file
*
* @return Full filename
*/
std::string makeFullFilename(std::string path, std::string filename);
};
#endif /* BSP_Q7S_DEVICES_STRHELPER_H_ */

View File

@ -9,6 +9,7 @@
#cmakedefine RASPBERRY_PI
#cmakedefine XIPHOS_Q7S
#cmakedefine BEAGLEBONEBLACK
#cmakedefine EGSE
#ifdef RASPBERRY_PI
#include "rpiConfig.h"
@ -55,10 +56,16 @@ debugging. */
#define OBSW_ADD_PL_PCDU 0
#define OBSW_ADD_SYRLINKS 0
#define OBSW_ENABLE_SYRLINKS_TRANSMIT_TIMEOUT 0
#define OBSW_SYRLINKS_SIMULATED 1
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
#define OBSW_ENABLE_PERIODIC_HK 0
#endif
#ifdef EGSE
#define OBSW_ADD_STAR_TRACKER 1
#endif
/*******************************************************************/
/** All of the following flags should be disabled for mission code */
/*******************************************************************/
@ -104,11 +111,16 @@ debugging. */
#define OBSW_DEBUG_SYRLINKS 0
#define OBSW_DEBUG_IMTQ 0
#define OBSW_DEBUG_RW 0
#define OBSW_DEBUG_STARTRACKER 0
#define OBSW_DEBUG_PLOC_MPSOC 0
#define OBSW_DEBUG_PLOC_SUPERVISOR 0
#define OBSW_DEBUG_PDEC_HANDLER 0
#ifdef EGSE
#define OBSW_DEBUG_STARTRACKER 1
#else
#define OBSW_DEBUG_STARTRACKER 0
#endif
#ifdef RASPBERRY_PI
#define OBSW_ENABLE_TIMERS 1

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 153 translations.
* @brief Auto-generated event translation file. Contains 152 translations.
* @details
* Generated on: 2022-02-26 13:53:13
* Generated on: 2022-03-01 15:17:49
*/
#include "translateEvents.h"
@ -107,12 +107,14 @@ const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE";
const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE";
const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE";
const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *BOOTING_FIRMWARE_FAILED_STRING = "BOOTING_FIRMWARE_FAILED";
const char *BOOTING_BOOTLOADER_FAILED_STRING = "BOOTING_BOOTLOADER_FAILED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE";
const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE";
const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT";
const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED";
const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD";
const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS";
const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED";
@ -133,12 +135,9 @@ const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
const char *IMAGE_DOWNLOAD_SUCCESSFUL_STRING = "IMAGE_DOWNLOAD_SUCCESSFUL";
const char *FLASH_WRITE_SUCCESSFUL_STRING = "FLASH_WRITE_SUCCESSFUL";
const char *FLASH_READ_SUCCESSFUL_STRING = "FLASH_READ_SUCCESSFUL";
const char *FLASH_WRITE_FAILED_STRING = "FLASH_WRITE_FAILED";
const char *FLASH_READ_FAILED_STRING = "FLASH_READ_FAILED";
const char *FPGA_DOWNLOAD_SUCCESSFUL_STRING = "FPGA_DOWNLOAD_SUCCESSFUL";
const char *FPGA_DOWNLOAD_FAILED_STRING = "FPGA_DOWNLOAD_FAILED";
const char *FPGA_UPLOAD_SUCCESSFUL_STRING = "FPGA_UPLOAD_SUCCESSFUL";
const char *FPGA_UPLOAD_FAILED_STRING = "FPGA_UPLOAD_FAILED";
const char *FIRMWARE_UPDATE_SUCCESSFUL_STRING = "FIRMWARE_UPDATE_SUCCESSFUL";
const char *FIRMWARE_UPDATE_FAILED_STRING = "FIRMWARE_UPDATE_FAILED";
const char *STR_HELPER_READING_REPLY_FAILED_STRING = "STR_HELPER_READING_REPLY_FAILED";
const char *STR_HELPER_COM_ERROR_STRING = "STR_HELPER_COM_ERROR";
const char *STR_HELPER_NO_REPLY_STRING = "STR_HELPER_NO_REPLY";
@ -160,7 +159,7 @@ const char *U_HPA_OUT_OF_BOUNDS_STRING = "U_HPA_OUT_OF_BOUNDS";
const char *I_HPA_OUT_OF_BOUNDS_STRING = "I_HPA_OUT_OF_BOUNDS";
const char *translateEvents(Event event) {
switch ((event & 0xFFFF)) {
switch((event & 0xFFFF)) {
case (2200):
return STORE_SEND_WRITE_FAILED_STRING;
case (2201):
@ -365,6 +364,10 @@ const char *translateEvents(Event event) {
return INVALID_ERROR_BYTE_STRING;
case (11301):
return ERROR_STATE_STRING;
case (11401):
return BOOTING_FIRMWARE_FAILED_STRING;
case (11402):
return BOOTING_BOOTLOADER_FAILED_STRING;
case (11501):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (11502):
@ -374,9 +377,9 @@ const char *translateEvents(Event event) {
case (11504):
return SUPV_CRC_FAILURE_EVENT_STRING;
case (11600):
return SANITIZATION_FAILED_STRING;
return ALLOC_FAILURE_STRING;
case (11601):
return MOUNTED_SD_CARD_STRING;
return REBOOT_SW_STRING;
case (11603):
return REBOOT_HW_STRING;
case (11700):
@ -418,32 +421,26 @@ const char *translateEvents(Event event) {
case (12005):
return FLASH_READ_SUCCESSFUL_STRING;
case (12006):
return FLASH_WRITE_FAILED_STRING;
case (12007):
return FLASH_READ_FAILED_STRING;
case (12007):
return FIRMWARE_UPDATE_SUCCESSFUL_STRING;
case (12008):
return FPGA_DOWNLOAD_SUCCESSFUL_STRING;
return FIRMWARE_UPDATE_FAILED_STRING;
case (12009):
return FPGA_DOWNLOAD_FAILED_STRING;
case (12010):
return FPGA_UPLOAD_SUCCESSFUL_STRING;
case (12011):
return FPGA_UPLOAD_FAILED_STRING;
case (12012):
return STR_HELPER_READING_REPLY_FAILED_STRING;
case (12013):
case (12010):
return STR_HELPER_COM_ERROR_STRING;
case (12014):
case (12011):
return STR_HELPER_NO_REPLY_STRING;
case (12015):
case (12012):
return STR_HELPER_DEC_ERROR_STRING;
case (12016):
case (12013):
return POSITION_MISMATCH_STRING;
case (12017):
case (12014):
return STR_HELPER_FILE_NOT_EXISTS_STRING;
case (12018):
case (12015):
return STR_HELPER_SENDING_PACKET_FAILED_STRING;
case (12019):
case (12016):
return STR_HELPER_REQUESTING_MSG_FAILED_STRING;
case (12101):
return NEG_V_OUT_OF_BOUNDS_STRING;

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 112 translations.
* Generated on: 2022-02-26 14:03:55
* Generated on: 2022-03-01 15:17:56
*/
#include "translateObjects.h"

View File

@ -457,6 +457,7 @@ ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) {
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
#endif
static_cast<void>(length);
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
sif::error << "I2C PST initialization failed" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
@ -479,9 +480,11 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
#endif
#ifdef XIPHOS_Q7S
thisSequence->addSlot(objects::PLOC_UPDATER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_MEMORY_DUMPER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
#endif
#if OBSW_ADD_PLOC_SUPERVISOR == 1
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
@ -510,7 +513,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.8, DeviceHandlerIF::GET_READ);
#endif
static_cast<void>(length);
if (uartPstEmpty) {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -8,4 +8,7 @@ find ./linux -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --sty
find ./bsp_q7s -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
find ./bsp_linux_board -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
find ./bsp_hosted -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
find ./bsp_egse -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
find ./test -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
find ./unittest -iname *.h -o -iname *.cpp -o -iname *.c -o -type d -name build -prune | \
xargs clang-format --style=file -i

6
scripts/egse-port.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
echo "-L 1534:localhost:1534 pi@192.168.18.31 portforwarding for tcf agent"
echo "-L 1537:localhost:7301 pi@192.168.18.31 for TMTC commanding using the TCP/IP IF"
ssh -L 1534:localhost:1534 \
-L 1537:localhost:7301 pi@192.168.18.31

View File

@ -2,6 +2,5 @@
#include "fsfw_tests/unit/CatchRunner.h"
int main(int argc, char* argv[]) {
// fsfwtest::customMain(argc, argv);
// fsfwtest::customMain(argc, argv);
}

View File

@ -1 +1,2 @@
/build
c_cpp_properties.json

View File

@ -0,0 +1,51 @@
{
"editor.tabSize": 2,
"files.associations": {
"iosfwd": "cpp",
"array": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"type_traits": "cpp",
"tuple": "cpp",
"typeinfo": "cpp",
"utility": "cpp",
"variant": "cpp",
"filesystem": "cpp",
"queue": "cpp"
}
}

View File

@ -1,10 +1,28 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.13.0)
project(reboot-logic VERSION 0.1.0)
include(CTest)
find_package(Catch2 3)
if(NOT Catch2_FOUND)
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.0.0-preview4
)
FetchContent_MakeAvailable(Catch2)
#fixes regression -preview4, to be confirmed in later releases
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
endif()
enable_testing()
add_executable(reboot-logic main.cpp)
add_executable(reboot-logic)
add_subdirectory(src)
target_link_libraries(reboot-logic PRIVATE Catch2::Catch2WithMain)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})

View File

@ -0,0 +1,16 @@
Reboot Logic Unittest
=======
These tests were written with Catch2 and VS code.
Install VS code with the C++ and CMake plugins and open this folder with VS code.
You should be able to run the tests directly.
It is also recommended to [install Catch2](https://github.com/catchorg/Catch2/blob/devel/docs/cmake-integration.md):
```sh
git clone https://github.com/catchorg/Catch2.git
cd Catch2
git checkout v3.0.0-preview4
cmake -Bbuild -H. -DBUILD_TESTING=OFF
sudo cmake --build build/ --target install
```

View File

@ -1,5 +0,0 @@
#include <iostream>
int main(int, char**) {
std::cout << "Hello, world!\n";
}

View File

@ -0,0 +1,14 @@
target_sources(reboot-logic PRIVATE
main.cpp
CoreController.cpp
SdCardManager.cpp
event.cpp
libxiphos.cpp
print.c
)
target_include_directories(reboot-logic PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
add_subdirectory(fsfw)

View File

@ -0,0 +1,529 @@
#include "CoreController.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include "HasActionsIF.h"
#include "SdCardManager.h"
#include "conf.h"
#include "event.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "libxiphos.h"
xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP;
xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY;
CoreController::CoreController() {
sdcMan = new SdCardManager();
setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
}
void CoreController::performRebootFileHandling(bool recreateFile) {
using namespace std;
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
if (not std::filesystem::exists(path) or recreateFile) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
#endif
rebootFile.enabled = true;
rebootFile.img00Cnt = 0;
rebootFile.img01Cnt = 0;
rebootFile.img10Cnt = 0;
rebootFile.img11Cnt = 0;
rebootFile.lastChip = xsc::Chip::CHIP_0;
rebootFile.lastCopy = xsc::Copy::COPY_0;
rebootFile.img00Lock = false;
rebootFile.img01Lock = false;
rebootFile.img10Lock = false;
rebootFile.img11Lock = false;
rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
rebootFile.bootFlag = false;
rewriteRebootFile(rebootFile);
} else {
if (not parseRebootFile(path, rebootFile)) {
performRebootFileHandling(true);
}
}
if (CURRENT_CHIP == xsc::CHIP_0) {
if (CURRENT_COPY == xsc::COPY_0) {
rebootFile.img00Cnt++;
} else {
rebootFile.img01Cnt++;
}
} else {
if (CURRENT_COPY == xsc::COPY_0) {
rebootFile.img10Cnt++;
} else {
rebootFile.img11Cnt++;
}
}
if (rebootFile.bootFlag) {
// Trigger event to inform ground that a reboot was triggered
uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy;
uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 | rebootFile.img10Cnt << 8 |
rebootFile.img11Cnt;
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
// Clear the boot flag
rebootFile.bootFlag = false;
}
if (rebootFile.mechanismNextChip != xsc::NO_CHIP and
rebootFile.mechanismNextCopy != xsc::NO_COPY) {
if (CURRENT_CHIP != rebootFile.mechanismNextChip or
CURRENT_COPY != rebootFile.mechanismNextCopy) {
std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " +
std::to_string(rebootFile.mechanismNextCopy);
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
<< infoString << " but currently on other image. Locking " << infoString
<< std::endl;
// Firmware or other component might be corrupt and we are on another image then the target
// image specified by the mechanism. We can't really trust the target image anymore.
// Lock it for now
if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
rebootFile.img00Lock = true;
} else {
rebootFile.img01Lock = true;
}
} else {
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
rebootFile.img10Lock = true;
} else {
rebootFile.img11Lock = true;
}
}
}
}
rebootFile.lastChip = CURRENT_CHIP;
rebootFile.lastCopy = CURRENT_COPY;
// Only reboot if the reboot functionality is enabled.
// The handler will still increment the boot counts
if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) {
// Reboot to other image
bool doReboot = false;
xsc::Chip tgtChip = xsc::NO_CHIP;
xsc::Copy tgtCopy = xsc::NO_COPY;
determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy);
if (doReboot) {
rebootFile.bootFlag = true;
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
#endif
rebootFile.mechanismNextChip = tgtChip;
rebootFile.mechanismNextCopy = tgtCopy;
rewriteRebootFile(rebootFile);
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
static_cast<xsc_libnor_copy_t>(tgtCopy));
}
} else {
rebootFile.mechanismNextChip = xsc::NO_CHIP;
rebootFile.mechanismNextCopy = xsc::NO_COPY;
}
rewriteRebootFile(rebootFile);
}
void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_0;
needsReboot = false;
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_0) and
(rf.img00Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
return;
}
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
return;
}
// Can't really do much here. Stay on image
sif::warning
<< "All reboot counts too high or all fallback images locked, already on fallback image"
<< std::endl;
needsReboot = false;
return;
}
if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and
(rf.img01Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
// Reboot on fallback image
return;
}
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
return;
}
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and
(rf.img10Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) {
tgtChip = xsc::CHIP_1;
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
return;
}
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and
(rf.img11Cnt >= rf.maxCount)) {
needsReboot = true;
if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) {
tgtChip = xsc::CHIP_1;
return;
}
if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) {
return;
}
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
tgtCopy = xsc::COPY_1;
return;
}
if (rf.img00Lock) {
needsReboot = false;
}
// Reboot to fallback image
}
}
bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
using namespace std;
std::string selfMatch;
if (CURRENT_CHIP == xsc::CHIP_0) {
if (CURRENT_COPY == xsc::COPY_0) {
selfMatch = "00";
} else {
selfMatch = "01";
}
} else {
if (CURRENT_COPY == xsc::COPY_0) {
selfMatch = "10";
} else {
selfMatch = "11";
}
}
ifstream file(path);
string word;
string line;
uint8_t lineIdx = 0;
while (std::getline(file, line)) {
istringstream iss(line);
switch (lineIdx) {
case 0: {
iss >> word;
if (word.find("on:") == string::npos) {
// invalid file
return false;
}
iss >> rf.enabled;
break;
}
case 1: {
iss >> word;
if (word.find("maxcnt:") == string::npos) {
return false;
}
iss >> rf.maxCount;
break;
}
case 2: {
iss >> word;
if (word.find("img00:") == string::npos) {
return false;
}
iss >> rf.img00Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = &rf.img00Cnt;
}
break;
}
case 3: {
iss >> word;
if (word.find("img01:") == string::npos) {
return false;
}
iss >> rf.img01Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = &rf.img01Cnt;
}
break;
}
case 4: {
iss >> word;
if (word.find("img10:") == string::npos) {
return false;
}
iss >> rf.img10Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = &rf.img10Cnt;
}
break;
}
case 5: {
iss >> word;
if (word.find("img11:") == string::npos) {
return false;
}
iss >> rf.img11Cnt;
if (word.find(selfMatch) != string::npos) {
rf.relevantBootCnt = &rf.img11Cnt;
}
break;
}
case 6: {
iss >> word;
if (word.find("img00lock:") == string::npos) {
return false;
}
iss >> rf.img00Lock;
break;
}
case 7: {
iss >> word;
if (word.find("img01lock:") == string::npos) {
return false;
}
iss >> rf.img01Lock;
break;
}
case 8: {
iss >> word;
if (word.find("img10lock:") == string::npos) {
return false;
}
iss >> rf.img10Lock;
break;
}
case 9: {
iss >> word;
if (word.find("img11lock:") == string::npos) {
return false;
}
iss >> rf.img11Lock;
break;
}
case 10: {
iss >> word;
if (word.find("bootflag:") == string::npos) {
return false;
}
iss >> rf.bootFlag;
break;
}
case 11: {
iss >> word;
int copyRaw = 0;
int chipRaw = 0;
if (word.find("last:") == string::npos) {
return false;
}
iss >> chipRaw;
if (iss.fail()) {
return false;
}
iss >> copyRaw;
if (iss.fail()) {
return false;
}
if (chipRaw > 1 or copyRaw > 1) {
return false;
}
rf.lastChip = static_cast<xsc::Chip>(chipRaw);
rf.lastCopy = static_cast<xsc::Copy>(copyRaw);
break;
}
case 12: {
iss >> word;
int copyRaw = 0;
int chipRaw = 0;
if (word.find("next:") == string::npos) {
return false;
}
iss >> chipRaw;
if (iss.fail()) {
return false;
}
iss >> copyRaw;
if (iss.fail()) {
return false;
}
if (chipRaw > 2 or copyRaw > 2) {
return false;
}
rf.mechanismNextChip = static_cast<xsc::Chip>(chipRaw);
rf.mechanismNextCopy = static_cast<xsc::Copy>(copyRaw);
break;
}
}
if (iss.fail()) {
return false;
}
lineIdx++;
}
if (lineIdx < 12) {
return false;
}
return true;
}
void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
rebootFile.img00Cnt = 0;
rebootFile.img01Cnt = 0;
rebootFile.img10Cnt = 0;
rebootFile.img11Cnt = 0;
} else {
if (tgtChip == xsc::CHIP_0) {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img00Cnt = 0;
} else {
rebootFile.img01Cnt = 0;
}
} else {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img10Cnt = 0;
} else {
rebootFile.img11Cnt = 0;
}
}
}
rewriteRebootFile(rebootFile);
}
void CoreController::rewriteRebootFile(RebootFile file) {
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
std::ofstream rebootFile(path);
if (rebootFile.is_open()) {
// Initiate reboot file first. Reboot handling will be on on initialization
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
<< "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
<< "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock
<< "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock
<< "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast<int>(file.lastChip)
<< " " << static_cast<int>(file.lastCopy)
<< "\nnext: " << static_cast<int>(file.mechanismNextChip) << " "
<< static_cast<int>(file.mechanismNextCopy) << "\n";
}
}
ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case (SWITCH_REBOOT_FILE_HANDLING): {
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
if (data[0] == 0) {
rebootFile.enabled = false;
rewriteRebootFile(rebootFile);
} else if (data[0] == 1) {
rebootFile.enabled = true;
rewriteRebootFile(rebootFile);
} else {
return HasActionsIF::INVALID_PARAMETERS;
}
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTERS): {
if (size == 0) {
resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
} else if (size == 2) {
if (data[0] > 1 or data[1] > 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
resetRebootCount(static_cast<xsc::Chip>(data[0]), static_cast<xsc::Copy>(data[1]));
}
return HasActionsIF::EXECUTION_FINISHED;
}
case (SWITCH_IMG_LOCK): {
if (size != 3) {
return HasActionsIF::INVALID_PARAMETERS;
}
if (data[1] > 1 or data[2] > 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
setRebootMechanismLock(data[0], static_cast<xsc::Chip>(data[1]),
static_cast<xsc::Copy>(data[2]));
return HasActionsIF::EXECUTION_FINISHED;
}
case (SET_MAX_REBOOT_CNT): {
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
rebootFile.maxCount = data[0];
rewriteRebootFile(rebootFile);
return HasActionsIF::EXECUTION_FINISHED;
}
default: {
return HasActionsIF::INVALID_ACTION_ID;
}
}
}
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
if (tgtChip == xsc::CHIP_0) {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img00Lock = lock;
} else {
rebootFile.img01Lock = lock;
}
} else {
if (tgtCopy == xsc::COPY_0) {
rebootFile.img10Lock = lock;
} else {
rebootFile.img11Lock = lock;
}
}
rewriteRebootFile(rebootFile);
}
void CoreController::setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy) {
CURRENT_CHIP = chip;
CURRENT_COPY = copy;
}

View File

@ -0,0 +1,79 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include "SdCardManager.h"
#include "definitions.h"
namespace xsc {
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
} // namespace xsc
struct RebootFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
bool enabled = true;
size_t maxCount = DEFAULT_MAX_BOOT_CNT;
uint32_t img00Cnt = 0;
uint32_t img01Cnt = 0;
uint32_t img10Cnt = 0;
uint32_t img11Cnt = 0;
bool img00Lock = false;
bool img01Lock = false;
bool img10Lock = false;
bool img11Lock = false;
uint32_t* relevantBootCnt = &img00Cnt;
bool bootFlag = false;
xsc::Chip lastChip = xsc::Chip::CHIP_0;
xsc::Copy lastCopy = xsc::Copy::COPY_0;
xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP;
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};
class SdCardManager;
class CoreController {
public:
static constexpr char REBOOT_FILE[] = "/conf/reboot.txt";
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
//! P2: Each byte is the respective reboot count for the slots
static constexpr Event REBOOT_MECHANISM_TRIGGERED = 1;
static xsc::Chip CURRENT_CHIP;
static xsc::Copy CURRENT_COPY;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
CoreController();
static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy);
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
void performRebootFileHandling(bool recreateFile);
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
bool parseRebootFile(std::string path, RebootFile& file);
void rewriteRebootFile(RebootFile file);
private:
struct SdInfo {
sd::SdCard pref = sd::SdCard::NONE;
sd::SdState prefState = sd::SdState::OFF;
sd::SdCard other = sd::SdCard::NONE;
sd::SdState otherState = sd::SdState::OFF;
} sdInfo;
SdCardManager* sdcMan = nullptr;
RebootFile rebootFile = {};
bool doPerformRebootFileHandling = true;
};

View File

@ -0,0 +1,9 @@
#include "definitions.h"
class HasActionsIF {
public:
static const ReturnValue_t IS_BUSY = 1;
static const ReturnValue_t INVALID_PARAMETERS = 2;
static const ReturnValue_t EXECUTION_FINISHED = 3;
static const ReturnValue_t INVALID_ACTION_ID = 4;
};

View File

@ -0,0 +1,5 @@
#include "SdCardManager.h"
std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { return "/tmp"; }
bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { return true; }

View File

@ -0,0 +1,23 @@
#pragma once
#include <cstdint>
#include <string>
namespace sd {
enum SdState : uint8_t {
OFF = 0,
ON = 1,
// A mounted SD card is on as well
MOUNTED = 2
};
enum SdCard : uint8_t { SLOT_0 = 0, SLOT_1 = 1, BOTH, NONE };
} // namespace sd
class SdCardManager {
public:
std::string getCurrentMountPrefix(sd::SdCard prefSdCard);
bool isSdCardMounted(sd::SdCard sdCard);
};

View File

@ -0,0 +1 @@
#define OBSW_VERBOSE_LEVEL 1

View File

@ -0,0 +1,6 @@
#include <cstdint>
using Event = uint32_t;
using ActionId_t = uint32_t;
using MessageQueueId_t = uint32_t;
using ReturnValue_t = uint16_t;

View File

@ -0,0 +1,21 @@
#include "event.h"
#include <queue>
std::queue<EventInfo> EVENT_QUEUE = {};
void triggerEvent(Event event, uint32_t p1, uint32_t p2) {
EventInfo info = {};
info.event = event;
info.p1 = p1;
info.p2 = p2;
EVENT_QUEUE.push(info);
}
void eventWasCalled(EventInfo& eventInfo, uint32_t& numEvents) {
numEvents = EVENT_QUEUE.size();
if (not EVENT_QUEUE.empty()) {
eventInfo = std::move(EVENT_QUEUE.back());
EVENT_QUEUE.pop();
}
}

View File

@ -0,0 +1,41 @@
#pragma once
#include <cstdint>
#include <iostream>
#include "definitions.h"
struct EventInfo {
// That was just for testing, follow rule of 0
/*
EventInfo () {}
EventInfo (const EventInfo& other): event(other.event), p1(other.p1), p2(other.p2) {
std::cout << "Event info copy ctor called" << std::endl;
}
EventInfo &operator= (const EventInfo& other) {
std::cout << "Event info assignment ctor called" << std::endl;
this->event = other.event;
this->p1 = other.p1;
this->p2 = other.p2;
return *this;
}
EventInfo &operator= (EventInfo&& other) {
std::cout << "Event info move ctor called" << std::endl;
this->event = other.event;
this->p1 = other.p1;
this->p2 = other.p2;
return *this;
}
*/
uint32_t event = 0;
uint32_t p1 = 0;
uint32_t p2 = 0;
};
void triggerEvent(Event event, uint32_t p1, uint32_t p2);
void eventWasCalled(EventInfo& eventInfo, uint32_t& numEvents);

View File

@ -0,0 +1 @@
add_subdirectory(serviceinterface)

View File

@ -0,0 +1,9 @@
#pragma once
#include <cstddef>
#define FSFW_CPP_OSTREAM_ENABLED 1
namespace fsfwconfig {
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 256;
}

View File

@ -0,0 +1,4 @@
target_sources(reboot-logic PRIVATE
ServiceInterfaceStream.cpp
ServiceInterfaceBuffer.cpp
)

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_
#define FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_
#include "fsfw/FSFW.h"
#include "serviceInterfaceDefintions.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include "ServiceInterfaceStream.h"
#else
#include "ServiceInterfacePrinter.h"
#endif
#endif /* FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_ */

View File

@ -0,0 +1,252 @@
#include "ServiceInterfaceBuffer.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <inttypes.h>
#include <cstring>
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#if defined(WIN32) && FSFW_COLORED_OUTPUT == 1
#include "Windows.h"
#endif
// to be implemented by bsp
extern "C" void printChar(const char*, bool errStream);
#ifndef UT699
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble,
bool buffered, bool errStream, uint16_t port)
: isActive(true),
logMessage(setMessage),
addCrToPreamble(addCrToPreamble),
buffered(buffered),
errStream(errStream) {
if (buffered) {
// Set pointers if the stream is buffered.
setp(buf, buf + BUF_SIZE);
}
#if FSFW_COLORED_OUTPUT == 1
if (setMessage.find("DEBUG") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_CYAN;
} else if (setMessage.find("INFO") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_GREEN;
} else if (setMessage.find("WARNING") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_MAGENTA;
} else if (setMessage.find("ERROR") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_RED;
} else {
colorPrefix = sif::ANSI_COLOR_RESET;
}
#ifdef WIN32
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
#endif
#endif
preamble.reserve(MAX_PREAMBLE_SIZE);
preamble.resize(MAX_PREAMBLE_SIZE);
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
length = sizeof(array);
}
memcpy(array, begin, length);
for (; begin != end; begin++) {
if (errStream) {
printChar(begin, true);
} else {
printChar(begin, false);
}
}
}
#endif
int ServiceInterfaceBuffer::overflow(int c) {
if (not buffered and this->isActive) {
if (c != Traits::eof()) {
if (errStream) {
printChar(reinterpret_cast<const char*>(&c), true);
} else {
printChar(reinterpret_cast<const char*>(&c), false);
}
}
return 0;
}
// Handle output
putChars(pbase(), pptr());
if (c != Traits::eof()) {
char c2 = c;
// Handle the one character that didn't fit to buffer
putChars(&c2, &c2 + 1);
}
// This tells that buffer is empty again
setp(buf, buf + BUF_SIZE - 1);
// I'm not sure about this return value!
return 0;
}
int ServiceInterfaceBuffer::sync(void) {
if (not this->isActive and not buffered) {
if (not buffered) {
setp(buf, buf + BUF_SIZE - 1);
}
return 0;
}
if (not buffered) {
return 0;
}
size_t preambleSize = 0;
std::string* preamble = getPreamble(&preambleSize);
// Write logMessage and time
this->putChars(preamble->data(), preamble->data() + preambleSize);
// Handle output
this->putChars(pbase(), pptr());
// This tells that buffer is empty again
setp(buf, buf + BUF_SIZE - 1);
return 0;
}
bool ServiceInterfaceBuffer::isBuffered() const { return buffered; }
std::string* ServiceInterfaceBuffer::getPreamble(size_t* preambleSize) {
size_t currentSize = 0;
char* parsePosition = &preamble[0];
if (addCrToPreamble) {
preamble[0] = '\r';
currentSize += 1;
parsePosition += 1;
}
#if FSFW_COLORED_OUTPUT == 1
currentSize += sprintf(parsePosition, "%s", colorPrefix.c_str());
parsePosition += colorPrefix.size();
#endif
int32_t charCount =
sprintf(parsePosition, "%s%s | ", this->logMessage.c_str(), sif::ANSI_COLOR_RESET);
if (charCount < 0) {
printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n");
return &preamble;
}
if (charCount > MAX_PREAMBLE_SIZE) {
printf(
"ServiceInterfaceBuffer: Char count too large for maximum "
"preamble size");
return &preamble;
}
currentSize += charCount;
if (preambleSize != nullptr) {
*preambleSize = currentSize;
}
return &preamble;
}
bool ServiceInterfaceBuffer::crAdditionEnabled() const { return addCrToPreamble; }
#if FSFW_COLORED_OUTPUT == 1
void ServiceInterfaceBuffer::setAsciiColorPrefix(std::string colorPrefix) {
this->colorPrefix = colorPrefix;
}
#endif
#ifdef UT699
#include "../osal/rtems/Interrupt.h"
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
this->log_message = set_message;
this->isActive = true;
setp(buf, buf + BUF_SIZE);
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
length = sizeof(array);
}
memcpy(array, begin, length);
if (!Interrupt::isInterruptInProgress()) {
std::cout << array;
} else {
// Uncomment the following line if you need ISR debug output.
// printk(array);
}
}
#endif // UT699
#ifdef ML505
#include <bsp_flp/network/networkconfig.h>
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port)
: isActive(true),
log_message(set_message),
udpSocket(0),
remoteAddressLength(sizeof(remoteAddress)) {
setp(buf, buf + BUF_SIZE);
memset((uint8_t*)&remoteAddress, 0, sizeof(remoteAddress));
remoteAddress.sin_family = AF_INET;
remoteAddress.sin_port = htons(port);
remoteAddress.sin_addr.s_addr = htonl(inet_addr("192.168.250.100"));
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
length = sizeof(array);
}
memcpy(array, begin, length);
if (udpSocket <= 0) {
initSocket();
}
if (udpSocket > 0) {
sendto(udpSocket, array, length, 0, (sockaddr*)&remoteAddress, sizeof(remoteAddress));
}
}
void ServiceInterfaceBuffer::initSocket() {
sockaddr_in address;
memset((uint8_t*)&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(0);
address.sin_addr.s_addr = htonl(INADDR_ANY);
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
if (socket < 0) {
printf("Error opening socket!\n");
return;
}
timeval timeout = {0, 20};
if (setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
printf("Error setting SO_RCVTIMEO socket options!\n");
return;
}
if (setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
printf("Error setting SO_SNDTIMEO socket options!\n");
return;
}
if (bind(udpSocket, (sockaddr*)&address, sizeof(address)) < 0) {
printf("Error binding socket!\n");
}
}
#endif // ML505
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */

View File

@ -0,0 +1,159 @@
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
#include "fsfw/FSFW.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <iomanip>
#include <iostream>
#include <sstream>
#ifndef UT699
/**
* @brief This is the underlying stream buffer which implements the
* streambuf class and overloads the overflow() and sync() methods
* @details
* This class is used to modify the output of the stream, for example by adding.
* It also calls the char printing function which is implemented in the
* board supply package (BSP).
*/
class ServiceInterfaceBuffer : public std::streambuf {
friend class ServiceInterfaceStream;
public:
static constexpr uint8_t MAX_PREAMBLE_SIZE = 40;
ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, bool buffered,
bool errStream, uint16_t port);
protected:
bool isActive;
//! This is called when buffer becomes full. If
//! buffer is not used, then this is called every
//! time when characters are put to stream.
int overflow(int c = Traits::eof()) override;
//! This function is called when stream is flushed,
//! for example when std::endl is put to stream.
int sync(void) override;
bool isBuffered() const;
private:
//! For additional message information
std::string logMessage;
std::string preamble;
#if FSFW_COLORED_OUTPUT == 1
std::string colorPrefix;
void setAsciiColorPrefix(std::string colorPrefix);
#endif
// For EOF detection
typedef std::char_traits<char> Traits;
//! This is useful for some terminal programs which do not have
//! implicit carriage return with newline characters.
bool addCrToPreamble;
//! Specifies whether the stream operates in buffered or unbuffered mode.
bool buffered;
//! This specifies to print to stderr and work in unbuffered mode.
bool errStream;
//! Needed for buffered mode.
static size_t const BUF_SIZE = fsfwconfig::FSFW_PRINT_BUFFER_SIZE;
char buf[BUF_SIZE];
//! In this function, the characters are parsed.
void putChars(char const* begin, char const* end);
std::string* getPreamble(size_t* preambleSize = nullptr);
bool crAdditionEnabled() const;
};
#endif
#ifdef UT699
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
friend class ServiceInterfaceStream;
public:
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
protected:
bool isActive;
// This is called when buffer becomes full. If
// buffer is not used, then this is called every
// time when characters are put to stream.
virtual int overflow(int c = Traits::eof());
// This function is called when stream is flushed,
// for example when std::endl is put to stream.
virtual int sync(void);
private:
// For additional message information
std::string log_message;
// For EOF detection
typedef std::char_traits<char> Traits;
// Work in buffer mode. It is also possible to work without buffer.
static size_t const BUF_SIZE = 128;
char buf[BUF_SIZE];
// In this function, the characters are parsed.
void putChars(char const* begin, char const* end);
};
#endif // UT699
#ifdef ML505
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <sys/types.h>
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
friend class ServiceInterfaceStream;
public:
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
protected:
bool isActive;
// This is called when buffer becomes full. If
// buffer is not used, then this is called every
// time when characters are put to stream.
virtual int overflow(int c = Traits::eof());
// This function is called when stream is flushed,
// for example when std::endl is put to stream.
virtual int sync(void);
private:
// For additional message information
std::string log_message;
// For EOF detection
typedef std::char_traits<char> Traits;
// Work in buffer mode. It is also possible to work without buffer.
static size_t const BUF_SIZE = 128;
char buf[BUF_SIZE];
// In this function, the characters are parsed.
void putChars(char const* begin, char const* end);
int udpSocket;
sockaddr_in remoteAddress;
socklen_t remoteAddressLength;
void initSocket();
};
#endif // ML505
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */

View File

@ -0,0 +1,21 @@
#include "ServiceInterfaceStream.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble,
bool buffered, bool errStream, uint16_t port)
: std::ostream(&streambuf), streambuf(setMessage, addCrToPreamble, buffered, errStream, port) {}
void ServiceInterfaceStream::setActive(bool myActive) { this->streambuf.isActive = myActive; }
std::string* ServiceInterfaceStream::getPreamble() { return streambuf.getPreamble(); }
bool ServiceInterfaceStream::crAdditionEnabled() const { return streambuf.crAdditionEnabled(); }
#if FSFW_COLORED_OUTPUT == 1
void ServiceInterfaceStream::setAsciiColorPrefix(std::string asciiColorCode) {
streambuf.setAsciiColorPrefix(asciiColorCode);
}
#endif
#endif

View File

@ -0,0 +1,67 @@
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_
#include "ServiceInterfaceBuffer.h"
#include "fsfw/FSFW.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <cstdio>
#include <iostream>
/**
* Generic service interface stream which can be used like std::cout or
* std::cerr but has additional capability. Add preamble and timestamp
* to output. Can be run in buffered or unbuffered mode.
*/
class ServiceInterfaceStream : public std::ostream {
public:
/**
* This constructor is used by specifying the preamble message.
* Optionally, the output can be directed to stderr and a CR character
* can be prepended to the preamble.
* @param setMessage message of preamble.
* @param addCrToPreamble Useful for applications like Puttty.
* @param buffered specify whether to use buffered mode.
* @param errStream specify which output stream to use (stderr or stdout).
*/
ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble = false, bool buffered = true,
bool errStream = false, uint16_t port = 1234);
//! An inactive stream will not print anything.
void setActive(bool);
/**
* This can be used to retrieve the preamble in case it should be printed in
* the unbuffered mode.
* @return Preamle consisting of log message and timestamp.
*/
std::string* getPreamble();
/**
* Can be used to determine if the stream was configured to add CR characters in addition
* to newline characters.
* @return
*/
bool crAdditionEnabled() const;
#if FSFW_COLORED_OUTPUT == 1
void setAsciiColorPrefix(std::string asciiColorCode);
#endif
protected:
ServiceInterfaceBuffer streambuf;
};
// Forward declaration of interface streams. These should be instantiated in
// main. They can then be used like std::cout or std::cerr.
namespace sif {
extern ServiceInterfaceStream debug;
extern ServiceInterfaceStream info;
extern ServiceInterfaceStream warning;
extern ServiceInterfaceStream error;
} // namespace sif
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */

View File

@ -0,0 +1,18 @@
#ifndef FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_
#define FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_
namespace sif {
enum class OutputTypes { OUT_INFO, OUT_DEBUG, OUT_WARNING, OUT_ERROR };
static const char* const ANSI_COLOR_RED = "\x1b[31m";
static const char* const ANSI_COLOR_GREEN = "\x1b[32m";
static const char* const ANSI_COLOR_YELLOW = "\x1b[33m";
static const char* const ANSI_COLOR_BLUE = "\x1b[34m";
static const char* const ANSI_COLOR_MAGENTA = "\x1b[35m";
static const char* const ANSI_COLOR_CYAN = "\x1b[36m";
static const char* const ANSI_COLOR_RESET = "\x1b[0m";
} // namespace sif
#endif /* FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_ */

View File

@ -0,0 +1,25 @@
#include "libxiphos.h"
#include "CoreController.h"
bool rebootWasCalled = false;
xsc_libnor_chip_t lastChip;
xsc_libnor_copy_t lastCopy;
bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy) {
tgtChip = lastChip;
tgtCopy = lastCopy;
bool tmp = rebootWasCalled;
if (rebootWasCalled) {
rebootWasCalled = false;
}
return tmp;
}
void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy) {
rebootWasCalled = true;
lastChip = boot_chip;
lastCopy = boot_copy;
CoreController::setCurrentBootCopy(static_cast<xsc::Chip>(boot_chip),
static_cast<xsc::Copy>(boot_copy));
}

View File

@ -0,0 +1,25 @@
#pragma once
/** Type for identifying the nominal or the gold (redundant) flash copy */
typedef enum {
XSC_LIBNOR_COPY_NOMINAL,
XSC_LIBNOR_COPY_GOLD,
XSC_LIBNOR_COPY_TOTAL_NUMBER
} xsc_libnor_copy_t;
/** Type for identifying on of the two NOR flash chips */
typedef enum {
XSC_LIBNOR_CHIP_0, /* First NOR flash chip */
XSC_LIBNOR_CHIP_1, /* Second NOR flash chip */
XSC_LIBNOR_CHIP_TOTAL_NUMBER
} xsc_libnor_chip_t;
/**
* @brief Used to verify whether reboot function was called
*
* @param tgtChip
* @param tgtCopy
*/
bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy);
void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy);

View File

@ -0,0 +1,413 @@
#include <catch2/catch_test_macros.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include "CoreController.h"
#include "HasActionsIF.h"
#include "event.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "libxiphos.h"
static constexpr bool CAT_FILE_TO_CONSOLE = false;
const std::string CONF_PATH = "/tmp/conf";
const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt";
void catFileToConsole();
ServiceInterfaceStream sif::debug("DEBUG");
ServiceInterfaceStream sif::info("INFO");
ServiceInterfaceStream sif::warning("WARNING");
ServiceInterfaceStream sif::error("ERROR", false, false, true);
TEST_CASE("Core Controller Reboot File Handling", "[reboot-file]") {
if (not std::filesystem::exists(CONF_PATH)) {
std::filesystem::create_directory(CONF_PATH);
}
CoreController ctrl;
std::array<uint8_t, 12> cmdData = {};
SECTION("Primary") {
xsc_libnor_chip_t chip;
xsc_libnor_copy_t copy;
RebootFile rf = {};
ctrl.rewriteRebootFile(rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == 0);
REQUIRE(rf.lastChip == 0);
REQUIRE(rf.lastCopy == 0);
// This recreates the file but should also increment the boot counter of the current image
REQUIRE(ctrl.CURRENT_CHIP == xsc::CHIP_0);
REQUIRE(ctrl.CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(true);
catFileToConsole();
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT);
REQUIRE(rf.img00Cnt == 1);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == 0);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_0);
uint8_t newRebootCnt = 3;
CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) ==
HasActionsIF::EXECUTION_FINISHED);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.maxCount == 3);
REQUIRE(not getRebootWasCalled(chip, copy));
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.bootFlag == true);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_0);
REQUIRE(getRebootWasCalled(chip, copy));
REQUIRE(chip == XSC_LIBNOR_CHIP_0);
REQUIRE(copy == XSC_LIBNOR_COPY_GOLD);
EventInfo info = {};
uint32_t numEvents = 0;
// We are now on image 0 1 and an event will be triggered
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_0);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 1);
CHECK(((info.p2 >> 8) & 0xFF) == 0);
CHECK((info.p2 & 0xFF) == 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 1);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Flag was cleared when event was thrown
REQUIRE(rf.bootFlag == false);
REQUIRE(rf.lastChip == xsc::CHIP_0);
REQUIRE(rf.lastCopy == xsc::COPY_1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// We are now on image 1 0 and an event will be triggered
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_1);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 1);
CHECK((info.p2 & 0xFF) == 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 1);
REQUIRE(rf.img11Cnt == 0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 0);
eventWasCalled(info, numEvents);
// On image 1 1 now
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_0);
CHECK(((info.p2 >> 24) & 0xFF) == 3);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 3);
CHECK((info.p2 & 0xFF) == 1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Now it should fall back to 0 0 because all are invalid
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
// Should remain on image now
ctrl.performRebootFileHandling(false);
eventWasCalled(info, numEvents);
CHECK(numEvents == 1);
CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED);
CHECK(static_cast<xsc::Chip>((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1);
CHECK(static_cast<xsc::Copy>(info.p1 & 0xFFFF) == xsc::COPY_1);
CHECK(((info.p2 >> 24) & 0xFF) == 4);
CHECK(((info.p2 >> 16) & 0xFF) == 3);
CHECK(((info.p2 >> 8) & 0xFF) == 3);
CHECK((info.p2 & 0xFF) == 3);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 3);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
// Reset a specific reboot counter
cmdData[0] = 0;
cmdData[1] = 1;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
// Reboot to 0 0 again
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 5);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 3);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_1);
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
uint8_t enable = 0;
ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 0);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Reboot to 1 0 explicitely
CoreController::setCurrentBootCopy(xsc::CHIP_1, xsc::COPY_0);
// Reboot three times and verify that no reboot is performed
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 0);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 4);
REQUIRE(rf.img11Cnt == 0);
// Now enable the functionality again and verify it reboots to 1 1
enable = 1;
ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 0);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 1);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should be on 0 0 now
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 1);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 5);
REQUIRE(rf.img11Cnt == 3);
// Now reset all reboot counters manually
cmdData[0] = 0;
cmdData[1] = 0;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
cmdData[0] = 1;
cmdData[1] = 0;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
cmdData[0] = 1;
cmdData[1] = 1;
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
// Reset lock on 0 1
cmdData[0] = false;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Now should be on 0 1
ctrl.parseRebootFile(REBOOT_FILE, rf);
CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0);
CHECK(CoreController::CURRENT_COPY == xsc::COPY_1);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 3);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == false);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
// Now simulate failure in kernel boot or reboot from ProASIC3
ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
ctrl.performRebootFileHandling(false);
// Image 0 1 should have been marked as invalid now. Reboot will be triggered
// on 1 0 instead of 0 1 because 0 1 is marked as locked
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 1);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == false);
// Reset lock on 0 1 again
cmdData[0] = false;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
// Lock 1 1 manually
// Reset lock on 0 1 again
cmdData[0] = true;
cmdData[1] = 1;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should be on 0 1 now
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 1);
REQUIRE(rf.img10Cnt == 3);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == false);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == true);
// Lock everything except 0 0
cmdData[0] = true;
cmdData[1] = 0;
cmdData[2] = 1;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
cmdData[0] = true;
cmdData[1] = 1;
cmdData[2] = 0;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 0);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == true);
REQUIRE(rf.img11Lock == true);
// Switch to 0 0
ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
ctrl.performRebootFileHandling(false);
// Should still be on 0 0
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 4);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == true);
REQUIRE(rf.img11Lock == true);
// Unlock 1 0
cmdData[0] = false;
cmdData[1] = 1;
cmdData[2] = 0;
ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3);
// Reboots to 1 0 now
ctrl.performRebootFileHandling(false);
ctrl.parseRebootFile(REBOOT_FILE, rf);
REQUIRE(rf.enabled == 1);
REQUIRE(rf.img00Cnt == 5);
REQUIRE(rf.img01Cnt == 0);
REQUIRE(rf.img10Cnt == 0);
REQUIRE(rf.img11Cnt == 0);
REQUIRE(rf.img00Lock == false);
REQUIRE(rf.img01Lock == true);
REQUIRE(rf.img10Lock == false);
REQUIRE(rf.img11Lock == true);
REQUIRE(CoreController::CURRENT_CHIP == xsc::CHIP_1);
REQUIRE(CoreController::CURRENT_COPY == xsc::COPY_0);
}
if (std::filesystem::exists(CONF_PATH)) {
std::uintmax_t n = std::filesystem::remove_all(CONF_PATH);
CHECK(n == 2);
}
}
void catFileToConsole() {
if (CAT_FILE_TO_CONSOLE) {
std::ifstream file(REBOOT_FILE);
if (file.is_open()) {
std::cout << file.rdbuf();
}
}
}

View File

@ -0,0 +1,10 @@
#include <stdbool.h>
#include <stdio.h>
void printChar(const char* character, bool errStream) {
if (errStream) {
putc(*character, stderr);
return;
}
putc(*character, stdout);
}