Hello,
I am using the microcontroller LPC55S69 to communicate with a device via SPI, using DMA.
The device is spitting data every 2ms, and i am saving it automatically in each descriptor.
I have 4 descriptors, when descriptor 2 concludes saving the data, i want it to flag intA, and when descriptor 4 finished filling the data in the buffer i want it to flag intB.
I have the following callback functions:
void SPI_DMA_master_callback(SPI_Type *base, spi_dma_handle_t *masterHandle, status_t status, void *userData)
void SPI_RxDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
void SPI_TxDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
To know the state of intA or intB, i should read the variable "tcds", however it never enters in the SPI_RxDMACallback() or SPI_TxDMACallback(), the code only gets into the function SPI_DMA_master_callback() after finishing all the descriptors.
Is there a way to check when it occurs intA and intB?
Thank you,
Kans
Hello,
The reason your code only triggers SPI_DMA_master_callback() at the end of the entire chain is that MCUXpresso’s high-level spi_dma_handle_t driver overwrites the individual DMA callbacks and disables intermediate descriptor interrupts (INTA/INTB) by default. The high-level driver only notifies you when the final descriptor completes.
Thank you for the response.
Indeed i have noticed that, so i was trying to find a way to still have access to the descriptor interrupts (INTA/INTB)
I have tried to use a custom Callback, and it seems to be working for now, to have access to intA and intB states:
*defenitions*
dma_callback g_nxp_rx_callback = NULL;
void *g_nxp_rx_userData = NULL;
void Custom_RxDmaCallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds);
*initialisation*
g_nxp_rx_callback = FLEXCOMM0_RX_Handle.callback;
g_nxp_rx_userData = FLEXCOMM0_RX_Handle.userData;
DMA_SetCallback(&FLEXCOMM0_RX_Handle, Custom_RxDmaCallback, NULL);
*callback*
void Custom_RxDmaCallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
{
// 1. Intercept intermediate descriptor interrupts
if (tcds == kDMA_IntA)
{
// Descriptor middle finished: 1st buffer filled
transferDone = false;
}
else if (tcds == kDMA_IntB)
{
// Descriptor final finished: 2nd buffer filled
transferDone = true;
}
if (transferDone && g_nxp_rx_callback != NULL)
{
g_nxp_rx_callback(handle, g_nxp_rx_userData, transferDone, tcds);
}
}This way it also goes to the SPI callback function when the communication is finished, however (correct me if i am wrong), by going into the SPI callback function it changes the internal state of SPI from kSPI_Busy to kSPI_Idle, while in reality i am in an infinite loop of descriptors (after last descriptor goes straight to first descriptor), so maybe this could generate some conflicts?
Also avoiding to move from callback to callback.
So i decided to keep it simple:
*initialisation*
DMA_SetCallback(&FLEXCOMM0_RX_Handle, Custom_RxDmaCallback, NULL);
*callback*
void Custom_RxDmaCallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
{
// 1. Intercept intermediate descriptor interrupts
if (tcds == kDMA_IntA)
{
// Descriptor middle finished: 1st buffer filled
}
else if (tcds == kDMA_IntB)
{
// Descriptor final finished: 2nd buffer filled
}
}