|
|
há 3 dias atrás | |
|---|---|---|
| firmware | há 3 dias atrás | |
| host | há 3 dias atrás | |
| .gitignore | há 3 dias atrás | |
| README.md | há 3 dias atrás |
USB to I2C master for ATmega8U2. No LUFA, no interrupts: ~3.6 KB flash. Composite device with two independent ways in:
host/usbi2c.py).i2c-tiny-usb vendor interface (EP0 control requests only): the mainline Linux i2c-tiny-usb
driver registers it as a normal kernel I2C adapter (/dev/i2c-N, i2c-tools, kernel client drivers).
Windows 10/11: binds inbox usbser.sys automatically (no driver/INF). Windows 7/8 need a stock CDC INF.
Windows: the vendor (i2c-tiny-usb) interface has no driver and shows up as an unknown device; harmless.
Linux: cdc_acm -> /dev/ttyACMx. Add the udev rule below so ModemManager does not probe it.
I2C is bit-banged (the 8U2 has no TWI): SCL=PD3, SDA=PD2, open drain. External pull-ups (2.2-4.7 k to 5 V) are required.
Default 400 kHz (set_delay(0), the maximum); each step adds 0.375 us per SCL period
(5 = 235 kHz, 10 = 163 kHz, 47 = 50 kHz). Timing is cycle-counted from the generated code:
data bits meet Fast-mode tLOW >= 1.3 us and tHIGH >= 0.6 us, reads run at ~314 kHz.
Clock stretching supported; stuck-SDA bus recovery runs automatically before a transaction.
cd firmware
make
make fuses # once: external crystal, CKDIV8 off (lfuse FF hfuse D9 efuse F4 - same as Arduino Uno 8U2)
make flash
Without the crystal fuse the chip runs from the 8 MHz/8 RC and USB will not enumerate.
Flashing over ISP overwrites any DFU bootloader. Use make VBUS=1 if PB6 carries a VBUS sense
(attach to USB only while PB6 high); not needed for a bus-powered board.
| Request | Reply |
|---|---|
A5 01 addr wlen rlen wdata.. (I2C xfer, 7-bit addr, <=32 B per phase; wlen&rlen>0 = repeated START; both 0 = probe) |
status [rdata] |
A5 02 n set SCL delay |
status |
A5 03 ping |
00 proto maxlen |
A5 04 bus recovery |
status |
Status: 0 OK, 1 NACK addr, 2 NACK data, 3 bus error, 0x10 bad op, 0x11 bad length. Bytes outside a frame are ignored and a stalled frame is dropped after ~100 ms.
Speed: a USB bulk round trip is ~1 ms, so unbatched transactions are ~1000/s. Pipeline
many frames in one write (Bridge.batch): the device answers a whole 64-byte OUT packet with one IN packet.
pip install pyserial
python host/usbi2c.py COM5 # or /dev/ttyACM0 : scan, blink port 0, benchmark
from usbi2c import Bridge, TCA9539
io = TCA9539(Bridge("COM5"), 0x74) # A1/A0 select 0x74..0x77
io.set_direction(0xFF00); io.write(0x00AA); print(hex(io.read()))
Linux udev (/etc/udev/rules.d/99-usbi2c.rules):
SUBSYSTEM=="tty", ATTRS{idVendor}=="1c40", ATTRS{idProduct}=="0534", ENV{ID_MM_DEVICE_IGNORE}="1", MODE="0666"
SUBSYSTEM=="i2c-dev", ATTRS{idVendor}=="1c40", ATTRS{idProduct}=="0534", MODE="0666"
VID/PID 1c40:0534 is the EZPrototypes i2c-tiny-usb ID, used so the stock kernel driver binds
without changes. It is not ours: development use only, change it in usb.c for anything shipped
(then bind with echo VID PID > /sys/bus/usb/drivers/i2c-tiny-usb/new_id).
Kernel config: CONFIG_I2C_TINY_USB=m (Device Drivers > I2C > I2C Hardware Bus support >
Tiny-USB adapter) and CONFIG_I2C_CHARDEV for /dev/i2c-N.
modprobe i2c-tiny-usb delay=1 # delay=N: SCL half period in us, rounded to the slower side
i2cdetect -l # "i2c-tiny-usb at bus 00X device 00Y"
i2cdetect -y N
delay: 0 or 1 = 400 kHz (the maximum), 2 = 235 kHz, 10 (driver default) = 50 kHz.
It is sent when the driver binds. The kernel interface and the CDC set_delay command keep separate settings.
Kernel client drivers work too, e.g. TCA9539 (needs CONFIG_GPIOLIB + CONFIG_GPIO_PCA953X):
echo tca9539 0x74 > /sys/bus/i2c/devices/i2c-N/new_device.
Notes:
cdc_acm keeps interfaces 0/1 (grouped by an IAD, which i2c-tiny-usb refuses); i2c-tiny-usb
gets interface 2. Both can be used at the same time: while a kernel transaction is open
(START sent, no STOP yet) CDC requests wait; an abandoned transaction is dropped after ~100 ms.i2c_msg costs two control transfers, so a register read is ~4 ms. Use the CDC path for bulk work.-ENXIO; data NAK or bus error -> -EIO. No 10-bit addresses, no protocol mangling.