Skip to content

Commit

Permalink
refactor(api): deploy libgpiod for gpio control and deprecate sysfs (#…
Browse files Browse the repository at this point in the history
…5381)

This moves our API server over to using libgpiod (https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/), the current state of the art for controlling GPIO pins in linux through a character device rather than sysfs. This should be faster, is easier to improve, and doesn't use an officially deprecated abi (https://www.kernel.org/doc/html/latest/admin-guide/gpio/sysfs.html).

One key difference that drives many changes in this PR is that control over gpios through libgpiod is lifetimed to a process, and ownership over an individual gpio line is restricted to a single pid. That means that
- We have a single gpio controller object instead of free functions; this has the lifetime of the main hardware controller and is passed around to other things that need it, notably the robot singleton in the robot server
- Given that the hardware controller owns the object, we pushed down smoothie reprogramming into the hardware controller so that we don't have to do it in the server code, which involves multiple instantiations of hardware controller sections

And finally, it means that only the robot server can control GPIOs. After this PR, protocols executed through jupyter or opentrons_execute cannot control GPIOs.

closes #5310
  • Loading branch information
ahiuchingau authored Apr 21, 2020
1 parent 0db633b commit 475ee25
Show file tree
Hide file tree
Showing 19 changed files with 494 additions and 381 deletions.
6 changes: 3 additions & 3 deletions api/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/mypy.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[mypy]
ignore_missing_imports=false
ignore_missing_imports=False
check_untyped_defs=True

[mypy-opentrons.legacy_api.*]
Expand Down
8 changes: 8 additions & 0 deletions api/src/opentrons/api/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import List, Dict, Any, Optional
from uuid import uuid4
from opentrons.drivers.smoothie_drivers.driver_3_0 import SmoothieAlarm
from opentrons.drivers.rpi_drivers.gpio_simulator import SimulatingGPIOCharDev
from opentrons import robot
from opentrons.broker import Broker
from opentrons.commands import tree, types as command_types
Expand Down Expand Up @@ -267,6 +268,7 @@ def _hw_iface(self):
def prepare(self):
if not self._use_v2:
robot.discover_modules()

self.refresh()

def get_instruments(self):
Expand Down Expand Up @@ -372,6 +374,7 @@ def on_command(message):
robot.broker = self._broker
# we don't rely on being connected anymore so make sure we are
robot.connect()
robot._driver.gpio_chardev = SimulatingGPIOCharDev('sim_chip')
robot.cache_instrument_models()
robot.disconnect()

Expand Down Expand Up @@ -504,6 +507,11 @@ def on_command(message):
'Internal error: v1 should only be used for python'
if not robot.is_connected():
robot.connect()
# backcompat patch: gpiod can only be used from one place so
# we have to give the instance of the smoothie driver used by
# the apiv1 singletons a reference to the main gpio driver
robot._driver.gpio_chardev\
= self._hardware._backend.gpio_chardev
self.resume()
self._pre_run_hooks()
robot.cache_instrument_models()
Expand Down
18 changes: 18 additions & 0 deletions api/src/opentrons/drivers/rpi_drivers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from .dev_types import GPIODriverLike

MODULE_LOG = logging.getLogger(__name__)


def build_gpio_chardev(chip_name: str) -> 'GPIODriverLike':
try:
from .gpio import GPIOCharDev
return GPIOCharDev(chip_name)
except (ImportError, OSError):
MODULE_LOG.info(
'Failed to initialize character device, cannot control gpios')
from .gpio_simulator import SimulatingGPIOCharDev
return SimulatingGPIOCharDev(chip_name)
59 changes: 59 additions & 0 deletions api/src/opentrons/drivers/rpi_drivers/dev_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Dict, Tuple
from typing_extensions import Protocol


class GPIODriverLike(Protocol):
""" Interface for the GPIO drivers
"""
def __init__(self, chip_name: str):
...

@property
def chip(self) -> str:
...

@property
def lines(self) -> Dict[int, str]:
...

async def setup(self):
...

def set_high(self, offset: int):
...

def set_low(self, offset: int):
...

def set_button_light(self,
red: bool = False,
green: bool = False,
blue: bool = False):
...

def set_rail_lights(self, on: bool = True):
...

def set_reset_pin(self, on: bool = True):
...

def set_isp_pin(self, on: bool = True):
...

def set_halt_pin(self, on: bool = True):
...

def get_button_light(self) -> Tuple[bool, bool, bool]:
...

def get_rail_lights(self) -> bool:
...

def read_button(self) -> bool:
...

def read_window_switches(self) -> bool:
...

def release_line(self, offset: int):
...
Loading

0 comments on commit 475ee25

Please sign in to comment.