Hello Jean-Adrien,
first please note that I'm far from an export for I2C but nevertheless like to share my thoughts from an architectural perspective on Genode.
On Thu, Feb 25, 2021 at 10:57:21 CET, Jean-Adrien Domage wrote:
We would like to introduce an i2c driver for imx8q_evk to Genode. Thanks to the hints from Sebastian, I now have a prototype component that can send/receive data via the i2c bus of the imx8q_evk. The next task is to design the RPC interface for the driver.
My first impulse was to respond with: Why don't you reuse an existing RPC interface as there are quite many use cases covered with these. But thinking about the task more I could not find a fit in the current arsenal myself ;-)
What would be a good kind of interface? Do you have driver(s)/component(s) to recommend as example? Or any specific guidelines?
In my opinion there are two design questions to answer.
1. What is the nature of I2C and how should it be reflected in Genode?
According to Wikipedia [1], I2C is a master-slave bus comparable to USB on a high level but far less complex. The master may request read or write transactions from/to a slave peripheral. I can't derive the requirement for an interrupt scheme resp. asynchronous operation from this information. Naturally, peripherals are addressed in some way by a _bus address_.
As I've limited to no hands-on experience with I2C hardware, I'd start with a design that considers the Genode host's I2C bus driver as the bus master, which sends request transactions to a bunch of slave peripherals on the bus. Each peripheral is a distinct hardware resource possibly used by distinct Genode components. Therefore, the permission to address requests to _one_ I2C peripheral should be expressed by a session. Multiple peripherals can be accessed via multiple sessions each one dedicated to one device on the I2C bus. The bus driver can then be configured by policies that match session labels to bus addresses and, thereby, the permission to interact with one specific peripheral.
A rough example of a Genode configuration may look like follows.
<start name="i2c_bus_drv"> <provides> <service name="I2c"/> </provides> <config> <policy label_prefix="sensor" bus_address="1"/> <policy label_prefix="motor" bus_address="2"/> <policy label_prefix="peripheral" bus_address="5"/> </config> <route> <!-- allow the bus driver to access required I/O resources --> </route> </start>
<start name="combined_drv"> <route> <!-- driver requests 2 sessions - "sensor" and "motor" --> <service name="I2c" label="sensor"> <child name="i2c_bus_drv" label="sensor"/> </service> <service name="I2c" label="motor"> <child name="i2c_bus_drv" label="motor"/> </service> </route> </start>
<start name="single_drv"> <route> <service name="I2c"> <child name="i2c_bus_drv" label="peripheral"/> </service> </route> </start>
2. How should an appropriate functional session interface look like?
According to what I learned from Wikipedia, the most simple operations required are like follows.
uint8_t read_byte() void write_byte(uint8_t)
The functions do not need a bus address parameter as the session hard-wires the access to one peripheral. The sketched operations may not suffice if I2C supports multi-byte transactions and those are required by the peripherals too. These could be added easily later.
[1] https://en.wikipedia.org/wiki/I%C2%B2C
I hope this helps you starting your design and are curious which solution you are going to propose.
Regards