fivdi / i2c-bus

I2C serial bus access with Node.js
MIT License
348 stars 58 forks source link

{"errno":-1,"code":"UNKNOWN","syscall":"write"} #38

Closed MaBecker closed 6 years ago

MaBecker commented 6 years ago

sometime there is a write error with unknown errno

no idea where this gets printed from.

Any hints to delimit this?

MaBecker commented 6 years ago

we run i2c-bus on beaglebone 3.8.13-bone84 and node v0.10.38

fivdi commented 6 years ago

What version of i2c-bus is being used? Which board is being used, a BeagleBone or BeagleBone Black?

Does your application call i2cWrite or i2cWriteSync? These look like the most likely candidates as the source of the error.

How does your application handle errors? Does it retry the operation of there is an error?

How is the I2C device connected to the board? Is it on a breadboard with jumper wires or is it soldered?

Note that i2c-bus simply passes the errors that it gets from Linux directly back to the application. In other words, I don't think the we're going to find an i2c-bus bug here.

MaBecker commented 6 years ago

First thanks for your quick response.

AFAIK this message is not from any i2c-bus code section, what about bindings or nan? Is there a catch missing in i2c-bus code?

What version of i2c-bus is being _used?

"name": "i2c-bus", "version": "1.2.1",

Which board is being used

beaglebone black

Does your application call

only use ....Sync

How does your application handle errors?

all calls use try {} catch{}

Does it retry the operation of there is an error?

no recalls

How is the I2C device connected to the board?

no bread board, soldered i2c components

bus frequenz: 100 KHz

fivdi commented 6 years ago

AFAIK this message is not not from any i2c-bus code section, what about bindings or nan?

If the i2c-bus module loads correctly which appears to be the case as it's running, then there isn't an issue with bindings. The chances of it being related to nan are very slim. If the only method being called when the error occurs is i2cWriteSync then nan isn't even involved as i2cWriteSync is implemented entirely in JavaScript.

If all calls use try catch and it's really the case that only sync calls are used the it should be possible to locate the error by adding console.log statements to the catch blocks.

Although it may not be a software issue can you post code that can be used to reproduce the error?

MaBecker commented 6 years ago

Ok - so it is the i2c-bus that is creating this output and not any other modules.

Will add some console.log and try to reproduce this error.

MaBecker commented 6 years ago

update:

this error happens when sending 8 chunks of 129 byte to an oled.

reduced chunk size 65 bytes and started test

fivdi commented 6 years ago

If the error is only occasionally occurring why not catch the error and retry?

MaBecker commented 6 years ago

You can use this code to reproduce the error, be sure that there is no device with id 60 on the bus.

// simple test code

var i2c = require("i2c-bus");
var i2cbus;
var bus = 1;

// open bus
try {
  console.log("cmd i2c.openSync(bus)");
  i2cbus = i2c.openSync(bus);
} catch(e) {
  console.log(e);
  process.exit(1);
}

// send buffer  
try {
  console.log("cmd i2cbus.i2cWriteSync(60,2,[ 0x00, 0xAF ])");
  i2cbus.i2cWriteSync(60,2, new Buffer([ 0x00, 0xAF ]));
} catch(e) {
  console.log(e);
}

// close bus
try {
  console.log("cmd i2c.closeSync()");
  i2cbus.closeSync();
} catch(e) {
  console.log(e);
}

output

cmd i2c.openSync(bus)
cmd i2cbus.i2cWriteSync(60,2,[ 0x00, 0xAF ])
{ [Error: UNKNOWN, unknown error] errno: -1, code: 'UNKNOWN', syscall: 'write' }
cmd i2c.closeSync()

Expected RemoteIO Error because a device with id 60 is not available.

fivdi commented 6 years ago

Here's the output I see with i2c-bus v1.2.4 and Node.js v9.2.0 on "Debian 9.2 2017-10-10 4GB SD IoT":

debian@beaglebone:~/i2c-bus$ node -v
v9.2.0
debian@beaglebone:~/i2c-bus$ uname -a
Linux beaglebone 4.4.91-ti-r133 #1 SMP Tue Oct 10 05:18:08 UTC 2017 armv7l GNU/Linux
debian@beaglebone:~/i2c-bus$ node t.js 
cmd i2c.openSync(bus)
cmd i2cbus.i2cWriteSync(60,2,[ 0x00, 0xAF ])
{ Error: EREMOTEIO: remote I/O error, write
    at Object.fs.writeSync (fs.js:753:20)
    at Bus.i2cWriteSync (/home/debian/i2c-bus/node_modules/i2c-bus/i2c-bus.js:348:13)
    at Object.<anonymous> (/home/debian/i2c-bus/t.js:17:10)
    at Module._compile (module.js:641:30)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
    at Function.Module._load (module.js:495:3)
    at Function.Module.runMain (module.js:682:10)
    at startup (bootstrap_node.js:191:16) errno: -121, code: 'EREMOTEIO', syscall: 'write' }
cmd i2c.closeSync()

As can be seen and as is to be expected there was a remote I/O error.

Note that it is not i2c-bus that decides what the errno, code and syscall are. It's the operating system and in particular the I2C driver that decide what the errno, code and syscall are.

Above you mention that beaglebone 3.8.13-bone84 and node v0.10.38 are being used. This is a very old Linux kernel version and and a very old version of Node. Because the kernel is old the I2C driver is most likely also old. You are almost certainly using a much older I2C driver than I used for the above test. This may explain the differing error messages.

I still haven't seen anything here that would lead me to believe that there is a bug in i2c-bus.

fivdi commented 6 years ago

Above you asked the following question:

Is there a catch missing in i2c-bus code?

To the best of my knowledge there isn't.

MaBecker commented 6 years ago

Thanks a lot for your comments and test.

Best thing is to upgrade linux and node.

So lets close both issues

fivdi commented 6 years ago

Thanks a lot for your comments and test.

No problem.

I took a closer look at how Node.js handles errors from the operating system. By the looks of things some of the work is done by uv rather than Node.js. For Node.js v0.10.38 errors from the operating system are mapped to Node.js errors using the information here. Closer examination of this information reveals that Node.js v0.10.38 does not know about EREMOTEIO. If Node.js v0.10.38 doesn't know about an error it appears to default to using this information. The first version of Node.js that knows about EREMOTEIO is Node.js v8.5.0. This can be seen here.

UPDATE: In Node.js v6.x.x EREMOTEIO is handled by Node.js v6.12.0 and higher.

fivdi commented 6 years ago

To further complicate matters related to error handling there is a difference between how errors are dealt with in code implemented in pure JavaScript and code implemented in C++ in the i2c-bus addon.

Methods like i2cRead, i2cReadSync, i2cWrite and i2cWriteSync that are implemented in pure JavaScript can result in '"errno":-1,"code":"UNKNOWN"' errors if Node/uv has no information about the error,

Methods like readByte, readByteSync, writeByte and writeByteSync that are implemented on C++ will end up calling strerror to get the error message for an error here. strerror is a Linux operating system that returns the error message for an errno.

All that being said and irrespective of how error handling works internally it's not going to be possible to prevent all errors from occurring. A strategy will be needed to handle the errors. For the case being discussed in this issue the best strategy may be to retry the operation. Upgrading to Node.js v6.12.0 or higher or Node.js V8.5.0 or higher will result in nicer error messages but there can still be errors that need to be handled.

MaBecker commented 6 years ago

Planing to use a central queue to handle calls and errors

MaBecker commented 6 years ago

Where you facing any trouble upgrading to bone-debian-9.2-iot-armhf-2017-10-10-4gb.img?

fivdi commented 6 years ago

Where you facing any trouble upgrading to bone-debian-9.2-iot-armhf-2017-10-10-4gb.img?

There were no issues. I didn't upgrade, I started from scratch and flashed the OS onto an SD card and use the SD card rather than the 2GB eMMC on-board flash storage. I have a very old BeagleBone Black that only has 2GB eMMC on-board flash storage. A newer BeagleBone Black will have 4GB eMMC on-board flash storage. I always format SD cards with a FAT32 file system before flashing the OS onto them. Not doing this has resulted in issues in the past.

Note that bone-debian-9.2-iot-armhf-2017-10-10-4gb.img comes with Node.js v6.11.4 pre-installed which will still give the '"errno":-1,"code":"UNKNOWN"' errors so you'll need to upgrade to a new version of Node.js for the nicer error messages.

I have had issues with new images in the past due to old boot loaders. In these cases it was necessary to hold down the boot button before power on, then power on and keep the boot button pressed until all four onboad LEDS turn on at the same time and then turn off. The boot button is the button that's on the same end of the BeagleBone Black as the SD card slot.

MaBecker commented 6 years ago

now running on

Linux bbb99 4.4.91-ti-r141 #1 SMP Fri Dec 22 10:23:45 UTC 2017 armv7l GNU/Linux

node v8.9.3 (LTS)

fivdi commented 6 years ago

That's good news. Hopefully things will improve now...