Thought that while I have been playing around with trying to make an Async version of SPI transfer method, I have run into a few different issues with DMA and some of them impact this library as well, so I thought I would mention some of them here. More info up on a couple other threads including:
https://forum.pjrc.com/threads/43048-How-best-to-manage-multiple-SPI-busses and
https://forum.pjrc.com/threads/43585-Teensy-3-5-SPI-DMA
a) Teensy LC - Does not work at all with Dma on current release - The system would at times do 8 bit or 16 bit transfer to a 32 bit register which must be accessed 32 bits and faults... TNI put in PR into core project. I also put in PR (
https://github.com/PaulStoffregen/cores/pull/242) with this and a few other DMA issues.
b) Once it get a) working, I am running into issues on SPI1, where when you disable SPI1 (before CS call) and then reenable, there appears to be a clock pulse which is causing the data to get corrupted. I have a version of your test program that I hacked up for SPI1... I set jumper to 0-1 and the buffers don't match.
Code:
Hi!
Buffers are prepared
Time for non-DMA transfer: 276us
src and dest match
Press a key to continue
DmaSpi::begin() : DmaSpi::start() : state_ = eStopped
DmaSpi::beginNextTransfer: no pending transfer
Transfer @ 0x20001774
Testing src -> dest, single transfer
--------------------------------------------------
Transfer @ 0x200017ac
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
real sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffe74 64 a01a0080
TX: 1fffff3c 40077006 64 20520080
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001774
state = eRunning
DmaSpi::beginNextTransfer: no pending transfer
Finished DMA transfer
src and dest don't match
src: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63
dest: 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62
==================================================
Testing src -> discard, single transfer
--------------------------------------------------
Transfer @ 0x200017ac
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
dummy sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffe50 64 a0120080
TX: 1fffff3c 40077006 64 20520080
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001774
state = eRunning
DmaSpi::beginNextTransfer: no pending transfer
Finished DMA transfer
last discarded value is 0x61
That appears to be wrong, it should be src[DMASIZE-1] which is 0x63
==================================================
Testing 0xFF dummy data -> dest, single transfer
--------------------------------------------------
Transfer @ 0x200017ac
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
real sink
dummy source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffe74 64 a01a0080
TX: 20001784 40077006 64 20120080
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001774
state = eRunning
DmaSpi::beginNextTransfer: no pending transfer
Finished DMA transfer
src and dest don't match
src: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
dest: 0x62 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
==================================================
Testing multiple queued transfers
--------------------------------------------------
Transfer @ 0x200017ac
Transfer @ 0x20001790
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
real sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffe74 64 a01a0080
TX: 1fffff3c 40077006 64 20520080
DmaSpi::registerTransfer(0x20001790)
DmaSpi::addTransferToQueue() : queueing transfer
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001774
state = eRunning
DmaSpi::beginNextTransfer: starting transfer @ 0x20001790
this was the last in the queue
real sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffed8 64 a01a0080
TX: 1fffff3c 40077006 64 20520080
Finished DMA transfer
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001790
state = eRunning
DmaSpi::beginNextTransfer: no pending transfer
Finished DMA transfer1
src and dest don't match
src: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63
dest: 0xff 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61
src and dest don't match
src: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63
dest: 0x62 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61
==================================================
Testing pause and restart
--------------------------------------------------
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
real sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffe74 64 a01a0080
TX: 1fffff3c 40077006 64 20520080
DmaSpi::registerTransfer(0x20001790)
DmaSpi::addTransferToQueue() : queueing transfer
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001774
state = eStopping
Time until stopped: 249 us
Finished DMA transfer
DMA SPI appears to have stopped (this is good)
restarting
DmaSpi::start() : state_ = eStopped
DmaSpi::beginNextTransfer: starting transfer @ 0x20001790
this was the last in the queue
real sink
real source
post_cs S C1 C2: 20 50 24
RX: 40077006 1ffffed8 64 a01a0080
TX: 1fffff3c 40077006 64 20520080
DmaSpi::rxIsr_()
finishCurrentTransfer() @ 0x20001790
state = eRunning
DmaSpi::beginNextTransfer: no pending transfer
Finished DMA transfer1
src and dest don't match
src: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63
dest: 0x62 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61
src and dest don't match
src: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63
dest: 0x62 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61
==================================================
Testing src -> dest, with chip select object
--------------------------------------------------
Transfer @ 0x200017ac
DmaSpi::registerTransfer(0x20001774)
DmaSpi::addTransferToQueue() : queueing transfer
starting transfer
DmaSpi::beginNextTransfer: starting transfer @ 0x20001774
this was the last in the queue
real sink
real source
c) on Teensy 3.x boards, if you do a 16 bit transfer just before you do a DMA transfer, your transfer will screw up. That is if in your dma example program you add a call: like:
Code:
SPI.transfer16(0xffff);
DmaSpi::Transfer trx(nullptr, 0, nullptr);
That is because the high word will be still set to 16 bit mode and all of your one byte writes to PUSHR will output two bytes on the buss... In my SPI version, what I did to resolve this was to have my library code do it's own PUSHR of the first users data byte with CTAR0 and also CONT bit so the transfer then actually runs faster. (Code up in my SPI fork/branch)
d) Teensy 3.5 with SPI1/2 - I was interested in getting async operations to work here as well. But SPI1 and SPI2 only have one DMA_SOURCE for SPI1 or SPI2, these can be used for TX or RX but not both at the same time. My current version does a couple of things depending on if it is TX only, RX only or a transfer. Currently in all cases I am using the DMA channel for TX, although may change later.
1) TX only operation - I setup to only set the DMA to do WRITES, I setup to interrupt when this completes, and I then toss data from RX queue. However this had problem that it would return before all data was sent, so if user changes CS there was problem. So the code now does not have the DMA send the last byte, but instead the interrupt handler here, then issues the PUSHR with EOQ flag, and I have an SPI interrupt handler which receives the EOQ interrupt and then does the appropriate stuff for the end.
2) RX and Transfer - I have simple SPI interrupt handler which processes the interrupt for stuff in RX Fifo and processes it... May change this later to have TX as interrupt and RX as DMA channel as if the interrupts are not processed fast enough then maybe some RX data is lost, but if we are slow to process TX, it should hopefully just slow the operation...
That is all for now.