MCollins-Lowell
New member
For an application where a number of SPI-based inertial sensors must be sampled at intervals of 1 ms or less, we could benefit from asynchronous operations involving two SPI modules, with a second transfer initiated while the first is in progress. Based upon information in this thread, along with another referenced within, this appears to be possible. At present, the system is fully functional with up to four sensors interfaced through SPI0 operating synchronously, however we hope to expand capabilities to eight ports.
I've been working for some time now to utilize the non-blocking 8-bit method KurtE describes in the thread referenced above, with only limited success. While it appears that the call to SPI.transfer() returns immediately, a simple semaphore operation in my callback evidently does not execute. I suspect that the problem may be related to invalid assignment of the callback function.
To demonstrate the issue, I've generated a simple example sketch with extraneous diagnostic output. Because the system I'm using for development is remote, I added watchdog reset capability since some of my test cases have put the Teensy into a state where the Arduino IDE cannot recover. In the sketch, flow stalls indefinitely while waiting for bit 0 in the semaphore word to be reset.
A related question. In my code, I reverse the byte order of a 32-bit COPI word and store it into a four-byte array, then pass the address of the array along with a count value of 4 to SPI.transfer. Am I correct in assuming that four 8-bit transfers will be completed before the callback is invoked, with CIPO data stored in the corresponding rxData array?
Any assistance would be most appreciated.
-- Mike --
I've been working for some time now to utilize the non-blocking 8-bit method KurtE describes in the thread referenced above, with only limited success. While it appears that the call to SPI.transfer() returns immediately, a simple semaphore operation in my callback evidently does not execute. I suspect that the problem may be related to invalid assignment of the callback function.
To demonstrate the issue, I've generated a simple example sketch with extraneous diagnostic output. Because the system I'm using for development is remote, I added watchdog reset capability since some of my test cases have put the Teensy into a state where the Arduino IDE cannot recover. In the sketch, flow stalls indefinitely while waiting for bit 0 in the semaphore word to be reset.
C-like:
#include <stdio.h>
#include <SPI.h>
#include "Watchdog_t4.h"
#define spi_fSCLK 1000000
#define spi_bitOrder MSBFIRST
#define spi_Mode SPI_MODE0
/*
* Global semaphore word
*/
volatile unsigned int stStat;
/*
* Global eventResponder object
*/
EventResponder erSPI;
WDT_T4<WDT3> wdt;
/*
* COPI data for SPI transfer sequence
*/
unsigned int txData[] = {
0x20012005,
0x20010034,
0x20010013,
0x30000000,
0x30002000,
0x30000000,
0 // end of sequence marker
};
/*
* Watchdog timer callback function
*/
void cbWDT() {
printf("Watchdog timeout -- system reset imminent\r\n");
}
/*
* SPI callback function
*
* Simply clears bit 0 in semaphore word
*/
void cbSPI(EventResponderRef eventResponder) {
extern volatile unsigned int stStat;
stStat &= ~1;
return;
}
void setup() {
/*
* Configure watchdog timer to reset MCU if loop stalls
*/
WDT_timings_t config;
config.timeout = 8000;
config.callback = cbWDT;
wdt.begin(config);
Serial.begin(1000000);
delay(4000);
SPI.begin();
SPI.beginTransaction(SPISettings(spi_fSCLK, spi_bitOrder, spi_Mode));
erSPI.attach(cbSPI);
printf("SPI transfer demo, 2025-09-08, r09\r\n");
}
void loop() {
extern volatile unsigned int stStat;
extern unsigned int txData[];
unsigned char rxByte[4];
unsigned char txByte[4];
int byteCount;
int loopCount;
int wordCount;
unsigned int rxData;
unsigned int *txdPtr;
loopCount = 0;
do {
printf("loopCount: %d\r\n", loopCount);
wordCount = 0;
txdPtr = txData;
/*
* Reverse txData byte ordering
*/
do {
txByte[0] = (*txdPtr >> 24) & 0xff;
txByte[1] = (*txdPtr >> 16) & 0xff;
txByte[2] = (*txdPtr >> 8) & 0xff;
txByte[3] = *txdPtr & 0xff;
printf(" txData[%d]: 0x%.8x\r\n", wordCount, *txdPtr);
for (byteCount = 0; byteCount < 4; ++byteCount)
printf(" txByte[%d]: 0x%.2x\r\n", byteCount, txByte[byteCount]);
/*
* Set semaphore bit
*/
stStat |= 1;
printf(" SPI.transfer(0x%x, 0x%x, %d, 0x%x)\r\n",
(unsigned int) &txByte[0], (unsigned int) &rxByte,
(size_t) 4, (unsigned int) cbSPI);
SPI.transfer((const void *) &txByte[0], (void *) &rxByte[0],
(size_t) 4, erSPI);
/*
* Wait for status bit to be cleared in callback function
*/
printf("Awaiting semaphore change of state...\r\n");
while (stStat != 0)
;
/*
* Assemble rdData word from byte array
*/
rxData = (rxByte[3] << 24) + (rxByte[2] << 16) +
(rxByte[1] << 8) + rxByte[0];
printf("wordCount: %d, txData: 0x%.8x, rxData: 0x%.8x\r\n",
wordCount, *txData, rxData);
++wordCount;
++txdPtr;
} while (*txdPtr != 0);
delay(2000);
printf("Watchdog reset\r\n");
wdt.feed();
} while (1);
}
A related question. In my code, I reverse the byte order of a 32-bit COPI word and store it into a four-byte array, then pass the address of the array along with a count value of 4 to SPI.transfer. Am I correct in assuming that four 8-bit transfers will be completed before the callback is invoked, with CIPO data stored in the corresponding rxData array?
Any assistance would be most appreciated.
-- Mike --