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 613 forks source link

Uart(0) and Uart(1), etc. are meaningless on Joule... #612

Open xmnboy opened 7 years ago

xmnboy commented 7 years ago

...apparently because the Joule BIOS does not enumerate the UART devices (per @arfoll). This means that they can only be initialized using their /dev/tty## device name strings.

Trying to use the Uart(#) constructor fails, even though the UART capabilities bits are set to a one in the pins (mraa_pincapabilities_t) bit structure. That is, mraa/src/x86/intel_gt_tuchuck.c includes those pins that have their UART capabilities bits set.

The brute-force solution would be to clear those bits in the respective capabilities struct, to indicate that they are not supported (which is only a half-truth). It won't eliminate the dramatic failure that results from trying to init using the Uart(#) constructor.

A nicer solution would be to inspect /sys/devices/pci* for all the /tty??* devices and then enumerate them dynamically as part of the mraa initialization, so the Uart(#) constructor could be used. For example, you'll find these four physical UART devices located in the /sys/devices/pci0000:00 folder on the Joule, using that technique:

./0000:00:18.0/dw-apb-uart.8/tty/ttyS0
./0000:00:18.1/dw-apb-uart.9/tty/ttyS1
./0000:00:18.2/dw-apb-uart.10/tty/ttyS2
./0000:00:18.3/dw-apb-uart.11/tty/ttyS3

For what it's worth, my experiments are based on using the JavaScript API, not the C or C++ API. The "failure" is quite dramatic, but I'll leave that for another issue.

p.s. The Uart.getDevicePath() returns gibberish when you use the Uart("/dev/tty##") constructor. It should return the string you supplied in the constructor.

arfoll commented 7 years ago

So I think you've misunderstood. Those uarts simply aren't connected to any physical pins on the board. Yes getting uarts via pci id may be good, but realistically they're usually enumerated statically by the kernel unlike i2c/spi so we don't have the issue of dissapearing uarts.

So just returning all the uarts we can find would just confuse users into thinking they can use those 4 uarts. We can pretend it works but since they're not muxed it just won't help users. Anyways I've cleared the uart pins from the caps with c1017bb6ead0cdf3e96071824f7ab5b833aa07f2. I don't feel that exposing /dev/ttyS2 as mraa::Uart(0) is a good idea because it's the default console port.

And yes there is a bug with uart::getDevicePath(), turns out that only works in non raw mode. I've fixed it with 1c180e393c3e7814b13626e9d201005d5ec69c20.

xmnboy commented 7 years ago

I am confused, because I am able to make those UARTs work (on a Joule), but only by using the uart("/dev/tty##") constructor. According to the board's schematic those devices are attached to header pins; and they are also present on the PCI bus by inspecting the /sys/devices filesystem. I am able to see the TxD signals "twiddle" on the board headers when I write data via the UART.

arfoll commented 7 years ago

I'm so confused. Just tell me the following for all the working uarts on your board: /dev/ttySx TX: pinXX, RX: pinXX

xmnboy commented 7 years ago

Here's what I have confirmed on a production Joule running the Ostro Linux distribution:

This last one (/dev/ttyS3) I have not fully confirmed, but I expect it to work similarly to the first two, as it is connected to the headers per the production schematic. My only concern, regarding this UART, is the reference to it as an "ISH" (Integrated Sensor Hub) UART on the datasheet, although it is present and accessible via the PCI bus.

fnoop commented 7 years ago

@xmnboy I can confirm /dev/ttyS1 works fine on pins 22/24 as well, using ubuntu 16.04 desktop. Thanks for the info :) There's an awful lot of bad information about the joule out there..

alext-mkrs commented 7 years ago

After UART-related commit of PR 669 is merged, the number-based UART use will be available and for now, using device file names (i.e. mraa raw mode) works as well (I've also tested it with UART 1). Thanks @xmnboy for the summary! This information (pin assignments) is also available these days in this official article