SBCX-TN-001: Android Things and SPI bus

From DAVE Developer's Wiki
Jump to: navigation, search
Info Box
SBC-AXEL-02.png Applies to SBC AXEL

History[edit | edit source]

Version Date Notes
1.0.0 April 2018 First public release

Introduction[edit | edit source]

When using Android for embedded platforms, software developers have to face several challenges. Most of them are due to the fact that Android was designed originally to run on mobile devices which meet specific hardware requirements. As such, the APIs to access the hardware interfaces from the application layer are defined accordingly.

These interfaces don't include the ones that are typically used in products addressing industrial applications: I2C bus, SPI bus, UARTs, etc. However, as Android popularity is growing outside the mobile world too, Google defined a set of additional APIs to standardize the access to these interfaces as well. These new APIs are part of the Android Things project.

This Technical Note describes the implementation of the APIs related to the SPI bus to access the SPI bus TBD of the SBCX platform. The solution was tested with Android 4.4.3.

Testbed[edit | edit source]

TBD

Development have been performed on the following platform:

  • CPU: based on NXP/Freescale i.MX6 Dual core
  • SOM: Axel lite
  • carrier board: SBC-AXEL
  • Android Version: 4.4.3 (Jelly Bean)
  • LCD adapter: TI-DF 1.0.0-CS102015

Implementation[edit | edit source]

TBD

Managing the device connection[edit | edit source]

In order to open a connection to a particular SPI slave, you need to know the unique name of the bus. Boot the device and run the following commands from the serial console

root@sbcx:/ # ls /dev/spi*
/dev/spidev32765.0
root@sbcx:/ #

Once you know the target name, the api of the library eu.dave.spi_test follow the Android things nomenclature


public class HomeActivity extends Activity {
    // SPI Device Name
    private static final String SPI_DEVICE_NAME = "/dev/spidev32765.0";

    private SpiDevice mDevice;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDevice = new SpiDevice(SPI_DEVICE_NAME);
        // Attempt to access the SPI device
        try {
           mDevice.Open();
        } catch (IOException e) {
             Log.w("Error", "Unable to access SPI device" + e.getMessage());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mDevice != null) {
            try {
                mDevice.Close();
                mDevice = null;
            } catch (IOException e) {
                Log.w("Error","Unable to close SPI device" + e.getMessage());
            }
        }
    }
}

Configuring clock and data modes[edit | edit source]

Configuration method are identical to the Andriod Things api ref.

public void configureSpiDevice(SpiDevice device) throws IOException {
    // Low clock, leading edge transfer
    device.setMode(SpiDevice.MODE0);

    device.setFrequency(500000);     // 16MHz
    device.setBitsPerWord(8);          // 8 BPW
    device.setBitJustification(false); // MSB first

Transferring data[edit | edit source]

Is important to note that async I/O are not supported in userspace at this time ref. To communicate with the device the following methods are available

  • void WriteByte(byte symbol) For transfer a byte without reading the response from the device.
  • void WriteBuffer(byte[] data, int len) For transfer a buffer to the device without processing the response.
  • void Transfer(byte[] tx_data, byte[] rx_data, int len) For transfer a buffer smaller than the length of the receiving one.
  • void Transfer(byte[] tx_data, byte[] rx_data) For transfer and read a buffer with the same length.
  • void Transfer(byte symbol, byte[] rx_data, int len) For transfer a byte and read a buffer of length len.
public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
    byte[] response = new byte[buffer.length];
    device.Transfer(buffer, response, buffer.length);
    ...
}