eclipse / mraa

Linux Library for low speed IO Communication in C with bindings for C++, Python, Node.js & Java. Supports generic io platforms, as well as Intel Edison, Intel Joule, Raspberry Pi and many more.
http://mraa.io
MIT License
1.37k stars 614 forks source link

Unable to use both UPM & MRAA with FT4222 #433

Closed Propanu closed 8 years ago

Propanu commented 8 years ago

Title says it all, if you try to use both MRAA and some UPM driver with the FT4222, the second subplatform init will fail. So far only tested this with node but I assume it will happen in other languages too. Here's the code:

> var mraa = require('mraa');
undefined
> var upm = require('jsupm_stepmotor');
undefined
> var sm = new upm.StepMotor(516, 517);
Error: Illegal arguments for construction of _exports_StepMotor
    at repl:1:10
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20
    at REPLServer.self.eval (repl.js:122:7)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:203:10)
    at Interface._line (readline.js:532:8)
    at Interface._ttyWrite (readline.js:761:14)
    at ReadStream.onkeypress (readline.js:100:10)
> var pin = new mraa.Gpio(516);
undefined

And here's the log:

Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: libmraa version v0.9.3-1-g64c162c initialised by user 'root' with EUID 0
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: Platform not supported, not initialising
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: FT_GetDeviceInfoList returned 2 devices
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: mraa_ftdi_ft4222_init completed successfully
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: FT4222_GetVersion 42220100 01020104
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: ft4222: using pca9555 as GPIO expander
Feb 18 07:34:44 WR-IDP-F6DA libmraa[4941]: libmraa initialised for platform 'Unknown platform + FTDI FT4222' of type 98
Feb 18 07:34:54 WR-IDP-F6DA libmraa[4941]: libmraa version v0.9.3-1-g64c162c initialised by user 'root' with EUID 0
Feb 18 07:34:54 WR-IDP-F6DA libmraa[4941]: Platform not supported, not initialising
Feb 18 07:34:54 WR-IDP-F6DA libmraa[4941]: FT_GetDeviceInfoList returned 2 devices
Feb 18 07:34:54 WR-IDP-F6DA libmraa[4941]: FT_GetDeviceInfoList contains no GPIO controllers
Feb 18 07:34:54 WR-IDP-F6DA libmraa[4941]: libmraa initialised for platform 'Unknown platform' of type 98
Feb 18 07:35:10 WR-IDP-F6DA libmraa[4941]: gpio: Using sub platform
Feb 18 07:35:10 WR-IDP-F6DA libmraa[4941]: gpio: Sub platform Not Initialised
Feb 18 07:35:28 WR-IDP-F6DA libmraa[4941]: gpio: Using sub platform

Thus you could use one or the other but not both. Using multiple UPM sensors seems to work as expected though.

whbruce commented 8 years ago

Think of libft4222 as serial port; it can can only be opened once. If it opened a second time it will fail. That's what you;re seeing. This is a mraa documentation bug.

Propanu commented 8 years ago

Yeah that part is clear and I don't have an issue with that. But I would expect us to be able to return the existing subplaform handle on an init call the second time around. In fact I'm sure we already do this to some extent or you won't be able to use multiple sensors from UPM, we're just not catching this UPM+MRAA case.

whbruce commented 8 years ago

Thanks for clarifying failure. If platform is already initialized I can't figure out how mraa_init() manages to initialize sub-platform a second time.I'll take a closer look.

whbruce commented 8 years ago

I dug deeper and found that the mraa node module links to mraa object files, not the shared library. upm node modules do the right thing and link to the mraa shared library. Thus when a node project uses both mraa and a upm modules you end up with two mraa instances so mraa_init() is called twice. The second mraa_init() call results in the libft4222 double load and subsequent failure. Java and Python bindings will have the same problem.

I fixed this by changing the following lines in src/javascript/CMakeLists.txt.

swig_add_module (mraajs javascript mraajs.i ${mraa_LIB_SRCS})
swig_link_libraries (mraajs ${mraa_LIBS})

to

swig_add_module (mraajs javascript mraajs.i)
swig_link_libraries (mraajs mraa)

Similar changes should be made for Python and Java.

@arfoll - is this a valid fix?

arfoll commented 8 years ago

Yeah it's valid - if it works as expected :D, there where some issues previously which is why mraa was built this way, wasted a few kBs.

Propanu commented 8 years ago

@whbruce thanks for tracking this down and finding a fix. I can see many use cases were both MRAA & UPM are desired within the same application.

whbruce commented 8 years ago

The Java fix is proving to be more complicated. There is JNI code in gpio.c (and maybe elsewhere) that complicates linking. It should be moved to src/java so it is exported by libmraajava.so and not libmraa.so. I'll get to this, but not for a few days.

petreeftime commented 8 years ago

UPM Java libraries link with libmraajava.so, and MRAA Java class should also load libmraajava.so. Are there any cases in which this doesn't happen already?

whbruce commented 8 years ago

Currently libmraajava.so statically links to mraa but UPM jini shared libraries dynamically link to libmraa. So if a Java app instantiates both mraa and upm objects, the underlying platform object is instantiated twice as well which causes the problem reported by @Propanu.

I have a fix in progress, will issue a PR by EOD which Java team can review.

whbruce commented 8 years ago

Done. See PR #441.

Propanu commented 8 years ago

Awesome, thanks everyone for the quick turnaround!