C001 i2c issues (but imp004m works)

I have the c001 dev board using 2 i2c busses. One is the bus that is tied to the ICs included on the dev board and another is to a chain of I/O for my project. When I run a bus scanner (like the one provided in the utilities package), I can sometimes see 1 or 2 of the 4 devices but after a reset and re-scan I see nothing. If I disconnect those i2c wires from the c001 and connect them to an imp004m dev board on my desk, every chip appears every time without fail (with exactly the same code, except for the name of the i2c bus).

Are there issues with i2c on the imp c001? I’ve tried i2cXBA and ic2JH. Both perform the same.

No known issues, no. What OS version are you on? What value pull-ups are you using? How long are the wires?

Scanning a bus isn’t really a supported i2c operation; you’re relying on the devices not being upset by the zero byte write.

Sure, I get that there’s no true “i2c scan” but like I said, I’m using the function from your utilities package that scans and lists out (most) connected devices:

    for (local i = 2 ; i < 256 ; i += 2) {
        if (i2c.read(i, "", 1) != null) server.log(format("Device at 8-bit address: 0x%02X (7-bit address: 0x%02X)", i, (i >> 1)));
    }

My entire point is that all of my code works just fine with the i2c lines connected to a port on a imp004m dev board but when connected to the c001, I can only get a read from 0-1 of the connected ICs.

My pull ups in both cases are 2.2k and the total length is about 4 inches. What I’m essentially asking, is why would it work so well on the 004m but not work at all on the c001 (dev board with headers soldered on)?

Honestly, it’s hard to tell. There are different CPUs involved and different wiring, but I2C is slow and generally not super fussy. It’s possible there are bugs with the I2C driver on the STM32H7 CPU - eg the very fact you’re trying to talk to devices that don’t respond could be causing the bus to not reset its state correctly or something similar.

If you don’t scan, and instead just actually try to talk to each device that you expect to be there - with a valid request - does it work fine? That would confirm the above hypothesis.

We should remove that bus scan from the “utilities” package, as it’s not good practice in general. Not all I2C devices will respond to a read transaction, there are such things as write-only I2C devices. for example.

If I slow the speed all the way down to 10kHz I can at least consistently get a read from all the ICs (though the imp004m performs just fine at 400kHz).

I spent the morning developing some libraries using the imp004m with all the devices connected and I didn’t have any bus-related errors. This afternoon I copied everything over to the c001 and took the bus speed down to 10kHz and I would say that every 3rd i2c.read gives me back
TRANSMIT_SELECT_ERROR or MASTER_RECEIVE_SELECT_ERROR

I think you’ve grabbed onto the scan issue a little tightly. Obviously that part is not ending up in my final code and the fact is that all my my ICs do respond to that function on the imp004m. We can debate the merits of such a function another time (though if you don’t write it, you force me to write it each time).

The question was “if you talk to the ICs directly (no scanning), on impC001, do all of them respond”? Not sure if that’s what you were answering above - it sounds like you’re saying that they don’t all respond even at 10kHz?

If so, that sounds a little like a clock stretching issue. Can you give part numbers of the devices in question? If a slow clock works but a fast one does not then it’s usually because the device is trying to stretch the clock (the slave holds SCL low to slow down the master). That should be supported by the I2C peripheral in the STM32H7, but it’s one of the most buggy areas of I2C hardware in my experience.

My comment on “scanning” is that there’s no such thing on i2c. You can try to address each device in turn and see if you get an ACK on the address byte, but aborting the transaction at that point is not something that’s documented for most parts and so I2C peripheral blocks (master or slave) may do undefined things.

If I talk directly with no “scanning” there is no change. All of the ICs do have an actual read operation on the 0 register so the scan would have no ill side effects in this case.

All of the slaves are other microprocessors. I can’t share much information except that they are all AVRs of one sort or another and that one of them specifically does not implement stretching. I’ve sent requests asking about the other two. I have experienced read/write issues on all of them including the one that states that it will not mess with scl.

Any chance you can get a logic analyzer trace - or if not, a scope shot - of a failure? There does appear to be something strange going on (like, I can see a stretch of >40ms would fail, but that seems a pretty huge stretch).

I2C is tested automatically by our system tests, but obviously we only test against a limited number of targets; in general, everyone using an impC001 devkit uses I2C (as the PMU, accelerometer, temp/humid sensor and gas gauge are all on I2C). These all work fine at 400kHz, but they are all hardware I2C devices.

Usually MCUs will be much slower to respond as they are firing interrupts off and (usually) stretching SCL until code runs to form a response or remove a byte from a holding register.

If you can share details privately on a support ticket then that would also be helpful.

Someone is borrowing my scope right now but I’ll take some traces when I get it back. When I sat down this morning to test it connected to the c001, everything worked just fine for about 5 minutes and then I started seeing errors at a similar rate to the last few days. Not sure what that means.

Hmm. Have you got a good ground connection between the boards?

Yes, good ground connection. I needed to get the prototype out the door so I switched to Hologram and everything is going great. I prefer the imp ecosystem so at some point I’ll come back to trying this but at this point it’s pretty clear to me that there’s some sort of issue with the c001 dev boards, or some implementation requirement I’m not aware of.

Hi, I’m going to try to take a look at this.

The reason you’re seeing a difference between imp004 and impC001 is likely because there’s a different i2c driver implementation used.

If you could provide scope or logic analyser traces of the failures that would be incredibly useful.

Thanks

You stated that you’re experiencing either TRANSMIT_SELECT_ERROR, or MASTER_RECEIVE_SELECT_ERROR - Neither of these can be generated from a clock stretch longer than 40ms, which would generate either TRANSMIT_ERROR, or DATA_RXNE_ERROR, depending on whether it’s the subaddress byte or actual message byte that’s timed out.

TRANSMIT_SELECT_ERROR is generated when a NACK is received on the first byte of subaddress transmission at the beginning of an i2c read.

MASTER_RECEIVE_SELECT_ERROR is generated when a NACK is received on the first byte of payload reception.

So it seems like for some reason you get NACKs on impC001, but not on imp004 - I’m not sure why this might be the case, but some logic analyser traces would be very useful in getting further with understanding this problem if you are able to provide any please?

Many thanks,
Toby

Hey Toby thanks for the detailed response. The device is now out in the field (with the Hologram board) but I’ll be building another one in a week or so. I’ll build it around the c001 again and post logic traces at that time.

My guess here, before seeing any traces, is that one or more of the multiple AVR slaves have an i2c implementation that might be NAKing. i.e. there’s bus contention, and more than one of the slaves is driving SDA at a time.

I’ve been writing code to emulate i2c error conditions, and testing the three different driver implementations used on the imps. There are certainly differences in the errors that can be returned from the same error conditions between different imp types, and so it’s possible that you might experience errors on one imp type that you do not experience on a different imp type, especially if the slave i2c devices are implemented in software (Not sure if your AVR slaves are your own i2c implementation, or not?)

Toby

From my experience with c001, 003,004,001 - I2C work ok. Speed up to 400kHz, cable length up to 8 meters, 16 I2C addresses.
I quit with the “I2C” scanner (typical for AVR’s) some while ago. I2C is a simple protocol, and the best way is to straight use of I2C address from the sensor datasheet. At least to find out if there is no address conflict. Why do you “scan” I2C on c001 if you know correct addresses from working 004?
Another thing is SDA and SCL connections. I want to say again - if you have only 2 wires, you probably connect them in the wrong way. But it never happens if you have 20 wires. Human nature :slight_smile: smart people do stupid things :slight_smile:
Pin headers on the c001 and 004 aren’t with the same layout - an easy way to make something wrong.
Try to connect them in order - start with one, then add another, and so on. Find failure point.
Of course - some lines of code must be taken out each time.