vUSB interrupt latency and other realtime requirements

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
andi
Posts: 2
Joined: Sat Nov 03, 2012 7:36 pm

vUSB interrupt latency and other realtime requirements

Post by andi » Sat Nov 03, 2012 11:19 pm

Hi all,

I like to use vUSB to let a PC talk to an i²C multi-master bus and I want to use an ATTiny for that task (currently an ATTiny 85, but eventually an ATTiny 861).

(Note: the point is vUSB+multi-master I²C, I know that other people sucessfully used vUSB+single-master I²C.)

To get I²C master functionality with the ATTiny, much of it has to be implemented in software (using the USI).

The problem with multi-master on the USI is timing-control over the clock-pin: once SCL becomes high, the master should pull it down after about 4.7µs (+ a bit), otherwise another master may assume that the bus is free and may start sending data. However, any device on the bus may pull SCL down for any amount of time (called clock stretching), so the master cannot predict when SCL will go high.

Normaly one would just do busy-waiting on SCL or even setup a pin-change interrupt for this case. Neither will work with vUSB though. And neither will disabling interrupts.

In my current code, I have something like this (you may have seen similar code before):

Code: Select all

        do {
                usi_i2c_delay_low();
                cli();
                usi_clock_strobe();                             //SCL Positive Edge

                usi_i2c_wait_scl_high();

                usi_i2c_delay_high();
                usi_clock_strobe();                             //SCL Negative Edge

                sei();

        } while (!(USISR&(1<<USIOIF)));                         //Do until transfer is complete


(usi_i2c_delay_*() would busy-wait for a few µs, usi_i2c_wait_scl_high() would wait for SCL to go high for a few more µs, usi_clock_strobe() would toggle the clock pin)

Well, naivly disabling interrupts as in the above did not work with vUSB (occasionaly, the USB bus locked down, which is probably what is supposed to happen when you ignore the notice in the docs ...) To begin with, 4.7µs is more then the 12cycles @12MHz (≃ 2µs) vUSB could tollerate.

What I need to achive is to pull SCL low again once it became high, within a predictable time and without screwing up vUSB. It does not really matter how long SCL is low, and I can really live with low I²C transmission speeds (which means just the same). In this particular project, I have even control over the other masters on the bus - they run the same software - but a more general solution would be helpful.

Any suggestions, anyone ?

Ciao
Andi

Post Reply