it appears to work well now

This commit is contained in:
2023-02-17 02:10:08 +01:00
parent 9d59f960a4
commit c6c92e1140
8 changed files with 179 additions and 270 deletions

View File

@ -4,6 +4,7 @@
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/common/spi/spiCommon.h>
#include <fsfw_hal/linux/utility.h>
#include <sys/ioctl.h>
@ -32,11 +33,14 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
// This loop takes 50 ms on a debug build.
// Stopwatch watch;
TaskFactory::delayTask(5);
int fd = 0;
for (auto& skip : skipCommandingForRw) {
skip = false;
}
setAllReadFlagsFalse();
ReturnValue_t result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
continue;
@ -55,27 +59,26 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
}
}
closeSpi(fd);
usleep(rws::SPI_REPLY_DELAY);
if (readAllRws(rws::SET_SPEED) != returnvalue::OK) {
continue;
}
// prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
// if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
// continue;
// }
// prepareSimpleCommand(rws::GET_RW_STATUS);
// if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
// continue;
// }
// prepareSimpleCommand(rws::GET_TEMPERATURE);
// if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
// continue;
// }
// prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
// if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
// continue;
// }
// handleSpecialRequests();
prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::GET_RW_STATUS);
if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::GET_TEMPERATURE);
if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
continue;
}
handleSpecialRequests();
}
return returnvalue::OK;
@ -188,7 +191,6 @@ ReturnValue_t RwPollingTask::writeAndReadAllRws(DeviceCommandId_t id) {
}
closeSpi(fd);
usleep(rws::SPI_REPLY_DELAY);
return readAllRws(id);
}
@ -208,50 +210,39 @@ ReturnValue_t RwPollingTask::readNextReply(RwCookie& rwCookie, uint8_t* replyBuf
int fd = 0;
gpioId_t gpioId = rwCookie.getChipSelectPin();
uint8_t byteRead = 0;
bool exitOuter = false;
for (unsigned retryIdx = 0; retryIdx < MAX_RETRIES_REPLY; retryIdx++) {
/**
* The reaction wheel responds with empty frames while preparing the reply data.
* However, receiving more than 5 empty frames will be interpreted as an error.
*/
for (int idx = 0; idx < 5; idx++) {
result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
return result;
}
pullCsLow(gpioId, gpioIF);
if (read(fd, &byteRead, 1) != 1) {
sif::error << "RwPollingTask: Read failed. " << strerror(errno) << std::endl;
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
return rws::SPI_READ_FAILURE;
}
if (idx == 0) {
if (byteRead != rws::FRAME_DELIMITER) {
sif::error << "Invalid data, expected start marker, got " << (int)byteRead << std::endl;
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
return rws::NO_START_MARKER;
}
}
if (byteRead != rws::FRAME_DELIMITER) {
exitOuter = true;
break;
}
result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
return result;
}
pullCsLow(gpioId, gpioIF);
bool lastByteWasFrameMarker = false;
Countdown cd(3000);
size_t readIdx = 0;
while (true) {
lastByteWasFrameMarker = false;
if (read(fd, &byteRead, 1) != 1) {
sif::error << "RwPollingTask: Read failed. " << strerror(errno) << std::endl;
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
if (idx == MAX_RETRIES_REPLY - 1) {
sif::error << "rwSpiCallback::spiCallback: Empty frame timeout" << std::endl;
return rws::NO_REPLY;
}
return rws::SPI_READ_FAILURE;
}
if(exitOuter) {
if (byteRead == rws::FRAME_DELIMITER) {
lastByteWasFrameMarker = true;
}
// Start of frame detected.
if (byteRead != rws::FRAME_DELIMITER and not lastByteWasFrameMarker) {
break;
}
TaskFactory::delayTask(5);
if (readIdx % 100 == 0 && cd.hasTimedOut()) {
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
return rws::SPI_READ_FAILURE;
}
readIdx++;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
sif::info << "RW start marker detected" << std::endl;
#endif
@ -339,13 +330,14 @@ ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) {
if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) {
continue;
}
if (spiLock == nullptr) {
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
return returnvalue::FAILED;
}
uint8_t* replyBuf;
size_t maxReadLen = idAndIdxToReadBuffer(id, idx, &replyBuf);
readNextReply(*rwCookies[idx], replyBuf, maxReadLen);
ReturnValue_t result = readNextReply(*rwCookies[idx], replyBuf + 1, maxReadLen);
if (result == returnvalue::OK) {
// The first byte is always a flag which shows whether the value was read
// properly at least once.
replyBuf[0] = true;
}
}
// SPI is closed in readNextReply as well.
return returnvalue::OK;
@ -440,6 +432,19 @@ void RwPollingTask::handleSpecialRequests() {
}
}
void RwPollingTask::setAllReadFlagsFalse() {
for (auto& rwCookie : rwCookies) {
RwReplies replies(rwCookie->replyBuf.data());
replies.getLastResetStatusReply[0] = false;
replies.clearLastResetStatusReply[0] = false;
replies.hkDataReply[0] = false;
replies.readTemperatureReply[0] = false;
replies.rwStatusReply[0] = false;
replies.setSpeedReply[0] = false;
replies.initRwControllerReply[0] = false;
}
}
// This closes the SPI
void RwPollingTask::closeSpi(int fd) {
// This will perform the function to close the SPI
@ -453,10 +458,10 @@ ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) {
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
return returnvalue::FAILED;
}
pullCsLow(gpioId, gpioIF);
// Add datalinklayer like specified in the datasheet.
size_t lenToSend = 0;
rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
pullCsLow(gpioId, gpioIF);
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
pullCsHigh(gpioId, gpioIF);
@ -513,7 +518,7 @@ ReturnValue_t RwPollingTask::prepareSetSpeedCmd(uint8_t rwIdx) {
speedToSet = rwCookies[rwIdx]->currentRwSpeed;
rampTimeToSet = rwCookies[rwIdx]->currentRampTime;
}
size_t serLen = 0;
size_t serLen = 1;
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),
SerializeIF::Endianness::LITTLE);
SerializeAdapter::serialize(&rampTimeToSet, &serPtr, &serLen, writeBuffer.size(),

View File

@ -80,6 +80,7 @@ class RwPollingTask : public SystemObject, public ExecutableObjectIF, public Dev
size_t idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** readPtr);
void fillSpecialRequestArray();
void setAllReadFlagsFalse();
void pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF);
void closeSpi(int);