1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

verify more assumptions in i2c

add selftest to I2c and readback Dino configuration to verify it was
actually set

Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
Niklas Eiling 2024-01-09 13:22:34 +01:00 committed by Niklas Eiling
parent 335dd2c0ce
commit 60c65c2880
3 changed files with 56 additions and 6 deletions

View file

@ -43,9 +43,10 @@ public:
class Switch {
public:
Switch(I2c *i2c, uint8_t address)
: i2c(i2c), address(address), channel(0), readOnce(false),
switchLock(){};
Switch(I2c *i2c, uint8_t address,
Logger logger = villas::logging.get("i2c"))
: i2c(i2c), address(address), channel(0), readOnce(false), switchLock(),
logger(logger){};
Switch(const Switch &other) = delete;
Switch &operator=(const Switch &other) = delete;
void setChannel(uint8_t channel);
@ -57,6 +58,7 @@ public:
uint8_t getChannel();
void setAddress(uint8_t address) { this->address = address; }
uint8_t getAddress() { return address; }
bool selfTest();
private:
I2c *i2c;
@ -64,10 +66,11 @@ public:
uint8_t channel;
bool readOnce;
std::mutex switchLock;
Logger logger;
};
Switch &getSwitch(uint8_t address = I2C_SWTICH_ADDR) {
if (switchInstance == nullptr) {
switchInstance = std::make_unique<Switch>(this, address);
switchInstance = std::make_unique<Switch>(this, address, logger);
} else {
switchInstance->setAddress(address);
}

View file

@ -87,6 +87,12 @@ void DinoAdc::configureHardware() {
IoextPorts ioext = {.raw = 0};
ioext.fields.sat_detect = true;
setIoextDir(ioext);
auto readback = getIoextDir();
if (readback.raw != ioext.raw) {
logger->error("Ioext direction register readback incorrect: {:#x} != {:#x}",
readback.raw, ioext.raw);
throw RuntimeError("Failed to set IOEXT direction register");
}
ioext.raw = 0;
ioext.fields.data_dir = true;
ioext.fields.status_led = true;
@ -95,6 +101,12 @@ void DinoAdc::configureHardware() {
setIoextOut(ioext);
ioext.fields.n_we = false;
setIoextOut(ioext);
readback = getIoextOut();
if (readback.raw != ioext.raw) {
logger->error("Ioext output register readback incorrect: {:#x} != {:#x}",
readback.raw, ioext.raw);
throw RuntimeError("Failed to set IOEXT output register");
}
i2cdev->getSwitch().unlockChannel();
}
@ -109,10 +121,24 @@ void DinoDac::configureHardware() {
i2cdev->getSwitch().setAndLockChannel(i2c_channel);
IoextPorts ioext = {.raw = 0};
setIoextDir(ioext);
auto readback = getIoextDir();
if (readback.raw != ioext.raw) {
logger->error("Ioext direction register readback incorrect: {:#x} != {:#x}",
readback.raw, ioext.raw);
throw RuntimeError("Failed to set IOEXT direction register");
}
ioext.fields.status_led = true;
// Default gain is 1. Although not really necessary, let's be explicit here
ioext.fields.gain_lsb = 0x00 & 0x1;
ioext.fields.gain_msb = 0x00 & 0x2;
setIoextOut(ioext);
readback = getIoextOut();
if (readback.raw != ioext.raw) {
logger->error("Ioext output register readback incorrect: {:#x} != {:#x}",
readback.raw, ioext.raw);
throw RuntimeError("Failed to set IOEXT output register");
}
i2cdev->getSwitch().unlockChannel();
setGain(GAIN_1);
}
void DinoDac::setGain(Gain gain) {

View file

@ -12,6 +12,7 @@
#include <villas/fpga/ips/i2c.hpp>
#include <villas/fpga/ips/intc.hpp>
#include <villas/log.hpp>
using namespace villas::fpga::ip;
@ -220,7 +221,7 @@ void I2c::Switch::setChannel(uint8_t channel) {
}
uint8_t I2c::Switch::getChannel() {
std::vector<u8> data(1);
std::vector<u8> data;
int retries = 10;
do {
i2c->read(address, data, 1);
@ -242,6 +243,26 @@ uint8_t I2c::Switch::getChannel() {
return channel;
}
bool I2c::Switch::selfTest() {
uint8_t readback;
logger->debug("I2c::Switch self test. Testing {} channels of device {:#x}",
sizeof(CHANNEL_MAP) / sizeof(CHANNEL_MAP[0]), address);
for (size_t i = 0; i < sizeof(CHANNEL_MAP) / sizeof(CHANNEL_MAP[0]); ++i) {
logger->debug("Setting switch to channel {}, data byte {:#x}", i,
CHANNEL_MAP[i]);
setAndLockChannel(i);
try {
readback = getChannel();
logger->debug("Readback channel: {}", readback);
} catch (const RuntimeError &e) {
logger->debug("Encoutered error on readback: {}", e.what());
return false;
}
unlockChannel();
}
return true;
}
void I2cFactory::parse(Core &ip, json_t *cfg) {
NodeFactory::parse(ip, cfg);