Compare commits

...

49 Commits

Author SHA1 Message Date
dea3077f29 changelog, prep v6.0.0
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-02 14:44:15 +02:00
d687715bcb Merge pull request 'v6.0.0' (#724) from main-v6 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #724
2023-07-02 14:43:24 +02:00
e2cd822e9c Merge branch 'main' into main-v6
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:30:50 +02:00
0e9035d6c1 changelog, prep v5.2.0
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-02 14:21:35 +02:00
c80eff4922 Merge pull request 'EM ACS board' (#723) from add-back-em-acs-brd into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #723
2023-07-02 14:19:54 +02:00
a5c9e1481b changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:04:29 +02:00
e19ddcfbd8 EM ACS board
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:02:37 +02:00
add079a7c6 Merge pull request 'Updates for new firmware' (#721) from complete-fw-tests into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #721
2023-07-01 13:30:26 +02:00
9cdcd47b1a Merge remote-tracking branch 'origin/main-v6' into complete-fw-tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-30 10:45:16 +02:00
dd5270e974 Merge pull request 'Important bugfix for live channel' (#720) from live-channel-bugfix into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #720
2023-06-29 16:39:09 +02:00
56ea9af615 add documentation of initial delay
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:06:25 +02:00
4fc999e102 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:03:45 +02:00
04d24e74b1 q7s-package version specification
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:01:54 +02:00
8137c9ea25 Merge remote-tracking branch 'origin/main-v6' into complete-fw-tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:00:49 +02:00
723b4bba3f Merge remote-tracking branch 'origin/main-v6' into live-channel-bugfix 2023-06-29 15:00:20 +02:00
8cff2fd6f7 Merge remote-tracking branch 'origin/main' into live-channel-bugfix 2023-06-29 15:00:11 +02:00
a1f7f77e01 Merge remote-tracking branch 'origin/main' into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-29 14:59:18 +02:00
f3aab775f3 Merge pull request 'Core controller bugfix' (#719) from core-ctrl-init-bugfix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #719
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:58:28 +02:00
59d542ab39 Merge remote-tracking branch 'origin/main' into core-ctrl-init-bugfix 2023-06-29 14:58:13 +02:00
7b0285c4ce Merge pull request 'Only reset PTME on rate change' (#716) from only-reset-ptme-on-rate-change into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #716
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:56:35 +02:00
0a77ee0508 Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-06-29 14:51:15 +02:00
51cbe46cf5 why indeed
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-06-29 14:49:57 +02:00
26fc4b8add Merge pull request 'small fix for persistent TM store' (#722) from persistent-tm-stores-fixes into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #722
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:46:50 +02:00
825de04f3b changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 10:15:36 +02:00
33985937b7 typo
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 09:44:09 +02:00
ba36b5f091 Merge branch 'main-v6' into live-channel-bugfix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 08:55:09 +02:00
4f5903227e changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main-v6 Build queued...
2023-06-29 08:54:58 +02:00
2173d89047 changelog 2023-06-29 08:54:34 +02:00
0a12dbf2be changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 08:53:08 +02:00
ad3c0e2a0e small fix for persistent TM store
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 01:28:40 +02:00
03e772246f less cycles..
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 00:35:06 +02:00
25da131653 seems to work well
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 00:33:58 +02:00
4c6b098f42 Merge branch 'live-channel-bugfix' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 17:49:06 +02:00
b57283101b important bugfix for live channel
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 17:46:21 +02:00
9dfdf38822 important bugfix for live channel
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 17:20:10 +02:00
c6240285e2 Merge branch 'core-ctrl-init-bugfix' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:51:48 +02:00
87c05705ec core ctrl bugfix
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 15:43:44 +02:00
c881b36630 prevent warning
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:28:27 +02:00
a380ff5ac9 Merge branch 'main-v6' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:24:20 +02:00
4d17184fba Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 15:18:05 +02:00
d8efd05a88 Merge branch 'main' into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:08:38 +02:00
4c63fed69d that is annoying
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:35:38 +02:00
eb27ab4bb0 fix and optimization
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:32:35 +02:00
b0a38136c1 Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change 2023-06-28 13:28:00 +02:00
b5cc430b5b Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-28 13:21:33 +02:00
27f77799a6 bump major version
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-26 17:33:17 +02:00
9080e7cbe4 Merge branch 'v5.0.0-dev' into main-v6 2023-06-26 17:33:01 +02:00
6c39e7dd0c and go back to newest version here
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-26 17:08:39 +02:00
1cc62238c2 only reset PTME on rate change init
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-26 14:39:03 +02:00
21 changed files with 157 additions and 185 deletions

View File

@ -16,11 +16,38 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
# [v6.0.0] to be released
# [v6.0.0] 2023-07-02
- `q7s-package` version v3.2.0
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
# [v5.1.0] to be released
## Changed
- Added back PTME busy bit polling. This is necessary due to changes to the AXI APB interface
to the PTME core.
## Fixed
- For the live channel (VC0), telemetry was still only dumped if the transmitter is active.
Please note that this fix will lead to crashes for FW versions below v3.2.
However, it might not be an issue for the oldest firmware on the satellite (v2.5.1).
# [v5.2.0] 2023-07-02
## Fixed
- The firmware information event was not triggered even when possible because of an ordering
bug in the initializer function.
- Empty dumps (no TM in time range) will now correctly be completed immediately
## Changed
- PTME was always reset on submode changes. The reset will now only be performed if the actual data
rate changes.
- Add back ACS board code for the EM. Now that the radiation sensor was removed, the image switching
issue has disappeared and adding back the ACS board is worth it for the GPS timekeeping.
# [v5.1.0] 2023-06-28
- `eive-tmtc` version v5.1.0

View File

@ -9,8 +9,8 @@
# ##############################################################################
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 5)
set(OBSW_VERSION_MINOR 1)
set(OBSW_VERSION_MAJOR 6)
set(OBSW_VERSION_MINOR 0)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@ -105,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER
${OBSW_Q7S_EM}
CACHE STRING "Add thermal sensor temperature inserter")
set(OBSW_ADD_ACS_BOARD
${INIT_VAL}
1
CACHE STRING "Add ACS board module")
set(OBSW_ADD_GPS_CTRL
${INIT_VAL}

View File

@ -964,6 +964,12 @@ used by other software components to read the current chip and copy.
This is a configuration scripts which runs after the Network Time Protocol has run. This script
currently sets the static IP address `192.168.133.10` and starts the `can` interface.
## Initial boot delay
You can create a file named `boot_delays_secs.txt` inside the home folder to delay the OBSW boot
for 6 seconds if the file is empty of for the number of seconds specified inside the file. This
can be helpful if something inside the OBSW leads to an immediate crash of the OBC.
## PCDU
Connect to serial console of P60 Dock

View File

@ -85,13 +85,9 @@ static constexpr char EN_RW_4[] = "enable_rw_4";
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select";
static constexpr char ENABLE_RADFET[] = "enable_radfet";
static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0";
static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0";
static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1";
static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1";
static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2";
static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2";
static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3";
static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3";
static constexpr char PTME_RESETN[] = "ptme_resetn";

View File

@ -170,9 +170,6 @@ ReturnValue_t CoreController::initialize() {
sdStateMachine();
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
announceCurrentImageInfo();
announceVersionInfo();
EventManagerIF *eventManager =
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (eventManager == nullptr or eventQueue == nullptr) {
@ -189,17 +186,22 @@ ReturnValue_t CoreController::initialize() {
if (result != returnvalue::OK) {
sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl;
}
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
announceCurrentImageInfo();
// This has to come before the version announce because it might be required for retrieving
// the firmware version.
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
result = sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
if (result != returnvalue::OK) {
// TODO: This might be a reason to switch to another image..
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
return ObjectManager::CHILD_INIT_FAILED;
result = ObjectManager::CHILD_INIT_FAILED;
}
}
return returnvalue::OK;
announceVersionInfo();
return result;
}
ReturnValue_t CoreController::initializeAfterTaskCreation() {

View File

@ -731,20 +731,12 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
// GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core
GpioCookie* gpioCookiePtmeIp = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr;
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN",
@ -753,19 +745,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs");
// Creating virtual channel interfaces
VirtualChannelIF* vc0 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
VirtualChannelIF* vc0 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
// Creating ptme object and adding virtual channel interfaces
Ptme* ptme = new Ptme(objects::PTME);
ptme->addVcInterface(ccsds::VC0, vc0);

View File

@ -84,9 +84,10 @@ void ObjectFactory::produce(void* args) {
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
#if OBSW_ADD_ACS_BOARD == 1
// Still initialize chip select to avoid SPI bus issues.
// Initialize chip select to avoid SPI bus issues.
createRadSensorChipSelect(gpioComIF);
#if OBSW_ADD_ACS_BOARD == 1
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
adis1650x::Type::ADIS16507);
#else

View File

@ -96,13 +96,9 @@ enum gpioId_t {
SPI_MUX,
VC0_PAPB_EMPTY,
VC0_PAPB_BUSY,
VC1_PAPB_EMPTY,
VC1_PAPB_BUSY,
VC2_PAPB_EMPTY,
VC2_PAPB_BUSY,
VC3_PAPB_EMPTY,
VC3_PAPB_BUSY,
PTME_RESETN,
PDEC_RESET,

View File

@ -16,9 +16,9 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
AxiPtmeConfig::~AxiPtmeConfig() {}
ReturnValue_t AxiPtmeConfig::initialize() {
ReturnValue_t result = returnvalue::OK;
UioMapper uioMapper(axiUio, mapNum);
result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
ReturnValue_t result =
uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -26,8 +26,7 @@ ReturnValue_t AxiPtmeConfig::initialize() {
}
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
ReturnValue_t result = returnvalue::OK;
result = mutex->lockMutex(timeoutType, mutexTimeout);
ReturnValue_t result = mutex->lockMutex(timeoutType, mutexTimeout);
if (result != returnvalue::OK) {
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
return returnvalue::FAILED;
@ -41,6 +40,11 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
return returnvalue::OK;
}
uint8_t AxiPtmeConfig::readCaduRateReg() {
MutexGuard mg(mutex);
return static_cast<uint8_t>(*(baseAddress + CADU_BITRATE_REG));
}
void AxiPtmeConfig::enableTxclockManipulator() {
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
}

View File

@ -38,6 +38,7 @@ class AxiPtmeConfig : public SystemObject {
* frequency of the clock connected to the bit clock input of PTME.
*/
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
uint8_t readCaduRateReg();
/**
* @brief Next to functions control the tx clock manipulator component

View File

@ -7,20 +7,16 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
gpioId_t papbEmptyId, std::string uioFile, int mapNum)
: gpioComIF(gpioComIF),
papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId),
uioFile(std::move(uioFile)),
mapNum(mapNum) {}
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId,
std::string uioFile, int mapNum)
: gpioComIF(gpioComIF), papbEmptyId(papbEmptyId), uioFile(std::move(uioFile)), mapNum(mapNum) {}
PapbVcInterface::~PapbVcInterface() {}
ReturnValue_t PapbVcInterface::initialize() {
UioMapper uioMapper(uioFile, mapNum);
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
UioMapper::Permissions::WRITE_ONLY);
UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -32,63 +28,27 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
if (size < 4) {
return returnvalue::FAILED;
}
if (pollInterfaceReadiness(0, true) == returnvalue::OK) {
if (pollReadyForPacket()) {
startPacketTransfer(ByteWidthCfg::ONE);
} else {
return DirectTmSinkIF::IS_BUSY;
}
// TODO: This should work but does not.. :(
// size_t idx = 0;
// while (idx < size) {
//
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
// if ((size - idx) < 4) {
// *vcBaseReg = CONFIG_DATA_INPUT | (size - idx - 1);
// usleep(1);
// }
// if (pollPapbBusySignal(2) == returnvalue::OK) {
// // vcBaseReg + DATA_REG_OFFSET + 3 = static_cast<uint8_t>(data + idx);
// // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast<uint8_t>(data + idx + 1);
// // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast<uint8_t>(data + idx + 2);
// // vcBaseReg + DATA_REG_OFFSET = static_cast<uint8_t>(data + idx + 3);
//
// // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize);
// *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast<const uint32_t*>(data + idx);
// //uint8_t* byteReg = reinterpret_cast<uint8_t*>(vcBaseReg + DATA_REG_OFFSET);
//
// //byteReg[0] = data[idx];
// //byteReg[1] = data[idx];
// } else {
// abortPacketTransfer();
// return returnvalue::FAILED;
// }
// // TODO: Change this after the bugfix. Right now, the PAPB ignores the content of the byte
// // width configuration.5
// // It's okay to increment by a larger amount for the last segment here, loop will be over
// // in any case.
// idx += 4;
// }
for (size_t idx = 0; idx < size; idx++) {
// This delay is super-important, DO NOT REMOVE!
// Polling the GPIO or the config register too often messes up the scheduler.
// TODO: Maybe this should not be done like this. It would be better if there was a custom
// FPGA module which can accept packets and then takes care of dumping that packet into
// the PTME. DMA would be an ideal solution for this.
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
} else {
abortPacketTransfer();
return returnvalue::FAILED;
}
}
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
completePacketTransfer();
} else {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
for (size_t idx = 0; idx < size; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
}
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
completePacketTransfer();
return returnvalue::OK;
}
@ -98,63 +58,49 @@ void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
bool checkReadyState) const {
uint32_t busyIdx = 0;
nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS;
while (true) {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
bool busy = (reg >> 5) & 0b1;
bool ready = (reg >> 6) & 0b1;
if (not busy) {
return returnvalue::OK;
}
if (checkReadyState and not ready) {
return PAPB_BUSY;
}
busyIdx++;
if (busyIdx >= maxPollRetries) {
return PAPB_BUSY;
}
// Ignore signal handling here for now.
nanosleep(&nextDelay, &remDelay);
// Adaptive delay.
if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
nextDelay.tv_nsec *= 2;
}
}
return returnvalue::OK;
bool PapbVcInterface::pollReadyForPacket() const {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
return (reg >> 6) & 0b1;
}
void PapbVcInterface::isVcInterfaceBufferEmpty() {
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
ReturnValue_t result = returnvalue::OK;
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
result = gpioComIF->readGpio(papbEmptyId, papbEmptyState);
if (result != returnvalue::OK) {
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return;
sif::error << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return true;
}
if (papbEmptyState == gpio::Levels::HIGH) {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
} else {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
return true;
}
return;
return false;
}
bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; }
bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); }
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
uint32_t reg;
uint32_t idx = 0;
while (idx < maxCycles) {
reg = *vcBaseReg;
// Busy bit.
if (not((reg >> 5) & 0b1)) {
return true;
}
idx++;
}
return false;
}
ReturnValue_t PapbVcInterface::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */
uint8_t testPacket[1105];

View File

@ -30,8 +30,7 @@ class PapbVcInterface : public VirtualChannelIF {
* @param uioFile UIO file providing access to the PAPB bus
* @param mapNum Map number of UIO map associated with this virtual channel
*/
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
std::string uioFile, int mapNum);
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, std::string uioFile, int mapNum);
virtual ~PapbVcInterface();
bool isBusy() const override;
@ -81,11 +80,9 @@ class PapbVcInterface : public VirtualChannelIF {
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
static constexpr uint32_t MAX_BUSY_POLLS = 1000;
LinuxLibgpioIF* gpioComIF = nullptr;
/** Pulled to low when virtual channel not ready to receive data */
gpioId_t papbBusyId = gpio::NO_GPIO;
/** High when external buffer memory of virtual channel is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO;
@ -120,13 +117,15 @@ class PapbVcInterface : public VirtualChannelIF {
*
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
*/
inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const;
inline bool pollReadyForPacket() const;
inline bool pollReadyForOctet(uint32_t maxCycles) const;
/**
* @brief This function can be used for debugging to check whether there are packets in
* the packet buffer of the virtual channel or not.
*/
void isVcInterfaceBufferEmpty();
bool isVcInterfaceBufferEmpty();
/**
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)

View File

@ -26,6 +26,11 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
}
uint32_t PtmeConfig::getRate() {
uint8_t rateReg = axiPtmeConfig->readCaduRateReg();
return (BIT_CLK_FREQ / (rateReg + 1));
}
void PtmeConfig::invertTxClock(bool invert) {
if (invert) {
axiPtmeConfig->enableTxclockInversion();

View File

@ -32,6 +32,7 @@ class PtmeConfig : public SystemObject {
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
*/
ReturnValue_t setRate(uint32_t bitRate);
uint32_t getRate();
/**
* @brief Will change the time the tx data signal is updated with respect to the tx clock

View File

@ -246,7 +246,13 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
triggerEvent(CHANGING_MODE, mode, submode);
if (mode == HasModesIF::MODE_ON) {
if (this->submode != submode) {
uint32_t currentRate = ptmeConfig.getRate();
// Check whether the rate actually changes.
if ((this->submode != submode) and
(((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW) and
(currentRate != RATE_100KBPS))) or
((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH) and
(currentRate != RATE_500KBPS))))) {
initPtmeUpdateAfterXCycles();
updateContext.enableTransmitAfterPtmeUpdate = true;
updateContext.updateClockRate = true;

View File

@ -19,13 +19,8 @@ LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunne
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
readCommandQueue();
while (true) {
bool performWriteOp = true;
if (mode == MODE_OFF or ptmeLocked) {
performWriteOp = false;
}
// The funnel tasks are scheduled here directly as well.
ReturnValue_t result = channel.handleNextTm(performWriteOp);
ReturnValue_t result = channel.handleNextTm(!ptmeLocked);
if (result == DirectTmSinkIF::IS_BUSY) {
sif::error << "Lost live TM, PAPB busy" << std::endl;
}

View File

@ -42,13 +42,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
if (not someonesBusy) {
TaskFactory::delayTask(100);
} else if (vcBusyDuringDump) {
// TODO: Might not be necessary
sif::debug << "VC busy, delaying" << std::endl;
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -24,13 +24,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
if (not busy) {
TaskFactory::delayTask(100);
} else if (dumpContext.vcBusyDuringDump) {
sif::debug << "VC busy, delaying" << std::endl;
// TODO: Might not be necessary
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -45,13 +45,19 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
} else {
Command_t execCmd;
// Handle TC requests, for example deletion or retrieval requests.
// TODO: Not really clean here.. would be better if the executed command is returns as an
// enumeration.
result = store.handleCommandQueue(ipcStore, execCmd);
if (result == returnvalue::OK) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler(store, dumpContext);
} else if (result == returnvalue::OK) {
cancelDumpCd.resetTimer();
tmSinkBusyCd.resetTimer();
dumpContext.reset();
}
}
if (execCmd != CommandMessageIF::CMD_NONE) {
tcRequestReceived = true;
}
}
@ -119,21 +125,13 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
DumpContext& dumpContext, bool& dumpPerformed) {
size_t dumpedLen = 0;
auto dumpDoneHandler = [&]() {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets,
dumpContext.dumpedBytes);
dumpContext.reset();
};
// Dump the next packet into the PTME.
dumpContext.ptmeBusyCounter = 0;
tmSinkBusyCd.resetTimer();
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
// This can happen if a file is corrupted and the next file swap completes the dump.
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
return returnvalue::OK;
} else if (result != returnvalue::OK) {
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
@ -157,7 +155,7 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
}
}
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
}
return returnvalue::OK;
}
@ -198,6 +196,14 @@ ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& pare
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
void TmStoreTaskBase::dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext) {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, dumpContext.dumpedBytes);
dumpContext.reset();
}
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
void TmStoreTaskBase::readCommandQueue(void) {

View File

@ -96,6 +96,8 @@ class TmStoreTaskBase : public SystemObject,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
void dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext);
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;

View File

@ -128,6 +128,7 @@ ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
Command_t& execCmd) {
execCmd = CommandMessageIF::CMD_NONE;
CommandMessage cmdMessage;
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
if (result != returnvalue::OK) {
@ -162,9 +163,9 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
if (result == BUSY_DUMPING) {
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
} else {
execCmd = cmd;
return result;
}
execCmd = cmd;
}
}
return result;
@ -359,7 +360,10 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
}
ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fileHasSwapped) {
if (state == State::IDLE or dumpParams.pendingPacketDump) {
if (state == State::IDLE) {
return DUMP_DONE;
}
if (dumpParams.pendingPacketDump) {
return returnvalue::FAILED;
}
fileHasSwapped = false;