gingardu:
la seriale ho gia visto che blocca anche le cose che adoperano gli interrupt bloccano
Con un AVR te lo scordi di non bloccare l'esecuzione del programma quando devi gestire i dati in arrivo da un bus, non importa se UART/SPI o I2C, dovrai sempre avere una ISR dedicata che esegue tutte le necessarie operazioni per ricevere il dato dalla periferica e gestirlo come serve.
Solo un processore dotato di DMA può ricevere, senza interrompere l'esecuzione del programma, una certa quantità di dati prima di avvisare la CPU che il pacchetto è pronto, e anche in questo caso il programma si deve fermare per gestire l'evento.
In tutti i casi l'I2C su Arduino è altamente bloccante, addirittura in caso di errori ti pianta letteralmente il micro, questo perché le relative routine sono state scritte basandosi sul polling, tramite while(), di determinati registri della I2C che se per un qualche motivo non raggiungono il valore atteso portano ad un loop di attesa eterno.
La seriale, UART hardware e non l'emulazione software, è il modo migliore per limitare le attese, viene gestita tramite interrupt e la gestione di ogni singola transazione richiede poco più di due us, la velocità media della loop() di Arduino è bassa, dipende molto da cosa contiene, ma anche nella migliore delle ipotesi, ciclo vuoto, richiede diversi us per essere eseguita quindi non vedo dove sta il problema.