Longan Nano : I2C Master

 After SPI, serial and Gpio, the next building block is I2C/Master.

That one is a bit peculiar.





Overview/DMA

It is actually a finite state machine. 

Each transition of a I2C transmission is associated with  an event, with a corresponding "event" interrupt.

The sequence is StartSent-AddressSent-DataDataData-BTC-Stop

Simple enough.

Where it becomes tricky is when you want to use DMA with it. You have to manage two interrupts source in parallel. It ends up as  : 

1- Do the beginning as usual, using  plain I2C interrupt events.

2- When reaching the "data" stage, start a DMA transfer + disable I2C event interrupt

(we trigger the DMA transfer only if the # of data is > 2, else we do it using basic interrupts)

3- When the DMA stage is done, re-enable the I2C event interrupts  to finish the transfer


To give an example:  to refresh the SSD1306 screen in one step (1024 bytes), we only need ~ 6 interrupts ( 5 I2C + 1 DMA) rather than ~ 1030 interrupts in plain i2c interrupt mode.


I did not find the event attached to the Stop condition, so it is done in polling mode at the moment.

Multiwrite

There is a second change compared to the simple Arduino Api : Multiwrite

You can send a list of data chunks as a single transfer.

That is very helpful to avoid copying data just to add a header.

SSD1306 example : When updating the screen with the SSD1306, you have to add a command byte in front of the raw data. That makes using DMA difficult and/or lead to duplicating the data.

Using the multiwrite, we'll just do a multiwrite made of 2 chunks : The command byte then the screen internal buffer.  That will be sent inside a single transfer. No need to duplicate data, we can send the whole buffer in one go.

Other Problem

A more general problem was spotted : DMA channels.

The DMA channels are shared among several peripherals, each of them is hardwired to a few peripherals usage.

So far it is more or less statically used. When you use SPI0,  the underlying dma channels are automatically initialized and used. 

The problem arises when using too many peripherals :  they will collide in terms of DMA channels.

It should be a more dynamic process, where the DMA channels  are allocated on the fly, only upon usage (with the associated mutex), so that they can coexist peacefully.


The mandatory SSD1306 demo pic : 







Comments

Popular posts from this blog

Component tester with STM32 : Part 1 ADC, Resistor

Fixing the INA3221

INA3221, weird wiring