meier/pdec #110
@ -17,7 +17,8 @@ static constexpr char UART_GNSS_0_DEV[] = "/dev/ttyUL0";
|
||||
static constexpr char UART_GNSS_1_DEV[] = "/dev/ttyUL2";
|
||||
|
||||
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0";
|
||||
static constexpr char UIO_PDEC_MEMORY[] = "/dev/uio2";
|
||||
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2";
|
||||
static constexpr char UIO_PDEC_RAM[] = "/dev/uio3";
|
||||
|
||||
namespace gpioNames {
|
||||
static constexpr char GYRO_0_ADIS_CS[] = "gyro_0_adis_chip_select";
|
||||
|
@ -961,7 +961,8 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF *gpioComIF) {
|
||||
gpioComIF->addGpios(gpioCookiePdec);
|
||||
|
||||
new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET,
|
||||
std::string(q7s::UIO_PDEC_MEMORY), std::string(q7s::UIO_PDEC_REGISTERS));
|
||||
std::string(q7s::UIO_PDEC_CONFIG_MEMORY), std::string(q7s::UIO_PDEC_RAM),
|
||||
std::string(q7s::UIO_PDEC_REGISTERS));
|
||||
|
||||
#if BOARD_TE0720 == 0
|
||||
GpioCookie* gpioRS485Chip = new GpioCookie;
|
||||
|
@ -22,6 +22,9 @@ void PdecConfig::initialize() {
|
||||
configWords[0] = word;
|
||||
word = 0;
|
||||
word |= (NEGATIVE_WINDOW << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
configWords[1] = word;
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::getConfigWord(uint8_t wordNo) {
|
||||
|
@ -39,6 +39,8 @@ private:
|
||||
// Set here for future use
|
||||
static const uint8_t POSITIVE_WINDOW = 10;
|
||||
static const uint8_t NEGATIVE_WINDOW = 151;
|
||||
static const uint8_t HIGH_AU_MAP_ID = 0xF;
|
||||
static const uint8_t ENABLE_DERANDOMIZER = 1;
|
||||
|
||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
@ -10,10 +11,11 @@
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioMemory,
|
||||
std::string uioRegisters) :
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
|
||||
std::string uioRamMemory, std::string uioRegisters) :
|
||||
SystemObject(objectId), tcDestinationId(tcDestinationId), gpioComIF(gpioComIF), pdecReset(
|
||||
pdecReset), uioMemory(uioMemory), uioRegisters(uioRegisters) {
|
||||
pdecReset), uioConfigMemory(uioConfigMemory), uioRamMemory(uioRamMemory), uioRegisters(
|
||||
uioRegisters) {
|
||||
|
||||
}
|
||||
|
||||
@ -43,7 +45,12 @@ ReturnValue_t PdecHandler::initialize() {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = getMemoryBaseAddress();
|
||||
result = getConfigMemoryBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = getRamBaseAddress();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
@ -76,45 +83,62 @@ ReturnValue_t PdecHandler::getRegisterAddress() {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::getMemoryBaseAddress() {
|
||||
int fd = open(uioMemory.c_str(), O_RDWR);
|
||||
ReturnValue_t PdecHandler::getConfigMemoryBaseAddress() {
|
||||
int fd = open(uioConfigMemory.c_str(), O_RDWR);
|
||||
if (fd < 1) {
|
||||
sif::warning << "PdecHandler::getMemoryBaseAddress: Invalid UIO device file" << std::endl;
|
||||
sif::warning << "PdecHandler::getConfigMemoryBaseAddress: Invalid UIO device file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
memoryBaseAddress = static_cast<uint32_t*>(mmap(NULL, MEMORY_MAP_SIZE, PROT_WRITE | PROT_READ,
|
||||
memoryBaseAddress = static_cast<uint32_t*>(mmap(NULL, CONFIG_MEMORY_MAP_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, fd, 0));
|
||||
|
||||
if (memoryBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getMemoryBaseAddress: Failed to map uio address" << std::endl;
|
||||
sif::error << "PdecHandler::getConfigMemoryBaseAddress: Failed to map uio address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::getRamBaseAddress() {
|
||||
int fd = open(uioRamMemory.c_str(), O_RDWR);
|
||||
|
||||
ramBaseAddress = static_cast<uint32_t*>(mmap(NULL, RAM_MAP_SIZE, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, fd, 0));
|
||||
|
||||
if (ramBaseAddress == MAP_FAILED) {
|
||||
sif::error << "PdecHandler::getRamBaseAddress: Failed to map RAM base address" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PdecHandler::writePdecConfig() {
|
||||
|
||||
PdecConfig pdecConfig;
|
||||
|
||||
*memoryBaseAddress = pdecConfig.getConfigWord(0);
|
||||
*(memoryBaseAddress + 1) = pdecConfig.getConfigWord(1);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET)= pdecConfig.getConfigWord(0);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
||||
|
||||
// uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
// Configure all MAP IDs as invalid
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) = NO_DESTINATION << 24
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx + 1 / 4) = NO_DESTINATION << 24
|
||||
| NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
|
||||
// *(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) = routeToPm << 24
|
||||
// | routeToPm << 16 | routeToPm << 8 | routeToPm;
|
||||
|
||||
}
|
||||
|
||||
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
|
||||
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
*(memoryBaseAddress + 1) = NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) = (NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8)
|
||||
| routeToPm;
|
||||
|
||||
// Write map id clock frequencies
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) = MAP_CLK_FREQ << 24
|
||||
| MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
||||
@ -173,9 +197,6 @@ ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
||||
bool PdecHandler::newTcReceived() {
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
|
||||
sif::debug << "PdecHandler::newTcReceived: pdecFar 0x" << std::hex
|
||||
<< static_cast<unsigned int>(pdecFar) << std::endl;
|
||||
|
||||
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
||||
return false;
|
||||
}
|
||||
@ -303,11 +324,12 @@ void PdecHandler::handleNewTc() {
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC == 1
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
unsigned int mapId = tcSegment[0] & MAP_ID_MASK;
|
||||
sif::debug << "PdecHandler::handleNewTc: Received TC segment with map ID" << mapId
|
||||
<< std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC */
|
||||
printTC(tcLength);
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
store_address_t storeId;
|
||||
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
||||
@ -331,18 +353,17 @@ void PdecHandler::handleNewTc() {
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
uint32_t tcOffset = *(registerBaseAddress + PDEC_BPTR_OFFSET) - PHYSICAL_BASE_ADDRESS;
|
||||
uint32_t tcOffset = (*(registerBaseAddress + PDEC_BPTR_OFFSET) - PHYSICAL_RAM_BASE_ADDRESS) / 4;
|
||||
|
||||
#if OBSW_DEBUG_PDEC == 1
|
||||
sif::debug << "PdecHandler::readTc: TC offset: " << std::hex << tcOffset << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC */
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::readTc: TC offset: 0x" << std::hex << tcOffset << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
uint32_t* tcPtr = reinterpret_cast<uint32_t*>(*(registerBaseAddress + tcOffset) / 4);
|
||||
tcLength = *(registerBaseAddress + PDEC_SLEN_OFFSET);
|
||||
|
||||
#if OBSW_DEBUG_PDEC == 1
|
||||
sif::debug << "PdecHandler::readTc: TC length: " << tcLength << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC */
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::readTc: TC segment length: " << std::dec << tcLength << std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
if (tcLength > MAX_TC_SEGMENT_SIZE) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Read invalid TC length from PDEC register"
|
||||
@ -352,9 +373,31 @@ ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
|
||||
uint32_t idx = 0;
|
||||
uint32_t tcData = 0;
|
||||
for (idx = 0; idx < tcLength; idx = idx + 4) {
|
||||
tcData = *(tcPtr + idx);
|
||||
std::memcpy(tcSegment + idx, &tcData, sizeof(tcData));
|
||||
for (idx = 0; idx <= tcLength; idx = idx + 4) {
|
||||
tcData = *(ramBaseAddress + tcOffset + idx / 4);
|
||||
if (idx == 0) {
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 3) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 2) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
else if (tcLength - idx + 1 == 1) {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
else {
|
||||
tcSegment[idx - 1] = static_cast<uint8_t>((tcData >> 24) & 0xFF);
|
||||
tcSegment[idx] = static_cast<uint8_t>((tcData >> 16) & 0xFF);
|
||||
tcSegment[idx + 1] = static_cast<uint8_t>((tcData >> 8) & 0xFF);
|
||||
tcSegment[idx + 2] = static_cast<uint8_t>(tcData & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
// Backend buffer is handled back to PDEC3
|
||||
@ -363,6 +406,16 @@ ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PdecHandler::printTC(uint32_t tcLength) {
|
||||
std::stringstream tcSegmentStream;
|
||||
|
||||
tcSegmentStream << "TC segment data: 0x";
|
||||
for (uint32_t idx = 0; idx < tcLength; idx++) {
|
||||
tcSegmentStream << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< static_cast<unsigned int>(tcSegment[idx]);
|
||||
}
|
||||
sif::debug << tcSegmentStream.str() << std::endl;
|
||||
}
|
||||
|
||||
uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) {
|
||||
uint8_t lutEntry = 0;
|
||||
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
|
||||
|
@ -37,11 +37,12 @@ public:
|
||||
* @param tcDestinationId Object ID of object responsible for processing TCs.
|
||||
* @param gpioComIF Pointer to GPIO interace responsible for driving GPIOs.
|
||||
* @param pdecReset GPIO ID of GPIO connected to the reset signal of the PDEC.
|
||||
* @param uioMemory String of uio device file same mapped to the PDEC memory space
|
||||
* @param uioConfigMemory String of uio device file same mapped to the PDEC memory space
|
||||
* @param uioregsiters String of uio device file same mapped to the PDEC register space
|
||||
*/
|
||||
PdecHandler(object_id_t objectId, object_id_t tcDestinationId, LinuxLibgpioIF* gpioComIF,
|
||||
gpioId_t pdecReset, std::string uioMemory, std::string uioRegisters);
|
||||
gpioId_t pdecReset, std::string uioConfigMemory, std::string uioRamMemory,
|
||||
std::string uioRegisters);
|
||||
|
||||
virtual ~PdecHandler();
|
||||
|
||||
@ -104,14 +105,19 @@ private:
|
||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||
|
||||
static const int MEMORY_MAP_SIZE = 0xF42400;
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
static const int REGISTER_MAP_SIZE = 0x10000;
|
||||
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
|
||||
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
|
||||
static const uint8_t MAP_ID_MASK = 0x3F;
|
||||
|
||||
static const uint32_t PHYSICAL_BASE_ADDRESS = 0x30000000;
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x32000000;
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
|
||||
static const uint8_t MAX_MAP_ADDR = 63;
|
||||
// Writing this to the map address in the look up table will invalidate a MAP ID.
|
||||
@ -122,11 +128,17 @@ private:
|
||||
// Expected value stored in FAR register after reset
|
||||
static const uint32_t FAR_RESET = 0x7FE0;
|
||||
|
||||
static const uint32_t TC_SEGMENT_LEN = 1017;
|
||||
|
||||
/**
|
||||
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
|
||||
* the PDEC memory.
|
||||
*/
|
||||
static const uint32_t PM_BUFFER = 7;
|
||||
static const uint8_t PM_BUFFER = 7;
|
||||
|
||||
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
|
||||
// discarded
|
||||
static const uint8_t MAP_CLK_FREQ = 2;
|
||||
|
||||
enum class FrameAna_t: uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
@ -166,7 +178,14 @@ private:
|
||||
* @brief Opens UIO device assigned to the base address of the PDEC memory space and maps the
|
||||
* physical address into the virtual address space.
|
||||
*/
|
||||
ReturnValue_t getMemoryBaseAddress();
|
||||
ReturnValue_t getConfigMemoryBaseAddress();
|
||||
|
||||
/**
|
||||
* @brief Opens UIO device assigned to the RAM section of the PDEC IP core memory map.
|
||||
*
|
||||
* @details A received TC segment will be written to this memory area.
|
||||
*/
|
||||
ReturnValue_t getRamBaseAddress();
|
||||
|
||||
/**
|
||||
* @brief This functions writes the configuration parameters to the configuration
|
||||
@ -225,6 +244,11 @@ private:
|
||||
*/
|
||||
ReturnValue_t readTc(uint32_t& tcLength);
|
||||
|
||||
/**
|
||||
* @brief Prints the tc segment data
|
||||
*/
|
||||
void printTC(uint32_t tcLength);
|
||||
|
||||
/**
|
||||
* @brief This function calculates the entry for the configuration of the MAP ID routing.
|
||||
*
|
||||
@ -259,8 +283,11 @@ private:
|
||||
*/
|
||||
gpioId_t pdecReset = gpio::NO_GPIO;
|
||||
|
||||
// UIO device file giving access to the PDEC memory space
|
||||
std::string uioMemory;
|
||||
// UIO device file giving access to the PDEC configuration memory section
|
||||
std::string uioConfigMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC RAM section
|
||||
std::string uioRamMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC register space
|
||||
std::string uioRegisters;
|
||||
@ -276,12 +303,14 @@ private:
|
||||
*/
|
||||
uint32_t* memoryBaseAddress = nullptr;
|
||||
|
||||
uint32_t* ramBaseAddress = nullptr;
|
||||
|
||||
// Pointer pointing to base address of register space
|
||||
uint32_t* registerBaseAddress = nullptr;
|
||||
|
||||
uint32_t pdecFar = 0;
|
||||
|
||||
uint8_t tcSegment[1017];
|
||||
uint8_t tcSegment[TC_SEGMENT_LEN];
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user
Maybe we can use arrayprinter::print() from
globalfunctions
here?Yes, we can also use the array printer function for this,