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
Post a Comment