Thanks to visit codestin.com
Credit goes to github.com

Skip to content

NACK from slave every other time when reading #416

@kaolpr

Description

@kaolpr

I've come across a strange behavior - every other time I run read operation, I get NACK. This happens only, when there is a read operation. If only writes are executed, it is fine.

Master is Adafruit FT232H (0403:6014 Future Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC), slave is FPGA core. I am aware that the issue may be IP core, however, logic analyzer output suggests otherwise. Please note that my IP core is very simple (clock stretching).

Sidenote: Slave is in fact a I2C to Wishbone bridge and due to some constraints it was implemented as two slaves - one for address and one for date.

To pin down an issue, I've created a minimal script:

from pyftdi.i2c import I2cController

i2c = I2cController()
i2c.configure('ftdi://ftdi:232h:1/1')

adr_port = i2c.get_port(0x30)
dat_port = i2c.get_port(0x31)

adr_port.write((0x00000800 >> 2).to_bytes(4, "big"))
dat_port.read(1)[0]
# adr_port.write((0x00000800 >> 2).to_bytes(4, "big"))

This script fails every other time with NACK when performing adr_port.wirte. The same script with read commented out works every time. Surprisingly, with the last line uncommented, the behaviour is exactly the same.

Now, from the slave side it looks that every other time FTDI performs malformed write operation:

Image

Please note that I2C lines are not pulled down initially, what makes my thinking that it is not related to slave holding line after previous operation. For comparison, this is the beginning of the working transaction:

Image

At the end of the operation both lines look ok:

Image

Both acquisitions triggered with SCL falling edge.

I've also made another minimal example, this time in Rust and with ftdi_embedded_hal:

use eh1::i2c::I2c;
use ftdi_embedded_hal as hal;


fn main() {
    let device = ftdi::find_by_vid_pid(0x0403, 0x6014)
        .interface(ftdi::Interface::A)
        .open()
        .unwrap();

    let hal = hal::FtHal::init_default(device).unwrap();
    let mut i2c = hal.i2c().unwrap();

    let address: u32 = 0x00000800 >> 2;
    let address_bytes = address.to_be_bytes();
    I2c::write(&mut i2c, 0x30, &address_bytes).unwrap();
    let mut buffer: [u8; 1] = [0];
    I2c::read(&mut i2c, 0x31, &mut buffer).unwrap();
}

This one works every time, what makes me think that the problem is pyftdi-related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions