AdaCore / Ada-SPARK-Crate-Of-The-Year

19 stars 2 forks source link

[2021][remoteio] Remote I/O Protocol Support #6

Closed pmunts closed 2 years ago

pmunts commented 2 years ago

remoteio

This crate contains a subset of the Linux Simple I/O Library (aka libsimpleio) that is relevant to the Remote I/O Protocol (aka remoteio).

Nearly all of the libsimpleio device packages are included in this crate.

libsimpleio, from which this crate is excerpted, is a general purpose library I have used and continue to use for a variety of projects, including submissions to the Make with Ada contest in 2017 (Ada Embedded Linux Framework) and 2019 (Modbus RTU Framework for Ada). I also used remoteio for the educational tutorial workshop Controlling I/O Devices with Ada, using the Remote I/O Protocol at the Ada-Europe 2019 conference in Warsaw, Poland.

All source files in this crate are my original work. Two prebuilt Windows .dll files, libusb-1.0.dll and hidapi.dll, are from the libusb project.

Purpose

This crate makes it possible to create Ada software for a Linux or Windows target computer that can control I/O devices connected to a remoteio server device.

A first Ada program to flash an LED connected to GPIO0 on some USB HID Remote I/O Protocol server (the embedded systems equivalent of Hello, World!) would look like:

WITH Ada.Text_IO; USE Ada.Text_IO;

WITH GPIO.RemoteIO;
WITH RemoteIO.Client.hidapi;

PROCEDURE test_led IS

  remdev : RemoteIO.Client.Device;
  LED    : GPIO.Pin;

BEGIN
  New_Line;
  Put_Line("USB HID Remote I/O LED test");
  New_Line;

  -- Open the remote I/O server device

  remdev := RemoteIO.Client.hidapi.Create;

  -- Configure GPIO0 to drive an LED

  LED := GPIO.RemoteIO.Create(remdev, 0, GPIO.Output);

  -- Flash the LED

  LOOP
    LED.Put(NOT LED.Get);
    DELAY 0.5;
  END LOOP;
END test_led;

History

remoteio and its Ada client and server implementations are the result of a convergence of factors. One was that libsimpleio was such a success on Linux computers that I began to wish I could use it on Windows and Mac computers as well. Another factor was the steady removal of traditional I/O ports from personal computers. I do a lot of physical computing, test fixture, and automation projects, and over the years my computers gradually lost the parallel ports, serial ports, and even ISA expansion slots I had been relying on to connect I/O devices. Nowadays many laptops no longer even have wired Ethernet. The only possibilities for I/O expansion are Bluetooth, WiFi and USB (from lowest to highest reliability, in my experience).

I spent a lot of time experimenting with and reimplementing the Labview LINX protocol, which can be transported over serial lines and TCP connections. I found some things in the LINX protocol that were incomplete or ill-conceived, but my communications with the maintainers were completely fruitless. They weren't interested in making any improvements or finishing incomplete items, and National Instruments finally seemed to just silently abandon it. (Fun fact: the multiple pin GPIO operations in remoteio were inspired by Labview LINX, but multiple device operations proved too onerous to implement for any other device type).

I also spent a period of time working with the MCP2221 USB serial port and I/O expander chip. The MCP2221 enumerates as two USB devices: a serial port and a raw HID (Human Interface Device) I/O expander. To a limited extent it solves the problem of connecting I/O devices to a modern PC with only USB ports for expansion. I noticed that the MCP2221 is just a preprogrammed PIC16F1455 microcontroller by comparing the datasheets. At about the same time I found that Mikropascal for PIC makes it easy to write USB device applications for even the 14-pin PIC16F1455. As a bonus, a USB raw HID device does not require any special device driver on Windows, Linux, or Mac computers.

I am very fond of RPC (Remote Procedure Call) programming, and I eventually realized that a very minimal RPC protocol could be defined to fit in 64-byte HID reports and implemented as a raw HID device on microcontrollers as small as the PIC16F1455. Thus was born remoteio. Later I implemented support for transporting the 64-byte messages over serial lines (using the Stream Framing Protocol) for microcontrollers and/or boards lacking USB slave device support, and over networks using UDP (User Datagram Protocol), and even over ZeroMQ Request/Reply sockets.

At time of writing, the known available remoteio server implementations are:

Some unpublished but fairly complete USB HID remoteio servers written in Mikropascal for ARM and Mikropascal for PIC32 also exist, as well some unfinished code using Mbed OS.

A future goal is to implement a remoteio server for the Raspberry Pi Pico, probably using either Mbed OS or Ada.

Design

This crate shares the layered design of the libsimpleio crate. The principal differences are that all packages not relevant to remoteio, such as those for Linux kernel devices, have been excluded, and that this crate can be used on Windows as well as Linux.

Performance

The Remote I/O Protocol trades performance for simplicity. As a stop-and-wait protocol, performance is limited by the communication channel latency.

For a USB HID device, a 64-byte report may be sent or received every millisecond, as USB defines a 1 kHz polling frequency for HID devices. Since each Remote I/O Protocol operation requires 1 command and 1 response, the maximum throughput is 500 I/O operations per second. Extant server implementations routinely achieve this rate with both Linux and Windows clients, provided the I/O processing within the server completes in time to return the response during the next USB HID poll.

Faster network channels, such as wired Ethernet, will yield somewhat higher throughput.

Authors

Philip Munts

License

BSD-1-Clause

Documentation

Crate README.pdf

Remote I/O Protocol Specification

Fabien-Chouteau commented 1 year ago

Hi @pmunts , I just want to let you know that you can enter the 2022 edition with the same crate if you want.