SPI.dmaSendAsync() has been added to SPI

Information on the latest releases
stevestrong
Posts: 2043
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by stevestrong » Mon Jun 12, 2017 12:33 pm

RogerClark wrote:@stevestrong
Do you mean the buffer copy I do after the dmaSendAsync ?
I meant line 100 of show() function.

User avatar
RogerClark
Posts: 7680
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by RogerClark » Mon Jun 12, 2017 10:11 pm

stevestrong wrote:
RogerClark wrote:@stevestrong
Do you mean the buffer copy I do after the dmaSendAsync ?
I meant line 100 of show() function.
Steve...

Do you mean, just line 100 or also line 94?

Originally I did not copy the buffers at all, however when I ran the example to test the code, I found that things like the colorWipe() effect did not work correctly.

I initially thought I had messed up with the buffer pointer position etc, and I spent several hours sending data patterns and checking with my logic analyser.

But I eventually realised that some of the colour effects rely on building the contents of the buffer progressively, and call show() repeatedly during the construction.

But when there are 2 independent frame buffers, the effects no longer work correctly, as each frame of the sequence ( effect ) builds on the data from frame - 2.

So.. I have to waste time copying the buffer. However I do the buffer copy just after the DMA transfer is started.

I cant use DMA for this memory copy, as I would still have to wait for completion, and I suspect because of checking the DMA status reg etc, it would be slower than calling memcpy.

But I could pad the frame buffer to 4 bytes as this may speed things uo by allowing 32 bit copies if I use my own code for this.

stevestrong
Posts: 2043
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by stevestrong » Tue Jun 13, 2017 7:36 am

Yeah, managing double buffer is not always trivial, so it makes sense what you did.

victor_pv
Posts: 1855
Joined: Mon Apr 27, 2015 12:12 pm

Re: SPI.dmaSendAsync() has been added to SPI

Post by victor_pv » Wed Jun 14, 2017 2:56 am

Roger, I had finished writing non-blocking DMA with callback as planned in another thread a while back, but just needed to clean up the code and upload.
It added 2 more functions to set the callback functions (1 for send, 1 for transfer/receive). When the callback is Null, it blocks, when is not Null it doesn't block and instead calls the call back upon transfer completion.
It also allows for repeating the same transfer from the same base address for the buffer, only sets the number of transfers and fires.
I will upload tomorrow so you can take the pieces and test. Between one thing and another I have been leaving that behind just because of wanting to clean the code.
It broke the functions in:
dmaSend :same as now, but allows blocking and non-blocking)
dmaSendSet :set DMA transfer parameters and peripherals but does not enable the channel)
dmaSendRepeat :set DMA count and initiate transfer.

So you could call dmaSendSet once with the buffer base address, and that will set the DMA peripheral, then call dmaSendRepeat repeatedly to send different or the same lenghts of from the buffer base address.

Additionally I converted the whole dma setting part to using the dma tubes, the latest API from leaflabs adding F4 support, but I believe Steven made the dma functions work in the F4 with the old API, so that part is not really needed.

Anyway I will try tomorrow to clean up from commmented code and upload them, may add a bit more functionallity on top of the Async one.
I tested them with a display and sdFat and seemed to work reliably.

User avatar
RogerClark
Posts: 7680
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by RogerClark » Wed Jun 14, 2017 3:05 am

Thanks Victor

No rush.

BTW. I have accepted a PR from @stevestrong for SPI changes last week, so I don't know if this will impact your work (sorry) ;-(

stevestrong
Posts: 2043
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by stevestrong » Wed Jun 14, 2017 8:41 am

I think Victor's changes will not affect my changes, so merging will be possible.

Indeed, I adapted the dma_setup_transfer() function for F4.
I did this because the version using "dma_tube" is much more run-time consuming than "dma_setup_transfer()" (declared as inline), and does not bring any visible advantage.

You most probably know this, I just want to point out that the non-blocking DMA functions have the restriction that they need double (multiple) buffering mechanism: while one buffer is transferred by the DMA, this buffer must not be touched. The other buffer(s) can be setup for the next transfer.
Also, the CB functions must be planned very carefully not to overlap/disturb each other.

racemaniac
Posts: 691
Joined: Sat Nov 07, 2015 9:09 am

Re: SPI.dmaSendAsync() has been added to SPI

Post by racemaniac » Wed Jun 14, 2017 9:03 am

stevestrong wrote:You most probably know this, I just want to point out that the non-blocking DMA functions have the restriction that they need double (multiple) buffering mechanism: while one buffer is transferred by the DMA, this buffer must not be touched. The other buffer(s) can be setup for the next transfer.
Also, the CB functions must be planned very carefully not to overlap/disturb each other.
I understand what you guys are talking about, but don't quite agree. If you're only looking at the neopixels, only doublebuffering will indeed make max use of the async nature of the DMA.
My first versions of the lightsaber were from the viewpoint of async neopixel transmission were probably like this: <fill neopixel buffer> <async transmit the neopixel buffer> <while transmitting, many other processes are running such as processing motion sensor data, processing sound, managing data coming from sd card/memory chip> <when done transmitting, fill the buffer again (should be very quick)> <transmit async again>
If you're also doing other stuff that really requires the cpu, even single buffering can give you a lot of gains when using non blocking DMA.

User avatar
RogerClark
Posts: 7680
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by RogerClark » Wed Jun 14, 2017 10:04 am

I think we are all in agreement that an async DMA SPI function has its uses, and should stay in the SPI library.

Its just that for some applications e.g. sending to the ILI9341 display, it doesn't help for most operations.
One reason for it not helping that display, is because we overclock both the STM32's SPI and also the display, i.e at DIV2, so that individual transfers don't take that long.

racemaniac
Posts: 691
Joined: Sat Nov 07, 2015 9:09 am

Re: SPI.dmaSendAsync() has been added to SPI

Post by racemaniac » Wed Jun 14, 2017 11:21 am

RogerClark wrote:I think we are all in agreement that an async DMA SPI function has its uses, and should stay in the SPI library.

Its just that for some applications e.g. sending to the ILI9341 display, it doesn't help for most operations.
One reason for it not helping that display, is because we overclock both the STM32's SPI and also the display, i.e at DIV2, so that individual transfers don't take that long.
i know :), i see you guys are pro it :). but sometimes the discussions seems to be missing the point that even while for that peripheral you're using DMA for when still doing things sequentially, that doesn't mean there aren't huge benefits :). One of the main questions on the arduino forum is people struggling with doing multiple tasks at the same time (but in their case the answer usually is "blink without delay" ^^). But if you need to do a lot of IO, even if for one specific port you're still doing things sequentially, being able to do other stuff while the DMA is running can make a huge difference :).

stevestrong
Posts: 2043
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: SPI.dmaSendAsync() has been added to SPI

Post by stevestrong » Wed Aug 02, 2017 6:05 pm

Victor, working on the OV7670 project I used the dmaSendAsync function.
I would welcome a kind of "how to " for all newly implemented functions.
Moreover, to the sendAsync function I would add as an additional parameter a CB function to be executed when the sending is finished.

Post Reply