Hi, I have two questions about the DMA engine on the KL25 — I'm hoping someone can help:
1. I would like to perform transfers from an array containing bytes to a peripheral register (TPM1_C0V). I thought this is exactly what SSIZE and DSIZE are for, so I set SSIZE to 8 bits and DSIZE to 32 bits:
DMA_DCR0 = DMA_DCR_EINT_MASK | DMA_DCR_ERQ_MASK | DMA_DCR_CS_MASK | DMA_DCR_SSIZE(0b01) | DMA_DCR_SINC_MASK | DMA_DCR_DSIZE(0x00);
I expected to be able to access single bytes from the source array, get them 0-padded to 32 bits by the DMA engine and get 32-bit writes to the target register. But what I actually get are 32-bit reads and 32-bit writes, e.g. on the first DMA request 4 bytes are copied from source to destination instead of one. The timer then truncates the write to 16-bits.
I've read and re-read the DMA section in the reference manual dozens of times and I can't see how this could be the intended behavior. If it is the expected behavior, how do I convert from source bytes to word writes?
2. I tried to implement a DMA ping-pong scheme, which proved unexpectedly hard. There is no half-way interrupt on the L series DMA engine. I wanted to use the other DMA channels in linked mode, to reconfigure things so that channels are switched. But then I found out that DMAMUX documentation says "Setting multiple CHCFG registers with the same Source value will result in unpredictable behavior". That is exactly what I need to do: I have one peripheral issuing requests, and wanted to have two channels, only one of which would have the ERQ bit set.
Having read that, I then tried to use *two* DMA channels for DMAMUX configuration changes. So the procedure would be roughly:
* DMA0 runs, upon completion links to DMA3,
* DMA3 writes a 0 to DMAMUX channel 0 and links to DMA4,
* DMA4 enables DMAMUX channel 1 with the appropriate source.
* DMA1 runs, upon completion links to DMA3 (which has hopefully been reconfigured in the meantime).
I tried this and it works. But I am still unclear on how the DMAMUX registers need to be accessed. Do I need to separately write the source, and then the enable bit, or is just a single write enough? Similarly for switching off: is a single 0-write enough?
Also, I'm wondering about the "unpredictable behavior" mentioned above. Is that really the case when only one of the channels is enabled for peripheral requests?
More generally, is there something I'm missing? A better way to have a ping-pong DMA scheme where one buffer can be prepared while the other gets sent?