Skip to content

Add configurable framesize for SPI DMA transactions on T4#70

Open
natecermak wants to merge 1 commit intoPaulStoffregen:masterfrom
natecermak:nc-add-configurable-framesize
Open

Add configurable framesize for SPI DMA transactions on T4#70
natecermak wants to merge 1 commit intoPaulStoffregen:masterfrom
natecermak:nc-add-configurable-framesize

Conversation

@natecermak
Copy link
Copy Markdown

@natecermak natecermak commented Jan 8, 2025

This PR makes the asynchronous DMA-driven SPI.transfer() for the Teensy 4.x take an additional argument for the size of the frame to be transmitted, which can range from framesize=7 (8 bit transmit) to framesize=31. If framesize=32 or greater, SPI.transfer() will return false. If the framesize is 7 or smaller, buffers are uint8. If framesize is 8-15, buffers are uint16. If framesize is > 16, buffers should be uint32. This PR does not support frame sizes beyond 32 bits (though theoretically the chip can support it).

This PR does not change the behavior of the library for any other overloaded variant of the SPIClass::transfer function, and it does not change the behavior for any other boards other than the Teensy 4.x

Questions:

  • Do all Teensy's need to have the same interface (do I need to update T3 code blocks?)
  • Do non-DMA transfer calls also need to have this option for consistency?
  • Does the following need to be updated? Not sure, need to understand this section better...
	if (count < 2) {
		// Use non-async version to simplify cases...
		transfer(buf, retbuf, count);
		event_responder.triggerEvent();
		return true;
	}
	// lets clear cache before we update sizes...
	if ((uint32_t)buf >= 0x20200000u)  arm_dcache_flush((uint8_t *)buf, count);
	if ((uint32_t)retbuf >= 0x20200000u)  arm_dcache_delete(retbuf, count);

	// Now handle the cases where the count > then how many we can output in one DMA request
	if (count > MAX_DMA_COUNT) {
		_dma_count_remaining = count - MAX_DMA_COUNT;
		count = MAX_DMA_COUNT;
	} else {
		_dma_count_remaining = 0;
	}

Tests:

Test 1: running with no additional parameter passed:

#include <SPI.h>
#include <EventResponder.h>

#define BUF_SIZE 100
uint8_t spi_tx_buf[BUF_SIZE];
uint8_t spi_rx_buf[BUF_SIZE];
EventResponder event_responder;
volatile bool dma_busy;

void asyncEventResponder(EventResponderRef event_responder) {
  dma_busy = false;
  SPI.endTransaction();
}

void setup() {
  for (int i = 0; i < BUF_SIZE; i++) spi_tx_buf[i] = i;
  SPI.setCS(10); // T4.1 pin 10 is default CS
  SPI.begin();  
  event_responder.attachImmediate(&asyncEventResponder);
}

void loop() {
  dma_busy = true;
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));   // avg 400ns/byte
  SPI.transfer(spi_tx_buf, spi_rx_buf, sizeof(spi_tx_buf), event_responder);
  while (dma_busy)
    delay(1);
}

Oscilloscope output:
image


Test 2: 14-bit output

Code is as before, but buffers are uint16_t and SPI.transfer line is:

SPI.transfer(spi_tx_buf, spi_rx_buf, sizeof(spi_tx_buf), event_responder, 13);

Output:
image


Test 3: 24-bit output

Again, same as before but with uint32_t buffers and the SPI.transfer() call is:

SPI.transfer(spi_tx_buf, spi_rx_buf, sizeof(spi_tx_buf), event_responder, 23);

Output:
image

@natecermak natecermak marked this pull request as ready for review January 9, 2025 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant