Merge branch 'mueller/reboot-file-handling' into mueller/master
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
This commit is contained in:
commit
b98a24373e
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,7 +9,7 @@
|
||||
!misc/eclipse/**/.project
|
||||
|
||||
#vscode
|
||||
.vscode
|
||||
/.vscode
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
|
@ -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)
|
||||
@ -115,6 +115,12 @@ if(TGT_BSP)
|
||||
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}
|
||||
)
|
||||
|
36
README.md
36
README.md
@ -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
7
bsp_egse/CMakeLists.txt
Normal 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
192
bsp_egse/InitMission.cpp
Normal 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
21
bsp_egse/InitMission.h
Normal 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_ */
|
49
bsp_egse/ObjectFactory.cpp
Normal file
49
bsp_egse/ObjectFactory.cpp
Normal 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
8
bsp_egse/ObjectFactory.h
Normal 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_ */
|
7
bsp_egse/boardconfig/CMakeLists.txt
Normal file
7
bsp_egse/boardconfig/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
print.c
|
||||
)
|
||||
|
||||
target_include_directories(${OBSW_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
8
bsp_egse/boardconfig/busConf.h
Normal file
8
bsp_egse/boardconfig/busConf.h
Normal 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_ */
|
38
bsp_egse/boardconfig/etl_profile.h
Normal file
38
bsp_egse/boardconfig/etl_profile.h
Normal 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
|
15
bsp_egse/boardconfig/gcov.h
Normal file
15
bsp_egse/boardconfig/gcov.h
Normal 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_ */
|
10
bsp_egse/boardconfig/print.c
Normal file
10
bsp_egse/boardconfig/print.c
Normal 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);
|
||||
}
|
8
bsp_egse/boardconfig/print.h
Normal file
8
bsp_egse/boardconfig/print.h
Normal 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_ */
|
6
bsp_egse/boardconfig/rpiConfig.h.in
Normal file
6
bsp_egse/boardconfig/rpiConfig.h.in
Normal 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
28
bsp_egse/main.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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): {
|
||||
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 (SET_MAX_REBOOT_CNT): {
|
||||
if (size < 1) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
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);
|
||||
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,20 +1186,29 @@ void CoreController::performWatchdogControlOperation() {
|
||||
}
|
||||
}
|
||||
|
||||
void CoreController::performRebootFileHandling(bool recreateFile) {
|
||||
void CoreController::performMountedSdCardOperations() {
|
||||
if (doPerformMountedSdCardOps) {
|
||||
bool sdCardMounted = false;
|
||||
if (not recreateFile and doPerformRebootFileHandling) {
|
||||
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);
|
||||
}
|
||||
if ((doPerformRebootFileHandling and sdCardMounted) or recreateFile) {
|
||||
initVersionFile();
|
||||
performRebootFileHandling(false);
|
||||
doPerformMountedSdCardOps = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoreController::performRebootFileHandling(bool recreateFile) {
|
||||
using namespace std;
|
||||
if (recreateFile) {
|
||||
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
|
||||
}
|
||||
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;
|
||||
@ -1194,6 +1216,12 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
||||
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 {
|
||||
@ -1202,161 +1230,173 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
case (xsc::COPY_1): {
|
||||
rebootFile.img01Cnt++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
} else {
|
||||
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
||||
rebootFile.img10Lock = true;
|
||||
} else {
|
||||
rebootFile.img11Lock = true;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
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;
|
||||
determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy);
|
||||
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 " << rebootFile.lastChip << " " << rebootFile.lastCopy
|
||||
<< std::endl;
|
||||
<< " 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>(rebootFile.lastChip),
|
||||
static_cast<xsc_libnor_copy_t>(rebootFile.lastCopy));
|
||||
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);
|
||||
}
|
||||
doPerformRebootFileHandling = false;
|
||||
}
|
||||
}
|
||||
|
||||
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_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;
|
||||
if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) {
|
||||
tgtCopy = xsc::COPY_1;
|
||||
return;
|
||||
} 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;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tgtChip = xsc::CHIP_0;
|
||||
tgtCopy = xsc::COPY_1;
|
||||
// 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;
|
||||
}
|
||||
} else {
|
||||
tgtCopy = xsc::COPY_1;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
tgtChip = xsc::CHIP_1;
|
||||
tgtCopy = xsc::COPY_0;
|
||||
if (rf.img00Lock) {
|
||||
needsReboot = false;
|
||||
}
|
||||
} else {
|
||||
// Reboot on fallback image
|
||||
// Reboot to fallback image
|
||||
}
|
||||
}
|
||||
if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) 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) {
|
||||
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.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 ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and
|
||||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -3,5 +3,3 @@ target_sources(${OBSW_NAME} PRIVATE
|
||||
PlocUpdater.cpp
|
||||
PlocMemoryDumper.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(startracker)
|
@ -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}!")
|
||||
|
@ -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!")
|
||||
|
@ -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
|
13
cmake/scripts/egse/egse_path_helper_win.sh
Normal file
13
cmake/scripts/egse/egse_path_helper_win.sh
Normal 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"
|
34
cmake/scripts/egse/make-debug-cfg.sh
Normal file
34
cmake/scripts/egse/make-debug-cfg.sh
Normal 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
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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" />
|
||||
|
@ -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,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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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");
|
||||
|
@ -3,3 +3,5 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER)
|
||||
GPSHyperionLinuxController.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
add_subdirectory(startracker)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
@ -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
|
@ -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_ */
|
@ -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;
|
||||
}
|
@ -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"
|
2074
linux/devices/startracker/StarTrackerHandler.cpp
Normal file
2074
linux/devices/startracker/StarTrackerHandler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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_ */
|
@ -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;
|
||||
}
|
@ -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_ */
|
@ -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;
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
result = checkFlashActionReply(req.region, req.address, req.length);
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
bytesWritten += CHUNK_SIZE;
|
||||
}
|
||||
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 result;
|
||||
}
|
||||
remainingBytes = remainingBytes - MAX_FLASH_DATA;
|
||||
}
|
||||
file.seekg(fileSize - remainingBytes, file.beg);
|
||||
file.read(reinterpret_cast<char*>(req.data), remainingBytes);
|
||||
file.close();
|
||||
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);
|
||||
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;
|
||||
}
|
@ -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_ */
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
6
scripts/egse-port.sh
Normal 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
|
@ -4,4 +4,3 @@
|
||||
int main(int argc, char* argv[]) {
|
||||
// fsfwtest::customMain(argc, argv);
|
||||
}
|
||||
|
||||
|
1
unittest/rebootLogic/.gitignore
vendored
1
unittest/rebootLogic/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/build
|
||||
c_cpp_properties.json
|
||||
|
51
unittest/rebootLogic/.vscode/settings.json
vendored
Normal file
51
unittest/rebootLogic/.vscode/settings.json
vendored
Normal 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"
|
||||
}
|
||||
}
|
@ -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})
|
||||
|
16
unittest/rebootLogic/README.md
Normal file
16
unittest/rebootLogic/README.md
Normal 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
|
||||
```
|
@ -1,5 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char**) {
|
||||
std::cout << "Hello, world!\n";
|
||||
}
|
14
unittest/rebootLogic/src/CMakeLists.txt
Normal file
14
unittest/rebootLogic/src/CMakeLists.txt
Normal 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)
|
529
unittest/rebootLogic/src/CoreController.cpp
Normal file
529
unittest/rebootLogic/src/CoreController.cpp
Normal 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;
|
||||
}
|
79
unittest/rebootLogic/src/CoreController.h
Normal file
79
unittest/rebootLogic/src/CoreController.h
Normal 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;
|
||||
};
|
9
unittest/rebootLogic/src/HasActionsIF.h
Normal file
9
unittest/rebootLogic/src/HasActionsIF.h
Normal 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;
|
||||
};
|
5
unittest/rebootLogic/src/SdCardManager.cpp
Normal file
5
unittest/rebootLogic/src/SdCardManager.cpp
Normal 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; }
|
23
unittest/rebootLogic/src/SdCardManager.h
Normal file
23
unittest/rebootLogic/src/SdCardManager.h
Normal 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);
|
||||
};
|
1
unittest/rebootLogic/src/conf.h
Normal file
1
unittest/rebootLogic/src/conf.h
Normal file
@ -0,0 +1 @@
|
||||
#define OBSW_VERBOSE_LEVEL 1
|
6
unittest/rebootLogic/src/definitions.h
Normal file
6
unittest/rebootLogic/src/definitions.h
Normal 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;
|
21
unittest/rebootLogic/src/event.cpp
Normal file
21
unittest/rebootLogic/src/event.cpp
Normal 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();
|
||||
}
|
||||
}
|
41
unittest/rebootLogic/src/event.h
Normal file
41
unittest/rebootLogic/src/event.h
Normal 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);
|
1
unittest/rebootLogic/src/fsfw/CMakeLists.txt
Normal file
1
unittest/rebootLogic/src/fsfw/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
add_subdirectory(serviceinterface)
|
9
unittest/rebootLogic/src/fsfw/FSFW.h
Normal file
9
unittest/rebootLogic/src/fsfw/FSFW.h
Normal 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;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
target_sources(reboot-logic PRIVATE
|
||||
ServiceInterfaceStream.cpp
|
||||
ServiceInterfaceBuffer.cpp
|
||||
)
|
@ -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_ */
|
@ -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 */
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
25
unittest/rebootLogic/src/libxiphos.cpp
Normal file
25
unittest/rebootLogic/src/libxiphos.cpp
Normal 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));
|
||||
}
|
25
unittest/rebootLogic/src/libxiphos.h
Normal file
25
unittest/rebootLogic/src/libxiphos.h
Normal 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);
|
413
unittest/rebootLogic/src/main.cpp
Normal file
413
unittest/rebootLogic/src/main.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
10
unittest/rebootLogic/src/print.c
Normal file
10
unittest/rebootLogic/src/print.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user