I’m not sure where the right place to put this is, since the MaximInterface library doesn’t have an issue tracker here or on on Gitlab where it’s hosted. I’m looking for any guidance I can get.
Maxim has two libraries for its 1-wire ecosystem, the legacy OneWire library and MaximInterface which superseded it. Both contain abstractions which wrap their I2C masters to make communication with the 1-wire bus attached to the master transparent to the client code. Both libraries appear to be fairly straightforward users of Mbed’s I2C APIs, and both exhibit the following behavior where they behave as expected in mbed-os 5.14 and don’t in all of the 6.x versions.
I have a Nucleo F446RE attached to a DS2482-800 on IC23 (I have tried with IC21 as well). All eight 1-wire channels of the DS2482-800 have 1-wire devices attached to their bus. The rest of the environment is as follows:
Parameter | Value |
---|---|
Board | Nucleo F446RE |
Dev Environment | Manjaro Linux |
Compiler | GNU Arm Embedded Toolchain 9-2020-q2-update 9.3.1 20200408 |
Build Tools | mbed-cli and cmake |
Mbed OS Version | works on 5.15.4, fails on 6.0.0, 6.1.0, 6.2.0 |
The MaximInterface library works as-is when I tested it on 5.15.4, and will detect the 1-wire devices on their respective busses.
However, it won’t immediately compile on mbed-os 6+ because of its use of Serial
and wait_ms
. By simply removing the Uart
masters and replacing the depricated waits with thread_sleep_for
the library will compile in both 5.15.4 and all of the 6.x versions of mbed-os.
MaximInterface with the API fixes works in 5.15.4 the same as the unmodified version. However, when running in 6.0.0, 6.1.0, and 6.2.0 the bus reset fails with a “Nack Error”.
This is the basic test program for mbed-os 6.x based on the MaximInterface example with the additional channel selection for the DS2482-800. It’s slightly different than the 5.15 version because of BufferedSerial
.
#define SERIAL_SPEED 115200
#include "mbed.h"
#include <MaximInterfaceCore/HexString.hpp>
#include <MaximInterfaceCore/RomCommands.hpp>
#include <MaximInterfaceDevices/DS2482_DS2484.hpp>
#include <MaximInterfaceMbed/I2CMaster.hpp>
BufferedSerial serial(USBTX, USBRX);
I2C i2c_bus(PB_4, PA_8);
MaximInterfaceMbed::I2CMaster i2c_wrapper(i2c_bus);
MaximInterfaceDevices::DS2482_800 one_wire_master(i2c_wrapper, 0x30);
FileHandle *mbed::mbed_override_console(int fd) {
return &serial;
}
void DetectChannel(int channel) {
auto result = one_wire_master.initialize();
if (!result) {
printf("Failed to initialize DS2482-800: %s\r\n", result.error().message().c_str());
return;
}
result = one_wire_master.selectChannel(channel);
if (!result) {
printf("Failed to select channel %i: %s\r\n", channel, result.error().message().c_str());
return;
}
MaximInterfaceCore::SearchRomState search_state;
do {
result = MaximInterfaceCore::searchRom(one_wire_master, search_state);
if (!result) {
printf("Failed to find device: %s\r\n", result.error().message().c_str());
return;
}
printf("Ch %i Found ROM ID: %s\r\n", channel, MaximInterfaceCore::toHexString(search_state.romId).c_str());
} while (!search_state.lastDevice);
}
int main() {
serial.set_baud(SERIAL_SPEED);
printf("\r\n\r\nStarting 1-Wire Search Program\r\n");
uint tick_count = 0;
while (true)
{
printf(" > tick! %u\r\n", tick_count++);
for (int i = 0; i < 8; ++i) {
DetectChannel(i);
}
ThisThread::sleep_for(1000);
}
}
Some basic printf
debugging suggests that in mbed-os v6.x the failure occurs during the 1-wire bus reset, specifically in a function called pollBusy
where what seems to be a single byte read from the I2C bus sits in a polling loop. The second read attempt always fails, and the return value indicates a NACK error.
MaximInterface/MaximInterfaceDevices/DS2482_DS2484.cpp
Result<uint_least8_t> DS2482_DS2484::readRegister() const {
uint_least8_t buf;
TRY(master->readPacket(address_, make_span(&buf, 1), I2CMaster::Stop));
return buf;
}
Result<uint_least8_t> DS2482_DS2484::pollBusy() {
const int pollLimit = 200;
int pollCount = 0;
uint_least8_t status;
do {
TRY_VALUE(status, readRegister()); // Error seems to happen here on the second loop
if (pollCount++ >= pollLimit) {
return HardwareError;
}
} while ((status & status_1WB) == status_1WB);
return status;
}
Interestingly, the legacy OneWire library also seems to fail in the second single byte read in a polling loop as part of the 1-wire bus reset. Both libraries seem to be fairly simple users of the Mbed I2C object, so I’m at a loss for what might have changed between mbed-os 5.15 and 6.x.
Any insight, guidance, or general help is appreciated. I’m not quite sure what to do or try next.