Internships/ProjectIdeas/I2CPassthrough: Difference between revisions

From QEMU
(→‎I2C Passthrough: update description)
Line 3: Line 3:
'''Summary:''' Implement I2C device passthrough on Linux hosts so that a single board computer like a Raspberry Pi can be used to develop applications for microcontrollers like the micro:bit.
'''Summary:''' Implement I2C device passthrough on Linux hosts so that a single board computer like a Raspberry Pi can be used to develop applications for microcontrollers like the micro:bit.


QEMU emulates I2C devices in software but currently cannot pass through real I2C devices from the host to the guest.  It would be useful to access real I2C devices from inside the guest, for example for developers writing and testing software under QEMU on their computer.
QEMU emulates I2C devices in software but currently cannot pass through real I2C devices from the host to the guest.  It would be useful to access real I2C devices from inside the guest, for example for developers writing and testing software under QEMU on their computer.  This would be used like ''-device i2c-passthrough,device=/dev/i2c-N,hostaddr=0x48'' (another possibility is to implement Linux I2C device support as a character device, like ''-chardev linux-i2c,address=0x48,device=/dev/i2c-N,id=i2c-chardev -device i2c-passthrough,chardev=i2c-chardev,address=0x49''.


The project consists of the following tasks:
A very basic implementation of I2C passthrough can be very simple (150-200 lines of code perhaps) using the read/write interface to /dev/i2c-N.  However, read/write is very limited and cannot drive all I2C devices because it does not support [https://www.i2c-bus.org/repeated-start-condition/ repeated start conditions].  The current I2C API in QEMU is also very limited.  Therefore there are many possible extensions:
* Write tests for one or more I2C emulated controllers using the qtest framework
 
* Implement ''-device i2c-passthrough,device=/dev/i2c-N'' (another possibility is to implement Linux I2C device support as a character device, like ''-chardev linux-i2c,device=/dev/i2c-N,id=i2c-chardev -device i2c-passthrough,chardev=i2c-chardev''; this enables testing even without actual I2C devices available)
* implementing I2C passthrough as an SMBusDevice instead of I2CSlave.  SMBusDevice provides a higher-level interface than I2CSlave, with support for repeated start conditions and block transfers.  (Question: how would the SMBusDevice API translate to /dev/i2c-N ioctls)?
* Add clock stretching support to i2c-passthrough support, and implement it in at least one emulated controller
* improving SMBusDevice support in QEMU: currently the SMBusDevice->I2CSlave adaptor in hw/i2c/smbus_slave.c only implements a subset of SMBus, in particular it can only read a single byte at a time from the device. Your task could be to improve the QEMU I2CBus API so that all functionality of
* Implement micro:bit TWI controller emulation on the nRF51 system-on-chip
SMBusDevice is accessible via I2CBus, at least for some I2C bus implementations.
* Currently I2C is entirely synchronous.  It would be nice to support asynchronous communication between the I2C master and the chardev, where the i2c-passthrough can hold down the I2C clock until linux-i2c has data ready. On the emulation side, this would require clock stretching support in i2c-passthrough.
 
If you are interested in device emulation especially, you could also implement an I2C adapter from scratch (e.g. the micro:bit TWI controller emulation on the nRF51 system-on-chip) if there's time.


This project will allow you to learn about the I2C bus and how to write device emulation code in QEMU.  You will enjoy it if you like working with physical hardware.
This project will allow you to learn about the I2C bus and how to write device emulation code in QEMU.  You will enjoy it if you like working with physical hardware.
Line 22: Line 25:
* Language: C
* Language: C
* Mentor: Paolo Bonzini <pbonzini@redhat.com> ("bonzini" on IRC), Stefan Hajnoczi <stefanha@redhat.com> ("stefanha" on IRC)
* Mentor: Paolo Bonzini <pbonzini@redhat.com> ("bonzini" on IRC), Stefan Hajnoczi <stefanha@redhat.com> ("stefanha" on IRC)
* Special requirements: you should already own already something like a Raspberry Pi
and an I2C device (for example a real-time clock and/or a Wii Nunchuk), some Dupont wires
(like [https://www.banggood.com/120pcs-20cm-Male-To-Female-Female-To-Female-Male-To-Male-Color-Breadboard-Jumper-Cable-Dupont-Wire-Combination-For-Arduino-p-974006.html these]), a soldering iron and header pins (like [these https://www.banggood.com/10-Pcs-40-Pin-2_54mm-Single-Row-Male-Pin-Header-Strip-For-Arduino-p-918427.html]).  It is important that you have these before the coding period begins; if you don't, take into account shipping and customs time, and/or talk to the mentors.

Revision as of 16:13, 25 March 2019

I2C Passthrough

Summary: Implement I2C device passthrough on Linux hosts so that a single board computer like a Raspberry Pi can be used to develop applications for microcontrollers like the micro:bit.

QEMU emulates I2C devices in software but currently cannot pass through real I2C devices from the host to the guest. It would be useful to access real I2C devices from inside the guest, for example for developers writing and testing software under QEMU on their computer. This would be used like -device i2c-passthrough,device=/dev/i2c-N,hostaddr=0x48 (another possibility is to implement Linux I2C device support as a character device, like -chardev linux-i2c,address=0x48,device=/dev/i2c-N,id=i2c-chardev -device i2c-passthrough,chardev=i2c-chardev,address=0x49.

A very basic implementation of I2C passthrough can be very simple (150-200 lines of code perhaps) using the read/write interface to /dev/i2c-N. However, read/write is very limited and cannot drive all I2C devices because it does not support repeated start conditions. The current I2C API in QEMU is also very limited. Therefore there are many possible extensions:

  • implementing I2C passthrough as an SMBusDevice instead of I2CSlave. SMBusDevice provides a higher-level interface than I2CSlave, with support for repeated start conditions and block transfers. (Question: how would the SMBusDevice API translate to /dev/i2c-N ioctls)?
  • improving SMBusDevice support in QEMU: currently the SMBusDevice->I2CSlave adaptor in hw/i2c/smbus_slave.c only implements a subset of SMBus, in particular it can only read a single byte at a time from the device. Your task could be to improve the QEMU I2CBus API so that all functionality of

SMBusDevice is accessible via I2CBus, at least for some I2C bus implementations.

  • Currently I2C is entirely synchronous. It would be nice to support asynchronous communication between the I2C master and the chardev, where the i2c-passthrough can hold down the I2C clock until linux-i2c has data ready. On the emulation side, this would require clock stretching support in i2c-passthrough.

If you are interested in device emulation especially, you could also implement an I2C adapter from scratch (e.g. the micro:bit TWI controller emulation on the nRF51 system-on-chip) if there's time.

This project will allow you to learn about the I2C bus and how to write device emulation code in QEMU. You will enjoy it if you like working with physical hardware.

Links:

Details:

  • Skill level: advanced (the project is not very difficult, but it is larger than usual)
  • Language: C
  • Mentor: Paolo Bonzini <pbonzini@redhat.com> ("bonzini" on IRC), Stefan Hajnoczi <stefanha@redhat.com> ("stefanha" on IRC)
  • Special requirements: you should already own already something like a Raspberry Pi

and an I2C device (for example a real-time clock and/or a Wii Nunchuk), some Dupont wires (like these), a soldering iron and header pins (like [these https://www.banggood.com/10-Pcs-40-Pin-2_54mm-Single-Row-Male-Pin-Header-Strip-For-Arduino-p-918427.html]). It is important that you have these before the coding period begins; if you don't, take into account shipping and customs time, and/or talk to the mentors.