Hello,
I have a bit of an unexpected behaviour with an LPSPI on i.MXRT1166. My situation / setup is:
- I'm trying to read data from an ADC connected via dual SPI.
- Every time, the ADC has converted data, I get a short signal via the HREQ pin. The signal is about 4 SPI clock cycles long (shorter than a SPI transaction).
- With the HREQ, a SPI transfer of 32 bit on two lines (-> 16 clocks) should be triggered.
- I've set up a circular FIFO with a single TCR in the LPSPI that should read the data.
- The data is pulled from the LPSPI via DMA.
My problem now is, that instead of one 32 bit transfers, I get two on every HREQ. Any ideas what the reason for that could be?
If I put two TCRs into the FIFO, I get two transfers too. If I put three TCRs into it, it's three transfers. So these would work like expected. Only the situation with one transfer doesn't work.
I also tried splitting up the transfer into two 16 bit transfers. But in that case, I get three transfers during the first trigger and two (like expected) on all others.
My register settings are:
LPSPI_Type *lpspi = /* Pointer to my LPSPI */;
/* Disable module. */
lpspi->CR &= ~LPSPI_CR_MEN_MASK;
/* Flush FIFOs */
lpspi->CR |= LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK;
lpspi->CR &= ~LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK;
/* Make sure that FIFO is empty. */
assert(lpspi->FSR == 0);
lpspi->IER = 0;
lpspi->CCR = LPSPI_CCR_SCKDIV(precalculated_sckdiv) |
LPSPI_CCR_SCKPCS(0) |
LPSPI_CCR_PCSSCK(0) |
LPSPI_CCR_DBT(0);
lpspi->CFGR0 = LPSPI_CFGR0_HREN_MASK | LPSPI_CFGR0_CIRFIFO_MASK;
lpspi->CFGR1 = LPSPI_CFGR1_OUTCFG(1) | LPSPI_CFGR1_MASTER(1);
/* Disable the FIFO watermark. */
lpspi->FCR = 0;
/* Rx will be handled by DMA. */
lpspi->DER = LPSPI_DER_RDDE_MASK;
/* Everything is prepared. Module can be enabled again. */
lpspi->CR |= LPSPI_CR_MEN_MASK;
/*
* Prepare the DMA. The following snipped is at a different location in
* my original code. I copied it here to make the example more readable.
* "transfers" is the total number of ADC conversions that I expect in
* my bigger sequence.
*/
tcd->SADDR = (uintptr_t)&lpspi->RDR;
tcd->SDF = EDMA_TCD_SDF_SOFF(0) | EDMA_TCD_SDF_SSIZE_32BIT |
EDMA_TCD_SDF_SMOD(0) | EDMA_TCD_SDF_DSIZE_32BIT |
EDMA_TCD_SDF_DMOD(0);
tcd->NBYTES = EDMA_TCD_NBYTES_ALT_NBYTES(BYTES_PER_LPSPI_RX_TRANSFER) |
EDMA_TCD_NBYTES_ALT_MLOFF(0) | EDMA_TCD_NBYTES_ALT_DMLOE;
tcd->SLAST = 0;
tcd->DADDR = (uintptr_t)dma_buffer;
tcd->CDF = EDMA_TCD_CDF_DOFF(BYTES_PER_LPSPI_RX_TRANSFER) |
EDMA_TCD_CDF_CITER(transfers);
tcd->DLAST_SGA = 0;
tcd->BMF = EDMA_TCD_BMF_BITER(transfers);
/*
* Usually here comes a code that would enable the DMA channel and copy
* the tcd to the right location in the DMA so that the DMA can work
* on the next trigger.
*/
uint32_t tcr = LPSPI_TCR_CPOL(0) | LPSPI_TCR_CPHA(1) |
LPSPI_TCR_PRESCALE(ctx->adc.lpspi_prescale) | LPSPI_TCR_PCS(0) |
LPSPI_TCR_LSBF(0) | LPSPI_TCR_BYSW(0) | LPSPI_TCR_RXMSK(0) |
LPSPI_TCR_TXMSK(1) | LPSPI_TCR_WIDTH(1) |
LPSPI_TCR_FRAMESZ(DATABITS_PER_CHANNEL * CHANNELS - 1);
/* Put SPI commands into the FIFO */
lpspi->TCR = tcr;
/* Clear empty flags */
lpspi->SR |= LPSPI_SR_REF_MASK | LPSPI_SR_TEF_MASK;
/*
* No transfer happened yet. As soon as a HREQ happens, I would expect
* one transfer with 16 clocks (32 bits). But instead I get two on each
* HREQ.
*
* I checked the LPSPI FIFO Status register at this point and it shows
* only one word in the FIFO.
*/
Best regards
Christian Mauderer