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
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.
Thank you in advance.
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
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.