Teensy 4.1 SPI slave - attachInterrupt on chip select broken?

Status
Not open for further replies.

PAAUX4

Well-known member
I am using the SPI slave code from here https://forum.pjrc.com/threads/58023-Teensy-4-as-SPI-Slave (KurtE #15) which works (sending data from SPI1 to SPI).

I want to add an interrupt on the slave chip select so there is a simple way to control longer SPI transactions. (eg. currentWord = 0; ), though there may be a better way to do this.

Adding
Code:
attachInterrupt(digitalPinToInterrupt(ChipSelectSlave), resetTransaction, FALLING); //with or without digitalPinToInterrupt
causes the transfer16 to return 0xffff every time and the rx_buffer is not getting filled. The interrupt function is not running either.

I tried doing it via the registers, but it looks like the GPIO interrupts are on the GPIO6/7/8/9 interrupt and I don't know how that corresponds to GPIO2 (IOMUX?).

If anyone can help, or can give me a clue, that would be great.

Code:
#include <DMAChannel.h>
#include <SPI.h>
#define PRREG(x) Serial.print(#x" 0x"); Serial.println(x, BIN) //Serial.println(x,BIN)
#define SAMPLES 1
#define ChipSelectSlave 10
#define CS_MASTER 0
volatile bool received_data = false;

DMAMEM static uint16_t rx_buffer[SAMPLES];
uint16_t loop_count = 0;

DMAChannel rx(false);

void rxISR() {
  rx.clearInterrupt();
  received_data = true;
  arm_dcache_delete(rx_buffer, SAMPLES); //delete Cache!
  LPSPI4_TDR = rx_buffer[0];
  asm volatile ("dsb");
}

bool initSPISlaveDMA() {
  rx.begin(true);
  rx.source((uint16_t &) LPSPI4_RDR);
  rx.triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI4_RX);
  rx.attachInterrupt(rxISR);
  rx.interruptAtCompletion(); //TCD->CSR |= DMA_TCD_CSR_INTMAJOR;
  rx.destinationBuffer(rx_buffer, SAMPLES + 1);
  rx.enable();
  return 1;
}

bool initSPISlave() {
  LPSPI4_CR &= ~LPSPI_CR_MEN; //Modul ausschalten
  LPSPI4_CR = LPSPI_CR_RST; //Master Logic reset! (Control Register => Software Reset)
  LPSPI4_CR &=  ~LPSPI_CR_RST; //Master Logic reset! (Control Register => Software Reset)
  LPSPI4_TCR = LPSPI_TCR_FRAMESZ(15); //16Bit Mode
  LPSPI4_DER = LPSPI_DER_RDDE; //RX DMA Request Enable
  LPSPI4_CR |= LPSPI_CR_MEN; //Enable SPI Module!
  return 1;
}
volatile int resetCounter = 0;
void resetTransaction(){
	resetCounter++;
	asm volatile ("dsb");
}


void setup() {
  // I am going to use SPI1 as the master.
  SPI1.begin(); // initialize it... 
  pinMode(CS_MASTER, OUTPUT);
  digitalWrite(CS_MASTER, HIGH);
  
  Serial.begin(115200);
  SPI.begin();
  SPI.setCS(ChipSelectSlave);
  
  attachInterrupt(digitalPinToInterrupt(ChipSelectSlave), resetTransaction, FALLING);

  while (!Serial);

  Serial.println("Init SPI!");
  if (initSPISlave()) {
    Serial.println("SPI SLAVE init!");
  }
  if (initSPISlaveDMA()) {
    Serial.println("DMA Channel init!");
  }
  
  
}

void loop() {
  elapsedMicros emloop = 0;
  received_data = false;
  digitalWrite(CS_MASTER, LOW);
  SPI1.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  uint16_t received_data = SPI1.transfer16(loop_count);
  SPI1.endTransaction();
  while (!received_data && (emloop < 250000)) ;
  Serial.printf("SPI Transfer: %x Return: %x SPI DMA: %x delay: %d rc: %d\n", loop_count, received_data, rx_buffer[0], (uint32_t)emloop, resetCounter);
  delay(250);
  loop_count++;
}

Thank you in advance.
 
longer SPI transactions, like continuous data flow? I don't know much about the DMA but I think it's not good for continuous transfers?
 
Nothing fancy like that. Just a series of single transfers to transfer more than one word/16 bits. I don't even need DMA really but the example came with it.
 
Status
Not open for further replies.
Back
Top