Blank I2C output ESP32 simple program
Chip type: esp32 (revision v1.0)
Crystal frequency: 40MHz
Flash size: 4MB
Peripheral: MLX90614
VCC: 3V3
GND: GND
SDA: GPIO 21
SCL: GPIO 22
Thank you for the awesome library. I am having issues connecting a MLX90614 (on a breakout board with 4.7K pull-up resistors on sda and scl) to my ESP32.
I've been able to validate that the device works via the Ardunio IDE using this library and this program.
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
void setup() {
Serial.begin(115200);
while (!Serial);
if (!mlx.begin()) {
Serial.println("Error connecting to MLX sensor. Check wiring.");
while (1);
};
}
void loop() {
Serial.print("Ambient temperature = ");
Serial.print(mlx.readAmbientTempC());
Serial.print("°C");
Serial.print(" ");
Serial.print("Object temperature = ");
Serial.print(mlx.readObjectTempC());
Serial.println("°C");
Serial.println("-----------------------------------------------------------------");
delay(500);
}
However I cannot seem to get a useful response when trying to communicate with the I2C bus via esp-hal
I've tried to manually write_read at the address 0x5A and always get a response of [ff, ff, ff].
Additionally I've attempted to scan for all I2C devices and send all 1 byte messages and always get a response of [00, 00, 00] or [ff, ff, ff]. Please see the example code below.
I am an embedded newbie so its very likely I'm doing something (or everything) completely wrong. Is there a better/correct way to read data from an I2C bus?
#![no_std]
#![no_main]
use esp32_hal::{
clock::{ClockControl, Clocks},
entry,
gpio::{Gpio6, GpioPin, Output, PushPull, Unknown, IO},
i2c::I2C,
interrupt,
peripherals::{Peripherals, I2C0, I2C1, RTC_I2C},
prelude::*,
Delay,
};
use esp_backtrace as _;
use esp_println::println;
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let sda = io.pins.gpio21;
let scl = io.pins.gpio22;
let mut i2c = I2C::new(peripherals.I2C0, sda, scl, 100u32.kHz(), &clocks);
for addr in 0..=127 {
if let Ok(_) = i2c.write(addr, &[0x07]) {
println!("Found device at address: 0x{:02X}", addr);
for msg in 0..=255 {
let to_send: [u8; 1] = [msg];
let mut data = [0u8; 3];
i2c.write_read(addr, &to_send, &mut data).ok();
println!("Sent: 0x{:02X}, Received: {:02x?}", msg, data);
}
}
}
loop {}
}
Code looks fine. Worth to try is using the pins we use in the examples (32,33). If that changes things for you it's probably a bug on our side (since 21,22 are the default pins, they should also work)
If that doesn't work you might want to use a logic analyzer (for the clock speeds of I2C a very cheap one is more than enough) and see what is happening on the wires
@bjoernQ I'm also experiencing issues with I2C async version. After running a simple task for a few minutes by reading out the humidity and temp. from the Rust ESP32-C3 board I start getting ack. checks errors:
Combined: 27.001 °C / 77.862 %RH
Combined: 26.94 °C / 77.856 %RH
Combined: 26.98 °C / 77.891 %RH
Combined: 26.972 °C / 77.868 %RH
Combined: 26.969 °C / 77.871 %RH
Combined: 27.001 °C / 77.862 %RH
Combined: 26.988 °C / 77.865 %RH
Combined: 26.98 °C / 77.853 %RH
Combined: 26.969 °C / 77.864 %RH
Combined: 26.961 °C / 77.87 %RH
Combined: 26.988 °C / 77.885 %RH
Combined: 26.972 °C / 77.836 %RH
Combined: 26.98 °C / 77.873 %RH
Combined: 27.001 °C / 77.882 %RH
Combined: 26.969 °C / 77.851 %RH
Combined: 26.969 °C / 77.915 %RH
Combined: 26.969 °C / 77.861 %RH
Combined: 26.996 °C / 77.891 %RH
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
I've experiening issues with the IMU I2Csensor as well, though I'm not sure if it's only the esp-hal impl or a driver crate bug included in there, see PR #862
Thanks! Oh, I somehow missed #862 - need to look into that
Thanks! There's definitely something broken in I2C but I'm far from my equipment so can't provide you with further info.
@bjoernQ I've acquired a logic analyzer and got it working with saleae's Logic2 however I'm not 100% sure what I should be looking for 😅
I've written a simple program to request the IR data every second and then attached the logic analyzer to the SDA and SCL pins. Please see the schematic, screenshot and code below.
Schematic
This is how I've wired the analyzer to the circuit (I had to add a diode in order for the circuit to run... not sure if this can cause any issues).
graph TD;
subgraph ESP32
GPIO21
GPIO22
GND_ESP
3V3
end
GPIO21 --- SDA
GPIO22 --- SCL
GND_ESP --- GND_MLX
3V3 --- VCC
subgraph MLX90614
SDA
SCL
GND_MLX
VCC
end
GND_MLX --- GND_LOGIC
SDA --- CH0
SCL --- DIODE_1N4148 --- CH1
subgraph DIODE_1N4148
end
subgraph LOGIC_ANALYZER
GND_LOGIC
CH0
CH1
end
Logic Analyzer Capture
I can see some communication on the wires but am not sure what a correct/incorrect patterns looks like
Program
#![no_std]
#![no_main]
use esp32_hal::{
clock::ClockControl, entry, gpio::IO, i2c::I2C, peripherals::Peripherals, prelude::*, Delay,
};
use esp_backtrace as _;
use esp_println::println;
#[entry]
fn main() -> ! {
// Initialize peripherals
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
// Initialize I2C specific pins
let sda = io.pins.gpio21;
let scl = io.pins.gpio22;
// Open I2C0
let mut i2c = I2C::new(peripherals.I2C0, sda, scl, 100u32.kHz(), &clocks);
// Delay configuration
let mut delay = Delay::new(&clocks);
println!("Scanning for devices...");
// Scan for devices
if let Ok(_) = i2c.write(0x5A, &[0x07]) {
// 0x04 is the command to read the raw sensor data
let to_send: [u8; 1] = [0x04];
loop {
let mut data = [0u8; 3];
i2c.write_read(0x5A, &to_send, &mut data).ok();
println!("Sent: 0x{:02X}, Received: {:02x?}", 0x00, data);
delay.delay_ms(1000u32);
}
}
loop {}
}
Thank you for the help 🙏
Great you got a logic analyzer. Will definitely be helpful in the future. Seems like for whatever reason the clock signal looks "interesting".
The Saleae software also contains a protocol decoder which you could use to make more sense of the signals but, in this case, SCL already looks suspicious. SDA looks good.
Would be good if you could use different pin (32 or 33) as SDA and compare what the logic analyzer captures
As I mentioned in https://github.com/esp-rs/esp-hal/pull/862, it's possible to simulate similar problem, by connecting ungrounded wire to PIN 8, or by touching the board.
It seems that I2C clocks are simply thrown out of balance.
Workaround: Decrease frequency of I2C to 2 kHz.
Possible suspect 1
https://github.com/esp-rs/esp-hal/blob/6005f9256625e7a83d37464bf2b5dea5feab6392/esp-hal-common/src/i2c.rs#L1498-L1515
icm42670 crate example
It's used both in async and current block Api for the crate:
/// Read a register at the provided address.
async fn read_reg_async(&mut self, reg: &dyn Register) -> Result<u8, Error<I2C::Error>> {
let mut buffer = [0u8];
self.i2c
.write_read(self.address as u8, &[reg.addr()], &mut buffer)
.await
.map_err(|e| Error::BusError(e))?;
Ok(buffer[0])
}
Will try with lowered frequency next
at 2 kz
With a breadboard
Without a breadboard
I'm investigating this issue on the Rust board.
Hello guys,
I can reproduce it in different ways and the initial conclusion is the bus trace capacitance is too high. The main reason for that is the trace length on both lines (SCL and SDA) and the trace path.
As you can see here, the SCL (400kHz) signal is far from the ideal with the 10k resistor:
Then I tested with 5k1 resistors and this is the result:
With the 5k1 resistor, I2C SCL @ 400kHz looks better and the issue is almost gone.
IMO, we need to fix the capacitance issue by removing the second GPIO8 pin on the left side, keeping the one on the right for the Feather pinout compatibility retracing both signals. The pullup resistor should be around 3k-5k.
For now, to reduce the I2C issue, you can change the 0402 pullups or add an external resistor 10k in parallel (current value is 10k) then you will have a 5k pullup, or reduce the clock on the I2C.
I'll start working on the hardware fix ASAP.
Thank you everyones help!
After much trial and error I was able to capture better samples of the i2c communication.
I believe the issue is related to the master_write_read method implementation. It appears that the write_read is implemented as two transactions rather than a single transaction (as seen in source and mentioned in the comment).
https://github.com/esp-rs/esp-hal/blob/ece40abaed0e642b751a8752ce6406740efa4af6/esp-hal-common/src/i2c.rs#L1496-L1512
Working Example Capture
Looking at a capture of working cpp code we can see the communication is:
The write:
START - ADDRESS - DATA
then without a STOP the read is
START - ADDRESS - DATA - DATA - DATA - STOP
for completeness the full command flow is
START - ADDRESS - DATA - START - ADDRESS - DATA - DATA - DATA - STOP
esp-rs Example Capture
The esp-rs implementation has two instances of STOP when trying to write_read
The full command flow
START - ADDRESS - DATA - STOP - START - ADDRESS - DATA - DATA - DATA - STOP
also its worth noting that there is a significant amount of time between the write and read while in the working example the read immediately follows.
I'm not sure if this is the exact issue however it seems to be the major difference between the working example and this i2c impl.
Again, I am new to embedded so please let me know if this makes sense, or if I am on the wrong track 🙏
**I attempted to craft a working command flow by removing the Stop command in setup_write but don't have enough domain knowledge to make the changes needed..
Thank you!
I've also gave it a stab @drbh - https://github.com/esp-rs/esp-hal/pull/979
I've also gave it a stab @drbh - #979
awesome thank you! I just pulled it down and got similar results. However it appears that you're changes are for async i2c and I am currently not using embassy which I believe is needed for async?
Do you know if these changes will work in the sync case? Also quick note but it appears there is still a STOP command emitted as part of the write. My impressions was that a transaction has a single STOP so this does not reduce the two transactions into one...
I haven't tested my implementation but decided to share it because you commented on the issue.
And no I don't believe you can do this in the blocking version. In async you can wait for two futures too complete in parallel.
@elpiel got it, thank you for sharing I really appreciate the information and am going to use the code to help debug the issue further 🙏
@drbh the time between write and read seem to be huge. Are you running in release mode?
This is how it looks like for me (other i2c device so it looks different)
Maybe the MLX90614 just doesn't like the long pause between write and read
Is this resolved? Can we close this issue?
@bjoernQ unfortunately I still cannot read data from the MLX90614, you were right I was originally compiling in debug. Building release did improve the timing (shown below) but I still get a response of [ff, ff, ff]
The only difference between the arduino and rust logic output seems to be the number of transactions sent over the bus. I believe this is due to master_write_read being implemented as two transaction rather than one (note the example below has one more stop frame than the cpp example).
It may make sense to close this issue since I cannot confirm that the issue is related to master_write_read and this issue has been open for a long time.
Thanks for all of the help!
I think I am experiencing the same, or very similar issue. Please let me know if I should open another issue elsewhere. I am using different boards (esp32-s3 and esp32-c6 DevKitC-1) targeting a different I2C device (Adafruit Atecc608A, not that it seems to matter yet at this point) though. When I try a slightly adapted version of @drbh s code (chip has a config zone that can be locked, don't wont to write random commands and ruin the chip), the program gets stuck after 2 iterations of the for loop:
#![no_std]
#![no_main]
use esp32s3_hal::{clock::ClockControl, prelude::*, timer::TimerGroup, Delay, IO};
use esp_backtrace as _;
use esp_println::println;
use esp32s3_hal::i2c::I2C;
#[entry]
fn main() -> ! {
esp_println::logger::init_logger(log::LevelFilter::Info);
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
// Set up SCL & SDA
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let scl = io.pins.gpio1;
let sda = io.pins.gpio2;
// Construct I2C
let mut i2c = I2C::new(peripherals.I2C0, scl, sda, 100u32.kHz(), &clocks);
let mut delay = Delay::new(&clocks);
for addr in 0..=127 {
println!("Scanning Address {}", addr as u8);
// Scan Address
let res = i2c.read(addr as u8, &mut [0]);
// Check and Print Result
match res {
Ok(_) => println!("Device Found at Address {}", addr as u8),
Err(err) => println!("No Device Found: {:?}", err),
}
}
loop {
println!("Loop...");
delay.delay_ms(500u32);
}
}
Output of stuck program:
Scanning Address 0
No Device Found: AckCheckFailed
Scanning Address 1
No Device Found: AckCheckFailed
Scanning Address 2
I expected that it would run through the for-loop and get back with one device found. I didn't expect the reads to get hung up in any case.
I tried
- with and without I2C device connected, same results
- with different versions of esp32s3_hal (0.14.0, 0.15.0, current main branch), same results
- on esp32s3 and esp32c6 boards
- with and without breadboard (not touching it), same results
- using different gpio pins (bunch of randoms, 1 & 2), same results
- starting the for loop at different addresses, same results
- repeatedly writing
0x00at address0x60which is supposed to make the chip wake up and have it respond with some data. Same result at the read (writes don't come through either) - setting
lto = "off"in my cargo.toml results in my for loop getting stuck one iteration earlier - using 50kHz I2C clock speed, it runs one iteration of the for loop less before it gets hung up
- using 2kHz or 400kHz the loop runs through, however, I am only seeing
AckCheckFailedon all addresses including the one where I am expecting the device according to it's specs (0x60), also my original problem persists :(
(I am new to embedded, I hope this counts as minimal example, my original goal is to get this library supported on my hardware but when trying to wake up the chip, the program either get's stuck or fails here https://github.com/BlackbirdHQ/at-cryptoauth-rs/blob/46db006c2da43e82bba4508e79e9db41bf84ce94/src/datalink.rs#L122)
I think I am experiencing the same, or very similar issue. Please let me know if I should open another issue elsewhere. I am using different boards (esp32-s3 and esp32-c6 DevKitC-1) targeting a different I2C device (Adafruit Atecc608A, not that it seems to matter yet at this point) though. When I try a slightly adapted version of @drbh s code (chip has a config zone that can be locked, don't wont to write random commands and ruin the chip), the program gets stuck after 2 iterations of the for loop:
#![no_std] #![no_main] use esp32s3_hal::{clock::ClockControl, prelude::*, timer::TimerGroup, Delay, IO}; use esp_backtrace as _; use esp_println::println; use esp32s3_hal::i2c::I2C; #[entry] fn main() -> ! { esp_println::logger::init_logger(log::LevelFilter::Info); let peripherals = Peripherals::take(); let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); // Set up SCL & SDA let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let scl = io.pins.gpio1; let sda = io.pins.gpio2; // Construct I2C let mut i2c = I2C::new(peripherals.I2C0, scl, sda, 100u32.kHz(), &clocks); let mut delay = Delay::new(&clocks); for addr in 0..=127 { println!("Scanning Address {}", addr as u8); // Scan Address let res = i2c.read(addr as u8, &mut [0]); // Check and Print Result match res { Ok(_) => println!("Device Found at Address {}", addr as u8), Err(err) => println!("No Device Found: {:?}", err), } } loop { println!("Loop..."); delay.delay_ms(500u32); } }Output of stuck program:
Scanning Address 0 No Device Found: AckCheckFailed Scanning Address 1 No Device Found: AckCheckFailed Scanning Address 2I expected that it would run through the for-loop and get back with one device found. I didn't expect the reads to get hung up in any case.
I tried
- with and without I2C device connected, same results
- with different versions of esp32s3_hal (0.14.0, 0.15.0, current main branch), same results
- on esp32s3 and esp32c6 boards
- with and without breadboard (not touching it), same results
- using different gpio pins (bunch of randoms, 1 & 2), same results
- starting the for loop at different addresses, same results
- repeatedly writing
0x00at address0x60which is supposed to make the chip wake up and have it respond with some data. Same result at the read (writes don't come through either)- setting
lto = "off"in my cargo.toml results in my for loop getting stuck one iteration earlier- using 50kHz I2C clock speed, it runs one iteration of the for loop less before it gets hung up
- using 2kHz or 400kHz the loop runs through, however, I am only seeing
AckCheckFailedon all addresses including the one where I am expecting the device according to it's specs (0x60), also my original problem persists :((I am new to embedded, I hope this counts as minimal example, my original goal is to get this library supported on my hardware but when trying to wake up the chip, the program either get's stuck or fails here https://github.com/BlackbirdHQ/at-cryptoauth-rs/blob/46db006c2da43e82bba4508e79e9db41bf84ce94/src/datalink.rs#L122)
This doesn't seem to be related to the issue here and probably it's better to create a separate issue for it
This issue has grown stale, and I'm not sure there's anything actionable here, so gonna go ahead and close this. Everybody involved, please feel free to open a new issue if you are still experiencing any problems.