Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Userspace I/O class? #63

Open
Livius90 opened this issue Jul 31, 2023 · 3 comments
Open

Add Userspace I/O class? #63

Livius90 opened this issue Jul 31, 2023 · 3 comments

Comments

@Livius90
Copy link

Can you consider to implement generic uio in your python periphery? As i see your MMIO implementation can serve the reg mapping for a /dev/uioX, only the IRQ waiting which is needed to implemented for this new class.

See this examples:

@Livius90
Copy link
Author

Livius90 commented Aug 7, 2023

@vsergeev
What do you think, is it fine?

import os
from periphery import MMIO

def get_uio_dev(uio_name):
    for dev in os.listdir("/sys/class/uio"):
        with open("/sys/class/uio/" + dev + "/name", "r") as f:
            name = f.readline().strip()
        if name == uio_name:
            return "/dev/" + dev
    return None

def get_uio_size(uio_dev):
    size = None
    with open("/sys/class/uio/" + uio_dev + "/maps/map0/size", "r") as f:
        size = int(f.readline().strip(), 16)
    return size

class UIO(MMIO):
    def __init__(self, name):
        uio_dev = get_uio_dev(name)
        uio_size = get_uio_size(uio_dev)
        super().__init__(0x00, uio_size, uio_dev)
        # _fdesc should be opened in MMIO's __init__() instead
        self._fdesc = os.open(uio_dev, os.O_RDWR | os.O_SYNC)
        
    def enable_irq(self):
        os.write(self._fdesc, bytes([1, 0, 0, 0]))

    def disable_irq(self):
        os.write(self._fdesc, bytes([0, 0, 0, 0]))
        
    def wait_irq(self):
        os.read(self._fdesc, 4)
        
    def close(self):
        os.close(self._fdesc)
        super().close()

@vsergeev
Copy link
Owner

It's a good idea -- could use a few more getters with the UIO info. One thing to decide is whether or not to abstract away the interrupt counts -- e.g. should wait_irq() return the raw interrupt counter or the number of interrupts that occurred since the last wait.

@Livius90
Copy link
Author

Livius90 commented Aug 17, 2023

It's a good idea -- could use a few more getters with the UIO info. One thing to decide is whether or not to abstract away the interrupt counts -- e.g. should wait_irq() return the raw interrupt counter or the number of interrupts that occurred since the last wait.

What getter you think is need more?

Implementation for return missed interrupts:
https://www.kernel.org/doc/html/v4.17/driver-api/uio-howto.html#how-uio-works

import os
from periphery import MMIO

def get_uio_dev(uio_name):
    for dev in os.listdir("/sys/class/uio"):
        with open("/sys/class/uio/" + dev + "/name", "r") as f:
            name = f.readline().strip()
        if name == uio_name:
            return "/dev/" + dev
    return None

def get_uio_size(uio_dev):
    size = None
    with open("/sys/class/uio/" + uio_dev + "/maps/map0/size", "r") as f:
        size = int(f.readline().strip(), 16)
    return size

class UIO(MMIO):
    def __init__(self, name):
        uio_dev = get_uio_dev(name)
        uio_size = get_uio_size(uio_dev)
        super().__init__(0x00, uio_size, uio_dev)
        # _fdesc should be opened in MMIO's __init__() instead
        self._fdesc = os.open(uio_dev, os.O_RDWR | os.O_SYNC)
        self.irq_total_count = 0
        self._irq_last_count = 0
        
    def enable_irq(self):
        os.write(self._fdesc, bytes([1, 0, 0, 0]))

    def disable_irq(self):
        os.write(self._fdesc, bytes([0, 0, 0, 0]))
        
    def wait_irq(self):
        self.irq_total_count = os.read(self._fdesc, 4)
        irq_count = self.irq_total_count - self._irq_last_count
        self._irq_last_count = self.irq_total_count
        
        # return 1 or number of missed interrupts
        return irq_count
        
    def close(self):
        os.close(self._fdesc)
        super().close()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants