Hey everybody, I am having issues running my Nucleo-L476RG as an I2C Slave
I found this example code using the I2CSlave class as a part of Mbed OS
#include <mbed.h>
#include "SerialStream.h"
int main()
{
I2CSlave slave(SDA, SCL);
slave.address(addr << 1); //keep actual address
BufferedSerial serial(USBTX, USBRX, 115200);
SerialStream<BufferedSerial> pc(serial);
pc.printf("I2C confiigured on 0x%X\n", addr);
char buf[10];
char msg[] = "Slave!";
while (1) {
int i = slave.receive();
switch (i) {
case I2CSlave::ReadAddressed: {
int res = slave.write(msg, strlen(msg) + 1); // Includes null char
pc.printf("wrote msg %d\n", res);
break;
}
case I2CSlave::WriteGeneral:
slave.read(buf, 10);
pc.printf("Read G: %s\n", buf);
break;
case I2CSlave::WriteAddressed:
slave.read(buf, 10);
pc.printf("Read A: %s\n", buf);
break;
}
for (int i = 0; i < 10; i++) {
buf[i] = 0; // Clear buffer
}
}
}
and I am attempting to interface with the board using a raspberry-pi 4 running the following Rust program
use rppal::i2c::I2c;
macro_rules! input {
{} => {{
input!("")
}};
($a:expr) => {{
use std::io;
use std::io::Write;
print!("{}", $a);
let _ = io::stdout().flush();
let mut line = String::new();
io::stdin().read_line(&mut line).expect("Error reading from stdin");
line.trim().to_string()
}};
}
const ADDR: u16 = 0x34;
fn main() {
let mut i2c = I2c::new().unwrap();
i2c.set_slave_address(ADDR).unwrap();
println!("{}", i2c.clock_speed().unwrap());
loop {
match input!("w or r").as_str() {
"w" => {
let msg: [u8; 6] = [65, 66, 67, 68, 69, 0];
match i2c.write(&msg) {
Ok(_) => {},
Err(n) => {
println!("could not transmit, {}", n);
},
};
},
"r" => {
let mut buf: [u8; 100] = [0u8; 100];
let num = match i2c.read(&mut buf) {
Ok(n) => {n},
Err(n) => {println!("error could not read, {}", n);0},
};
let msg = &buf[0..num];
let msg = match from_utf8(msg) {
Ok(n) => {n},
Err(_) => {
println!("=========");
for i in 0..num {
println!("\t{}", msg[i]);
}
println!("==========");
""
},
};
println!("msg: {}", msg);
},
_ => {},
}
}
}
basically it prompts the user for input, w or r, and either writes to the slave or reads from the slave
I have gotten the write command to work
left is mbed console, right is raspi console
however when attempting to run a read command I get the following
the stm32 reports that the packet was sent perfectly, while the raspi gets errno 5, then errno 110 on consecutive attempts
I have also noticed that running sudo i2cdetect -y 1
on the raspberry pi console takes ~1 second to scan each address, which, along with the connection timed out errors from above, point to the idea that upon trying to write to the I2C master, the stm32 causes some kind of interference along the data line.
so far I have tried removing the print statements to see if it was a timing issue, as well as adding external pullup resistors both 2.2k and 4.7k (note the write command works perfectly fine with both resistors and no resistors)
Im not sure I can do much else because I don’t have a scope.
Any Ideas? Thanks.
EDIT 1
I managed to get access to an oscilloscope and have determined that when the master tries to read from the slave, the clock is stuck in a low position. Im not sure if this is due to a fault with the master or the slave, but ill keep looking