Merge remote-tracking branch 'origin/v3.0.0-dev' into core-ctrl-dir-listing-fsm
All checks were successful
EIVE/eive-obsw/pipeline/pr-v3.0.0-dev This commit looks good

This commit is contained in:
Robin Müller 2023-06-09 14:24:42 +02:00
commit 3bdbc67e0d
Signed by: muellerr
GPG Key ID: A649FB78196E3849
13 changed files with 147 additions and 26 deletions

View File

@ -20,6 +20,8 @@ will consitute of a breaking change warranting a new major release:
# [v3.0.0] to be released
- `eive-tmtc` version v4.0.0
## Changed
- Adapt EM configuration to include all GomSpace PCDU devices except the ACU. For the ACU
@ -55,7 +57,9 @@ will consitute of a breaking change warranting a new major release:
commands.
- The Directory Listing direct dumper now has a state machine to stagger the directory listing dump.
This is required because very large dumps will overload the queue capacities in the framework.
- The PUS Service 8 now has larger queue sizes to handle more action replies.
- The PUS Service 8 now has larger queue sizes to handle more action replies. The PUS Service 1
also has a larger queue size to handle a lot of step replies now.
- Moved PDU `vcc` and `vbat` variable from auxiliary dataset to core dataset.
## Added
@ -66,9 +70,12 @@ will consitute of a breaking change warranting a new major release:
- IMTQ HK sets
- IMTQ dummy now handles power switch
- Added some new ACS parameters
- Enabled decimation filter for the ADIS GYRs
- Enabled second low-pass filter for L3GD20H GYRs
## Fixed
- CFDP low level protocol bugfix. Requires `fsfw` update and `tmtc` update.
- Compile fix if SCEX is compiled for the EM.
- Set up Rad Sensor chip select even for EM to avoid SPI bus issues.
- Correct ADIS Gyroscope type configuration for the EM, where the 16507 type is used instead of the
@ -102,6 +109,7 @@ will consitute of a breaking change warranting a new major release:
quaternion.
- Various fixes for the pointing modes of the `ACS Controller`. All modes should work now as
intended.
- The variance for the ADIS GYRs now represents the used `-3` version and not the `-1` version
# [v2.0.5] 2023-05-11

2
fsfw

@ -1 +1 @@
Subproject commit b442ca09b91d0cfdc6acd5a30349a25c4051972c
Subproject commit 5322de059916efcf874b10ccc766b46e53d2470b

View File

@ -113,6 +113,7 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send
if (req->mode != adis.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
adis.type = req->type;
adis.decRate = req->cfg.decRateReg;
// The initial countdown is handled by the device handler now.
// adis.countdown.setTimeout(adis1650x::START_UP_TIME);
if (adis.type == adis1650x::Type::ADIS16507) {
@ -376,6 +377,80 @@ void AcsBoardPolling::gyroL3gHandler(GyroL3g& l3g) {
}
}
ReturnValue_t AcsBoardPolling::writeAdisReg(SpiCookie& cookie) {
ReturnValue_t result = returnvalue::OK;
int retval = 0;
// Prepare transfer
int fileDescriptor = 0;
std::string device = spiComIF.getSpiDev();
UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return spi::OPENING_FILE_FAILED;
}
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 0;
cookie.getSpiParameters(spiMode, spiSpeed, nullptr);
spiComIF.setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
cookie.assignWriteBuffer(cmdBuf.data());
cookie.setTransferSize(2);
gpioId_t gpioId = cookie.getChipSelectPin();
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 0;
MutexIF* mutex = spiComIF.getCsMutex();
cookie.getMutexParams(timeoutType, timeoutMs);
if (mutex == nullptr) {
sif::warning << "GyroADIS16507Handler::spiSendCallback: "
"Mutex or GPIO interface invalid"
<< std::endl;
return returnvalue::FAILED;
}
size_t idx = 0;
spi_ioc_transfer* transferStruct = cookie.getTransferStructHandle();
uint64_t origTx = transferStruct->tx_buf;
uint64_t origRx = transferStruct->rx_buf;
for (idx = 0; idx < 4; idx += 2) {
result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "AcsBoardPolling: Failed to lock mutex" << std::endl;
#endif
return result;
}
// Pull SPI CS low. For now, no support for active high given
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullLow(gpioId);
}
// Execute transfer
// Initiate a full duplex SPI transfer.
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle());
if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = spi::FULL_DUPLEX_TRANSFER_FAILED;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie);
#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullHigh(gpioId);
}
mutex->unlockMutex();
transferStruct->tx_buf += 2;
transferStruct->rx_buf += 2;
if (idx < 4) {
usleep(adis1650x::STALL_TIME_MICROSECONDS);
}
}
transferStruct->tx_buf = origTx;
transferStruct->rx_buf = origRx;
cookie.setTransferSize(0);
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen) {
ReturnValue_t result = returnvalue::OK;
int retval = 0;
@ -455,15 +530,20 @@ void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
ReturnValue_t result;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool mustPerformStartup = false;
uint16_t decRate = 0;
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mode = gyro.mode;
decRate = gyro.decRate;
mustPerformStartup = gyro.performStartup;
}
if (mode == acs::SimpleSensorMode::OFF) {
return;
}
if (mustPerformStartup) {
adis1650x::prepareWriteRegCommand(adis1650x::DEC_RATE_REG, decRate, cmdBuf.data(),
cmdBuf.size());
writeAdisReg(*gyro.cookie);
uint8_t regList[6];
// Read configuration
regList[0] = adis1650x::DIAG_STAT_REG;
@ -491,13 +571,21 @@ void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
gyro.replyResult = returnvalue::FAILED;
return;
}
uint16_t decRateReadBack = (rawReply[10] << 8) | rawReply[11];
sif::debug << "AcsPollingTask: DEC rate configuration. Read " << decRateReadBack
<< ", expected " << decRate << std::endl;
if (decRateReadBack != decRate) {
sif::warning << "AcsPollingTask: DEC rate configuration failed. Read " << decRateReadBack
<< ", expected " << decRate << std::endl;
gyro.replyResult = returnvalue::FAILED;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
gyro.ownReply.cfgWasSet = true;
gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3];
gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.cfg.decRateReg = decRateReadBack;
gyro.ownReply.cfg.prodId = prodId;
gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl);
gyro.performStartup = false;

View File

@ -37,6 +37,7 @@ class AcsBoardPolling : public SystemObject,
struct GyroAdis : public DevBase {
adis1650x::Type type;
uint16_t decRate;
Countdown countdown;
acs::Adis1650XReply ownReply;
acs::Adis1650XReply readerReply;
@ -84,6 +85,8 @@ class AcsBoardPolling : public SystemObject,
void gyroAdisHandler(GyroAdis& gyro);
void mgmLis3Handler(MgmLis3& mgm);
void mgmRm3100Handler(MgmRm3100& mgm);
// This fumction configures the register as specified on p.21 of the datasheet.
ReturnValue_t writeAdisReg(SpiCookie& cookie);
// Special readout: 16us stall time between small 2 byte transfers.
ReturnValue_t readAdisCfg(SpiCookie& spiCookie, size_t transferLen);
};

View File

@ -15,7 +15,7 @@ GyrAdis1650XHandler::GyrAdis1650XHandler(object_id_t objectId, object_id_t devic
}
void GyrAdis1650XHandler::doStartUp() {
if (internalState != InternalState::STARTUP) {
if (internalState == InternalState::NONE) {
internalState = InternalState::STARTUP;
commandExecuted = false;
}
@ -24,13 +24,14 @@ void GyrAdis1650XHandler::doStartUp() {
if (not commandExecuted) {
warningSwitch = true;
breakCountdown.setTimeout(adis1650x::START_UP_TIME);
updatePeriodicReply(true, adis1650x::REPLY);
commandExecuted = true;
}
if (breakCountdown.hasTimedOut()) {
updatePeriodicReply(true, adis1650x::REPLY);
setMode(MODE_ON);
internalState = InternalState::NONE;
}
}
if (internalState == InternalState::STARTUP_DONE) {
setMode(MODE_ON);
commandExecuted = false;
internalState = InternalState::NONE;
}
}
@ -61,6 +62,7 @@ ReturnValue_t GyrAdis1650XHandler::buildTransitionDeviceCommand(DeviceCommandId_
return NOTHING_TO_SEND;
}
*id = adis1650x::REQUEST;
adisRequest.cfg.decRateReg = adis1650x::DEC_RATE;
return preparePeriodicRequest(acs::SimpleSensorMode::NORMAL);
}
case (InternalState::SHUTDOWN): {
@ -91,6 +93,9 @@ ReturnValue_t GyrAdis1650XHandler::scanForReply(const uint8_t *start, size_t rem
getMode() == _MODE_POWER_DOWN) {
return IGNORE_FULL_PACKET;
}
if (internalState == InternalState::STARTUP) {
internalState = InternalState::STARTUP_DONE;
}
*foundLen = remainingSize;
if (remainingSize != sizeof(acs::Adis1650XReply)) {
return returnvalue::FAILED;

View File

@ -48,7 +48,7 @@ class GyrAdis1650XHandler : public DeviceHandlerBase {
bool warningSwitch = true;
enum class InternalState { NONE, STARTUP, SHUTDOWN };
enum class InternalState { NONE, STARTUP, STARTUP_DONE, SHUTDOWN };
InternalState internalState = InternalState::STARTUP;
bool commandExecuted = false;

View File

@ -8,11 +8,6 @@
namespace acs {
struct Adis1650XRequest {
SimpleSensorMode mode;
adis1650x::Type type;
};
struct Adis1650XConfig {
uint16_t diagStat;
uint16_t filterSetting;
@ -22,6 +17,12 @@ struct Adis1650XConfig {
uint16_t prodId;
};
struct Adis1650XRequest {
SimpleSensorMode mode;
adis1650x::Type type;
Adis1650XConfig cfg;
};
struct Adis1650XData {
double sensitivity = 0.0;
// Angular velocities in all axes (X, Y and Z)

View File

@ -52,3 +52,14 @@ double adis1650x::rangMdlToSensitivity(uint16_t rangMdl) {
}
}
}
void adis1650x::prepareWriteRegCommand(uint8_t regStart, uint16_t val, uint8_t* outBuf,
size_t maxLen) {
if (maxLen < 4) {
return;
}
outBuf[0] = regStart | adis1650x::WRITE_MASK;
outBuf[1] = val & 0xff;
outBuf[2] = (regStart + 1) | adis1650x::WRITE_MASK;
outBuf[3] = (val >> 8) & 0xff;
}

View File

@ -16,6 +16,8 @@ enum class BurstModes {
};
size_t prepareReadCommand(const uint8_t* regList, size_t len, uint8_t* outBuf, size_t maxLen);
void prepareWriteRegCommand(uint8_t regStart, uint16_t val, uint8_t* outBuf, size_t maxLen);
BurstModes burstModeFromMscCtrl(uint16_t mscCtrl);
double rangMdlToSensitivity(uint16_t rangMdl);
@ -92,6 +94,9 @@ static constexpr size_t SENSOR_READOUT_SIZE = 20 + 2;
static constexpr uint32_t ADIS_DATASET_ID = READ_SENSOR_DATA;
static constexpr uint32_t ADIS_CFG_DATASET_ID = READ_OUT_CONFIG;
static constexpr uint16_t FILT_CTRL = 0x0000;
static constexpr uint16_t DEC_RATE = 0x00C7;
enum GlobCmds : uint8_t {
FACTORY_CALIBRATION = 0b0000'0010,
SENSOR_SELF_TEST = 0b0000'0100,

View File

@ -781,9 +781,9 @@ class AcsParameters : public HasParametersIF {
/* var = sigma^2, sigma = RND*sqrt(freq), following values are RND^2 and not var as freq is
* assumed to be equal for the same class of sensors */
float gyr02variance[3] = {pow(3.0e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms
pow(3.0e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms
pow(4.3e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms
float gyr02variance[3] = {pow(4.6e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms
pow(4.6e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms
pow(6.1e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms
float gyr13variance[3] = {pow(11e-3, 2), pow(11e-3, 2), pow(11e-3, 2)};
uint8_t preferAdis = false;
float gyrFilterWeight = 0.6;

View File

@ -595,8 +595,8 @@ ReturnValue_t GomspaceDeviceHandler::parsePduHkTable(PDU::PduCoreHk& coreHk, PDU
for (uint8_t idx = 0; idx < PDU::CHANNELS_LEN; idx++) {
coreHk.voltages[idx] = as<uint16_t>(packet + 0x12 + (idx * 2));
}
auxHk.vcc.value = as<int16_t>(packet + 0x24);
auxHk.vbat.value = as<int16_t>(packet + 0x26);
coreHk.vcc.value = as<int16_t>(packet + 0x24);
coreHk.vbat.value = as<int16_t>(packet + 0x26);
coreHk.temperature = as<int16_t>(packet + 0x28) * 0.1;
for (uint8_t idx = 0; idx < 3; idx++) {

View File

@ -404,6 +404,11 @@ class PduCoreHk : public StaticLocalDataSet<9> {
/** Battery mode: 1 = Critical, 2 = Safe, 3 = Normal, 4 = Full */
lp_var_t<uint8_t> battMode = lp_var_t<uint8_t>(sid.objectId, pool::PDU_BATT_MODE, this);
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, pool::PDU_TEMPERATURE, this);
/** Measured VCC */
lp_var_t<int16_t> vcc = lp_var_t<int16_t>(sid.objectId, pool::PDU_VCC, this);
/** Measured VBAT */
lp_var_t<int16_t> vbat = lp_var_t<int16_t>(sid.objectId, pool::PDU_VBAT, this);
};
class PduConfig : public StaticLocalDataSet<32> {
@ -451,11 +456,6 @@ class PduAuxHk : public StaticLocalDataSet<36> {
PduAuxHk(object_id_t objectId, uint32_t setId) : StaticLocalDataSet(sid_t(objectId, setId)) {}
/** Measured VCC */
lp_var_t<int16_t> vcc = lp_var_t<int16_t>(sid.objectId, pool::PDU_VCC, this);
/** Measured VBAT */
lp_var_t<int16_t> vbat = lp_var_t<int16_t>(sid.objectId, pool::PDU_VBAT, this);
/** Output converter enable status */
lp_vec_t<uint8_t, 3> converterEnable =
lp_vec_t<uint8_t, 3>(sid.objectId, pool::PDU_CONV_EN, this);

2
tmtc

@ -1 +1 @@
Subproject commit 6182369e4f40872c5c26e59be25d5fa79339176a
Subproject commit 8804a4e8e9fce1d45fcf62314affb791114d1517