Hello,
I'm using S32K148EVB board.
The SW uses:
- FreeRTOS
- SPI slave (spi_pal with lpspi0 using DMA)
- additional Output pin PTA30 for Spi Slave to request the master to start SPI communication
- additional Input pin PTA6 for Spi Slave, connected to SPI CS pin and configure as interrupt
Sending data from Slave to Master works fine.
Detecting CS pin change with PTA6 Interrupt works fine.
Our application protocol starts with 1 byte with value 0x55 and as variable length (with lenght indicated in the payload).
For reception I'm calling API SPI_SlaveTransfer(SPI_INSTANCE, slave_send, slave_receive, BUFFER_SIZE) and wait for the master to poll the SPI.
The issue is that we don't know in advance the size of the packet that the master will send.
So the spi callback will not be triggered unless all the bytes are received.
What would be the best solution for our case (being able to receive any length, any time)? Should we wait for CS to be disabled before reading the DMA rx buffer?
I would like to avoid modifying as much as possible the spi_pal and lpspi drivers provided in the SDK.
There seems to be no clear answer from all the NXP Community thread I read:
my first thread: https://community.nxp.com/message/1160105
https://community.nxp.com/message/1123908
https://community.nxp.com/message/1068750
Solved! Go to Solution.
Hi,
So when pin interrupt occurs you can't get all frames?
I suppose the root cause is the interrupt priorities. Pins interrupt priority is higher than lpspi interrupt. In this case when you get the rising edge on PCS some SPI frames are still in the hardware fifo.
Can you try to use interrupt manager API to change the interrupts priorities for LPSPI and pins?
Best regards,
Razvan
Hi all,
is this true also for dspi on MK6x kinetis microcontrollers with or without DMA enabled? To enable variable message len on dspi slave we need to use an external GPIO to signal received message has been totally sent?
Thank you,
Michele
We are using the following configuration for interrupt
Any combinaison will give the same result.
FreeRTOSConfig.h:
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0F
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
Changing Interrupt priority like this will do the job:
Calling the LPSPI_DRV_SlaveTransfer function direclty in the IRQ handler will lost the first received byte. To avoid this, we call the LPSPI_DRV_SlaveTransfer right after the transmission is complete (CS pin disabled) so it is ready for next time.
Hi,
Ok I didn't know this that you are using the DMA mode, but the point is to abort the transfer only when you are sure that you have processed all frames.
Sorry for this workaround, but from hardware perspective is hard to know when to finish the transfer.
Best regards,
Razvan
Hello,
We have implemented the CS pin detection IRQ. The CS pin state change works fine.
In the IRQ handler we are doing the following:
static void spi_cs_detection(void)
{
if(bIsSpiCsPinActive()==true)
{
LPSPI_DRV_SlaveAbortTransfer(SPI_OVER_LPSPI00_INSTANCE);
memset(slave_receive, 0xFF, BUFFER_SIZE);
memset(slave_send, 0xFF, BUFFER_SIZE);
LPSPI_DRV_SlaveTransfer(SPI_OVER_LPSPI00_INSTANCE, slave_send, slave_receive, BUFFER_SIZE);
}
else
{
LPSPI_DRV_SlaveAbortTransfer(SPI_OVER_LPSPI00_INSTANCE);
LPSPI_DRV_ReadRXBuffer(SPI_OVER_LPSPI00_INSTANCE);
}
PINS_DRV_ClearPinIntFlagCmd(SPI_CS_PORT, SPI_CS_PIN);
}
Problem is, the rxBuff is always truncated:
Also, we always get a LPSPI_TRANSMIT_ERROR in the LPSPI_DRV_SlaveIRQHandler:
Hi,
So when pin interrupt occurs you can't get all frames?
I suppose the root cause is the interrupt priorities. Pins interrupt priority is higher than lpspi interrupt. In this case when you get the rising edge on PCS some SPI frames are still in the hardware fifo.
Can you try to use interrupt manager API to change the interrupts priorities for LPSPI and pins?
Best regards,
Razvan
Hi,
The solution for your problem is on second post.
Because the LPSPI hardware doesn't have any method to detect when CS is negated you must use another GPIO pin to monitor CS pin and when the transfer is done (CS switch from low to high) you can call transfer abort function.
Best regards,
Razvan