jamesbowman / i2cdriver

I2CDriver open source tools
https://i2cdriver.com/
BSD 3-Clause "New" or "Revised" License
184 stars 57 forks source link

i2cdriver hardware hangs up #30

Closed codehero closed 4 years ago

codehero commented 4 years ago

There should be no issue at all receiving echo responses. i2cdriver fails to respond. I am not a MyForth expert nor will I ever be, but I don't see that the watchdog timer is used. I don't see any exception vectors handled either. This looks like it could be a 5 star product but it needs the basics covered!

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64 write(3, "eA", 2) = 2 read(3,

jamesbowman commented 4 years ago

Right, I see this:

$ strace ./build/i2ccl /dev/ttyUSB3 i
...
openat(AT_FDCWD, "/dev/ttyUSB3", O_RDWR|O_NOCTTY) = 4
ioctl(4, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(4, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(4, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(4, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(4, "eA", 2)                       = 2
read(4, "A", 1)                         = 1

This might just be a bad unit. So please can you confirm the basics:

The firmware does catch failures, using the SiLabs EFM8 system of timers and interrupts.

codehero commented 4 years ago

I have only tested with an I2C slave microcontroller. I have connected to this microcontroller before with Linux GPIO I2C.

I am 100% sure /dev/ttyUSB0 is the I2CDriver FT230X device

I am not sure what you mean by "that nothing is plugged into the I2CDriver's I2C ports, at least to begin with"? Do you mean on power up, on i2c_connect()? Please provide specific context.

You say the FW catches failures, but if it does they are not reported to the user via serial. For example if there is a watchdog failure, a brownout condition or some other exceptional HW condition this should be reported via serial. There is no bootup message sent out over UART when the unit starts. There is no pulse from the unit. There isn't even a blinking light on the OLED display.

jamesbowman commented 4 years ago

At startup, the display should look like this:

image

To clarify, by "nothing plugged in" I mean no I2C peripherals are connected. So the full procedure:

  1. Take I2CDriver, with no I2C peripherals connected
  2. connect USB cable
  3. confirm that the I2CDriver display lights up, as shown above
  4. confirm the USB port as /dev/ttyUSBx
  5. Use "i2ccl /dev/ttyUSBx i" to confirm that the I2CDriver is alive

Or have you already reached this point?

codehero commented 4 years ago

This point has worked for me before. I have tried a few more times and got this

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64 write(3, "eA", 2) = 2 read(3, "A", 1) = 1 write(3, "e\r", 2) = 2 read(3, "\r", 1) = 1 write(3, "e\n", 2) = 2 read(3, "\n", 1) = 1 write(3, "e\0", 2) = 2 read(3, "\0", 1) = 1 write(3, "?", 1) = 1

codehero commented 4 years ago

openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260A\2\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1996592, ...}) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb7fde41000 mmap(NULL, 2004992, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb7fdc57000 mprotect(0x7fb7fdc79000, 1826816, PROT_NONE) = 0 mmap(0x7fb7fdc79000, 1511424, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7fb7fdc79000 mmap(0x7fb7fddea000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x193000) = 0x7fb7fddea000 mmap(0x7fb7fde37000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1df000) = 0x7fb7fde37000 mmap(0x7fb7fde3d000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb7fde3d000 close(3) = 0 arch_prctl(ARCH_SET_FS, 0x7fb7fde42540) = 0 mprotect(0x7fb7fde37000, 16384, PROT_READ) = 0 mprotect(0x559d19931000, 4096, PROT_READ) = 0 mprotect(0x7fb7fde80000, 4096, PROT_READ) = 0 munmap(0x7fb7fde43000, 78628) = 0 openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0 write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64 write(3, "eA", 2) = 2 read(3,

codehero commented 4 years ago

So sometimes I get a hangup and sometimes I don't. When it does hangup I have to power cycle and the Voltage reading never changes.

jamesbowman commented 4 years ago

OK, I think what you are saying is that the I2CDriver display and communications are working, and that after some communication with a microcontroller I2C Slave, the I2CDriver can hang.

Can you provide any more details on the I2C transaction that leads to the hang?

codehero commented 4 years ago

New information here!

Three program invocations. The first shows code with no bugs. This runs fine. The second has the following bugs: Single character strings are mistyped as single characters ("a" vs 'a'). This shows an address error in strace The third invocation the code is run without the bug and exhibits the no response behaviour.

This is quite possible a bug in the Linux ftdi driver. Or it is a bug in your FW. I don't know which. I think I have given you enough to reproduce it. Please ask more questions if needed.

TRACES

This runs fine

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3
ioctl(3, TCGETS, {B9600 opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B9600 opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(3, "eA", 2)                       = 2
read(3, "A", 1)                         = 1
write(3, "e\r", 2)                      = 2
read(3, "\r", 1)                        = 1
write(3, "e\n", 2)                      = 2
read(3, "\n", 1)                        = 1
write(3, "e\0", 2)                      = 2
read(3, "\0", 1)                        = 1
write(3, "?", 1)                        = 1
read(3, "[i2cdriver1 DO01JT5U 000000013 4"..., 80) = 80
close(3)                                = 0
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(3, "eA", 2)                       = 2
read(3, "A", 1)                         = 1
write(3, "e\r", 2)                      = 2
read(3, "\r", 1)                        = 1
write(3, "e\n", 2)                      = 2
read(3, "\n", 1)                        = 1
write(3, "e\0", 2)                      = 2
read(3, "\0", 1)                        = 1
write(3, "?", 1)                        = 1
read(3, "[i2cdriver1 DO01JT5U 000000013 4"..., 80) = 80
write(3, "x", 1)                        = 1
write(3, "r", 1)                        = 1
write(3, "1", 1)                        = 1
write(3, "i", 1)                        = 1
write(3, "sb", 2)                       = 2
read(3, "3", 1)                         = 1
write(3, "\300\1", 2)                   = 2
read(3, "\0", 1)                        = 1
write(3, "p", 1)                        = 1
exit_group(0)                           = ?

This does not

openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(3, "eA", 2)                       = 2
read(3, "A", 1)                         = 1
write(3, "e\r", 2)                      = 2
read(3, "\r", 1)                        = 1
write(3, "e\n", 2)                      = 2
read(3, "\n", 1)                        = 1
write(3, "e\0", 2)                      = 2
read(3, "\0", 1)                        = 1
write(3, "?", 1)                        = 1
read(3, "[i2cdriver1 DO01JT5U 000000095 4"..., 80) = 80
close(3)                                = 0
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(3, "eA", 2)                       = 2
read(3, "A", 1)                         = 1
write(3, "e\r", 2)                      = 2
read(3, "\r", 1)                        = 1
write(3, "e\n", 2)                      = 2
read(3, "\n", 1)                        = 1
write(3, "e\0", 2)                      = 2
read(3, "\0", 1)                        = 1
write(3, "?", 1)                        = 1
read(3, "[i2cdriver1 DO01JT5U 000000095 4"..., 80) = 80
write(3, 0x78, 1)                       = -1 EFAULT (Bad address)
write(3, 0x72, 1)                       = -1 EFAULT (Bad address)
write(3, 0x31, 1)                       = -1 EFAULT (Bad address)
write(3, 0x69, 1)                       = -1 EFAULT (Bad address)
write(3, "sb", 2)                       = 2

This is the error I was seeing:

openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260A\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1996592, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa155353000
mmap(NULL, 2004992, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fa155169000
mprotect(0x7fa15518b000, 1826816, PROT_NONE) = 0
mmap(0x7fa15518b000, 1511424, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7fa15518b000
mmap(0x7fa1552fc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x193000) = 0x7fa1552fc000
mmap(0x7fa155349000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1df000) = 0x7fa155349000
mmap(0x7fa15534f000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa15534f000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7fa155354540) = 0
mprotect(0x7fa155349000, 16384, PROT_READ) = 0
mprotect(0x55d7700c8000, 4096, PROT_READ) = 0
mprotect(0x7fa155392000, 4096, PROT_READ) = 0
munmap(0x7fa155355000, 78628)           = 0
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY) = 3
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B1000000 -opost -isig -icanon -echo ...}) = 0
write(3, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"..., 64) = 64
write(3, "eA", 2)                       = 2
read(3,
codehero commented 4 years ago

I should note that I am running on an osboxes ubuntu VM

Linux osboxes 4.18.0-25-generic #26-Ubuntu SMP Mon Jun 24 09:32:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

jamesbowman commented 4 years ago

Aha, thanks. What is running this on the Linux box? I assume it is C code that you have for driving the I2CDriver, but want to confirm.

codehero commented 4 years ago

This is all C code. Not sure I understand why I would need 2 separate reads after 'a N' (read N bytes with ack). It seems I need 1 call for the status and 1 for the data. Why is this so?

jamesbowman commented 4 years ago

Looking at the trace... first observation is that the 'x' (bus reset) command sends a response bye back, with the state of SDA,ACL lines in the two low bits. Am updating the C sample code to include reset now.

codehero commented 4 years ago

Thanks for patching, but can you please just fix up the documentation with precise definitions of what commands are accepted and precisely what responses are sent back.

First off page 24 talks about toggling a CS??? line with commands not even in the table. Apparently '_' is a command in the code and it's not in the DOCS???

Please go back and fix the documentation so someone skilled in the art can write a proper C API for it. The only reason I haven't tossed this product in the junk bin is because I think it is fundamentally good and just needs some rigorous attention.

jamesbowman commented 4 years ago

Agreed, on it.

jamesbowman commented 4 years ago

Updated doc, section 7.4 has all the core commands:

https://i2cdriver.com/i2cdriver.pdf

Capture mode is TBD.

jamesbowman commented 4 years ago

Did you get a chance to look at the updated docs? They should have enough detail to write an API.

Reading through the C reference code, I notice that it is incorrect for long (>64 byte) reads, and have raised #34 for the fix.

codehero commented 4 years ago

Yes I have and it makes more sense now. I am going forward with my own C code from scratch given your docs. I am looking forward to monitor mode!

jamesbowman commented 4 years ago

OK to close this one?