Home  >  Edison  >  Current State

I2C SPI HSU USB

I2C

The Edison has 2 i2c channels that we can use, i2c-1 and i2c-6. i2c-1 is used by the Edison Arduino board itself to control level shifters, multiplexers etc. i2c-6 is routed to the Arduino headers. i2c-6 pinmux are already set as needed.

To test i2c you need to insert the module i2c-dev first:

modprobe -i i2c-dev

To detect all i2c channels:

i2cdetect -l
#i2c-3   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-1   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-6   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-4   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-2   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-7   i2c             Synopsys DesignWare I2C adapter         I2C adapter
#i2c-5   i2c             Synopsys DesignWare I2C adapter         I2C adapter

Show the devices detected on a channel:

i2cdetect -y -r 1
root@edison:~# i2cdetect -y -r 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: UU UU UU UU -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

i2c-1 works, the devices shown as UU are the multiplexers on the Arduino board.

root@edison:~# i2cdetect -y -r 6
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

i2c-6 is also working and shows a TSL2561 sensor at address 0x39.

SPI

User-mode access to SPI devices via /dev/spidev5.1 works. It was tested with an RFM69 radio module attached to an Intel mini-breakout board; single-byte and burst transfers were performed in both directions at an SPI speed of 6 MHz.

HSU

We apply a set of patches to the kernel so that the high speed UART (HSU) is handled by DMA to eliminate UART interrupts completely:

  • “8250_mid: arm Rx DMA on all ports with DMA continously” arms the receiver (RX) DMA in advance. After each block reception there is still a little time needed to setup DMA for the next block transfer. DMA treats a 4 character inter-character gaps (timeout) as the end of a block.
  • “WIP: serial: 8250_dma: use sgl on transmit” prevents inter character gaps when transmitting even when the end of the circular buffer is reached by placing the 2 chunks on a scatter-gather list. This prevent spurious inter character gaps.
  • “serial: 8250_port: when using DMA do not split writes in TTY” fixes a bug where transmitting blocks larger then 2kB are split into chunks.

We need to prevent the dma controller from entering a sleep state as waking up can take a long time and the latency can be longer then the UART FIFO length. To do this we need to write 0 to /dev/cpu_dma_latency. The easiest way to do this without coding is to run cyclictest in the background:

cyclictest > /dev/null &

With the above patches no data loss occurs even at 3500000 baud, provided inter-character gaps are sufficiently long. For intentional gaps (the time between sending 2 blocks) this is always the case.

For the console DMA is disabled so that kernel messages to the console (ttyS2) do not depend on the DMA subsystem. For the HSU connected to the Bluetooth modem (ttyS3) and the free UART on the Arduino headers (ttyS1) DMA is enabled by default.

GPIO

Commands included in libgpiod are gpiodetect, gpiofind gpioget, gpioinfo, gpiomon, gpioset.

For instance, to set TRI_STATE_ALL high:

gpioset `gpiofind TRI_STATE_ALL`=1

USB

With linux 4.20 USB works in dual role mode which means it can act either as a device or as a host. In addition it has OTG (On The Go), meaning it can detect the role depending on the type of cable and device at the other end of the cable. For the Edison Arduino the mode is determined by the position of Switch 1 as it has a standard Type A USB plug for host mode and a standard micro B USB plug for device mode. The Edison Breakout board has a micro AB OTG connector to enable automatic selection of the mode.

Host mode

You can use this mode to connect a USB ethernet dongle. Hubs based on smsc95xx (AKA LAN 9514) provide 4 USB ports and 1 10/100 Ethernet port and works out of the box, providing almost 100Mb/s. You can also connect USB sticks and ftdi based serial port dongles.

Gadget (device) mode

In Gadget mode you can connect the Edison to your PC and the PC will detect a multi-function device. Current we have:

1. Ethernet over USB connection

See Networking functions). The network connection has been verified to work with Linux hosts. More work may be needed with Windows based hosts. The speed of the network connection is expected to be in the order of 200Mb/s.

2. Mass storage device.

The partition that is shared is the boot partition (/dev/mmcblk0p9)

3. Serial port over USB.

To make this work, on the host: echo 0x1d6b 0x0104 >/sys/bus/usb-serial/drivers/generic/new_id, this creates a new /dev/USBx port. On Edison put a tty on the newly created port ttyGS0 with /sbin/agetty -L 115200 ttyGS0 xterm-256color.

4. Sound source and sink over USB (uac2)

To make this work, on Edison:

  • To get pulse audio to work first create an ordinary user and add it to group sudo.
  • Give this user access to the sound devices sudo setfacl -m u:ferry:rw /dev/snd/* (for some reason pulseaudio should do this automatically, but doesn’t).
  • Start pulseaudo as ordinary user systemctl --user start pulseaudio.

On host:

  • Configure the Multifunction Composite Gadget using pav selecting Analog Stereo Duplex or Digital Stereo (IEC958) Output + Analog Stereo Input
  • List source device
    pactl list sources | grep Name | grep Gadget
        Name: alsa_input.usb-USBArmory_USBArmory_Gadget_0123456789abcdef-03.iec958-stereo
    
  • List sink device
    pactl list sinks | grep Name
        Name: alsa_output.pci-0000_00_1b.0.analog-stereo
    
  • Create a loopback device
    pactl load-module module-loopback source=alsa_input.usb-USBArmory_USBArmory_Gadget_0123456789abcdef-03.iec958-stereo sink=alsa_output.pci-0000_00_1b.0.analog-stereo
    

Play a wav file on edison:

    paplay "clubbed to death - Matrix soundtrack.wav" 

The load for pulseaudio + paplay is ~ 24% out of 200% (devided over 2 CPU’s.

Play a mp3 file on edison:

pactl list sinks | grep Name
        Name: alsa_output.pci-0000_00_11.0-platform-dwc3.0.auto.stereo-fallback
mpg123 -a alsa_output.pci-0000_00_11.0-platform-dwc3.0.auto.stereo-fallback clubbed-to-death-Matrix-soundtrack.mp3

The load for pulseaudio + mpg123 ~ 30% out of 200%. To make this work you need to install mpg123 to your image, or build it using bitbake mpg123 and install using apt see Building the deb repository.

Script

The Gadget functions are created by the script conf-gadget.sh in a dedicated directory GADGET_BASE_DIR in configfs. Whenever the USB port goes into Gadget mode this script is called from the udev rule gadget.rules. The Gadget functions persist when going to Hode mode, so the directory in configfs is only written once. Script and rule are provided by recipe gadget in meta-intel-bsp.