Hello,
I am working on a custom board that is based on MIMXRT1042 and my issue is that I have a delay between every frame transaction on the LPSPI bus during communication with a display.
Data that is transferred can be a few bytes or up to (32*1024U - 1) bytes per chunk.
LPSPI_CLK_ROOT is configured to 132MHz and transfer baud rate is 50MHz.
The delay between frames is ~74ns (see the attached image) and that is affecting the display frame rate.
Can that delay be removed and if not what can I do to reduce it even more?
Best regards,
Adde
Solved! Go to Solution.
Hi Miguel,
I have increased LPSPI bitsPerFrame from 8 to 16 and I don't see any delays between transactions. The display frame rate is ~34 fps that is acceptable.
Thanks for the support!
Best regards,
Adde
The max baudrate is 30M
Hi @adde_ado
Can you tell me the display you are using? Also, make sure to use the SDK examples to avoid a peripheral configuration issue.
I'll be looking into your problem, however, since you are using a custom board, we cannot discard any hardware issues.
Best Regards, Miguel.
Hi Miguel and Lucas,
The display we are using is ST7789V2 and LPSPI communication is One-directional (CPU to Display).
We are using latest SDK (SDK_2_13_0_MIMXRT1042xxxxB) and our LPSPI/EDMA code is more or less based on example from SDK.
I have now decreaset baudrate to 30MHz but I still have delay between frames (see the attached image).
This is my source code that is relevant for LPSPI/EDMA.
#define LPSPI_MASTER_BASEADDR (LPSPI1)
//#define TRANSFER_BAUDRATE 5000000U /*! Transfer baudrate - 5 MHz */
//#define TRANSFER_BAUDRATE 10000000U /*! Transfer baudrate - 10 MHz */
//#define TRANSFER_BAUDRATE 20000000U /*! Transfer baudrate - 20 MHz */
#define TRANSFER_BAUDRATE 30000000U /*! Transfer baudrate - 30 MHz */
//#define TRANSFER_BAUDRATE 40000000U /*! Transfer baudrate - 40 MHz */
//#define TRANSFER_BAUDRATE 50000000U /*! Transfer baudrate - 50 MHz */
#define LPSPI_MASTER_PCS_FOR_INIT (kLPSPI_Pcs0)
#defi
#define LPSPI_MASTER_DMA_MUX_BASEADDR (DMAMUX)
#define LPSPI_MASTER_DMA_RX_REQUEST_SOURCE kDmaRequestMuxLPSPI1Rx
#define LPSPI_MASTER_DMA_TX_REQUEST_SOURCE kDmaRequestMuxLPSPI1Tx
#define LPSPI_MASTER_DMA_BASEADDR (DMA0)
#define LPSPI_MASTER_DMA_RX_CHANNEL 1U
#define LPSPI_MASTER_DMA_TX_CHANNEL 3U
#define MAX_TRANSMIT_SIZE_FOR_EDMA (32*1024U - 1)
/* LPSPI user callback */
void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData);
static uint32_t st7789v2_hal_split_in_chunks(uint32_t items_to_transmit, uint32_t * chunk_size);
AT_NONCACHEABLE_SECTION_INIT(lpspi_master_edma_handle_t g_m_edma_handle) = {0};
edma_handle_t lpspiEdmaMasterRxRegToRxDataHandle;
edma_handle_t lpspiEdmaMasterTxDataToTxRegHandle;
edma_config_t userConfig = {0};
volatile BOOL isTransferCompleted = false;
void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData)
{
if (status == kStatus_Success)
{
__NOP();
}
isTransferCompleted = TRUE;
}
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_00_LPSPI1_SCK, 0); // SPI clock GPIO_SD_B0_00 LCD_SCLK1 SCL
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_01_LPSPI1_PCS0, 0); // SPI chip select GPIO_SD_B0_01 LCD_/CSB CSX
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_02_LPSPI1_SDO, 0); // SDA (data) GPIO_SD_B0_02 LCD_SDA SDA
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_03_LPSPI1_SDI, 0); // SDA2 GPIO_SD_B0_03 LCD_SDA2 SDA2/WRX
******************************** configure LPSPI/EDMA ***********************
/* DMA MUX init*/
DMAMUX_Init(LPSPI_MASTER_DMA_MUX_BASEADDR);
DMAMUX_SetSource(LPSPI_MASTER_DMA_MUX_BASEADDR, LPSPI_MASTER_DMA_RX_CHANNEL,
LPSPI_MASTER_DMA_RX_REQUEST_SOURCE);
DMAMUX_EnableChannel(LPSPI_MASTER_DMA_MUX_BASEADDR, LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_SetSource(LPSPI_MASTER_DMA_MUX_BASEADDR, LPSPI_MASTER_DMA_TX_CHANNEL,
LPSPI_MASTER_DMA_TX_REQUEST_SOURCE);
DMAMUX_EnableChannel(LPSPI_MASTER_DMA_MUX_BASEADDR, LPSPI_MASTER_DMA_TX_CHANNEL);
EDMA_GetDefaultConfig(&userConfig);
userConfig.enableRoundRobinArbitration = true;
EDMA_Init(LPSPI_MASTER_DMA_BASEADDR, &userConfig);
// To use the second data lane: CFGR1[PCSCFG] = 1 --> Use pin PCS2/DATA[2] as data 2. See [2], Table 45.12.
LPSPI_Reset(LPSPI_MASTER_BASEADDR);
/*Master config*/
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.whichPcs = LPSPI_MASTER_PCS_FOR_INIT;
masterConfig.bitsPerFrame = 8; // 8 bits to transfer.
masterConfig.pinCfg = kLPSPI_SdiInSdoOut; // According to [2], page 2625, PINCFG: "If performing parallel transfers, the Pin Configuration field must be 00."
masterConfig.betweenTransferDelayInNanoSec = 1000000000 / (masterConfig.baudRate * 2);
masterConfig.dataOutConfig = kLpspiDataOutRetained;
masterConfig.cpha = kLPSPI_ClockPhaseSecondEdge; // kLPSPI_ClockPhaseFirstEdge
masterConfig.cpol = kLPSPI_ClockPolarityActiveLow;
srcClock_Hz = BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT; //132MHz;
LPSPI_MasterInit(LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);
LPSPI_Enable(LPSPI_MASTER_BASEADDR, false);
LPSPI_MASTER_BASEADDR->CR |= LPSPI_CR_DBGEN(1); // Support debugging.
// Change PCS[3:2] from chip selects to be used as data lines. See [2] page 2624.
LPSPI_MASTER_BASEADDR->CFGR1 &= ~(LPSPI_CFGR1_PCSCFG_MASK);
LPSPI_MASTER_BASEADDR->CFGR1 |= LPSPI_CFGR1_PCSCFG(1);
LPSPI_MASTER_BASEADDR->SR |= LPSPI_SR_TCF_MASK; // Clear Transfer Complete Flag.
LPSPI_Enable(LPSPI_MASTER_BASEADDR, true);
/*Set up lpspi master*/
memset(&(lpspiEdmaMasterRxRegToRxDataHandle), 0, sizeof(lpspiEdmaMasterRxRegToRxDataHandle));
memset(&(lpspiEdmaMasterTxDataToTxRegHandle), 0, sizeof(lpspiEdmaMasterTxDataToTxRegHandle));
EDMA_CreateHandle(&(lpspiEdmaMasterRxRegToRxDataHandle), LPSPI_MASTER_DMA_BASEADDR,
LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_CreateHandle(&(lpspiEdmaMasterTxDataToTxRegHandle), LPSPI_MASTER_DMA_BASEADDR,
LPSPI_MASTER_DMA_TX_CHANNEL);
LPSPI_MasterTransferCreateHandleEDMA(LPSPI_MASTER_BASEADDR, &g_m_edma_handle, LPSPI_MasterUserCallback,
NULL, &lpspiEdmaMasterRxRegToRxDataHandle,
&lpspiEdmaMasterTxDataToTxRegHandle);
************************* Start Transffer **************************
masterXfer.rxData = NULL;
masterXfer.configFlags = LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterByteSwap | kLPSPI_MasterPcsContinuous;
masterXfer.txData = tx_data;
masterXfer.dataSize = items_to_transmit * bytes_per_item;
isTransferCompleted = FALSE;
LPSPI_MasterTransferEDMA(LPSPI_MASTER_BASEADDR, &g_m_edma_handle, &masterXfer);
/* Wait until transfer completed */
while (!isTransferCompleted)
{
}
}
I have also seen that others have had similara issues but I don't know how thay have solved it.
They are using a different CPU (1050).
https://community.nxp.com/t5/i-MX-Processors/LPSPI-and-EDMA-RT1050-Too-Slow/td-p/1269109
Best regards,
Adde
Hi @adde_ado
According to the community thread, the customer added a delay between the transfers and jeremyzhou posted some steps to transfer the data faster.
"1) The steps of modifying the lpspi_edma_b2b_transfer_master demo (SDK library version is 2.8.5)
a) in lpspi_edma_b2b_transfer_master.c, increae the number of tranmit data and transfer baudrate."
See the complete reply and follow the steps using the parameters you need for the display.
Best Regards, Miguel.
Hi Miguel,
I have increased LPSPI bitsPerFrame from 8 to 16 and I don't see any delays between transactions. The display frame rate is ~34 fps that is acceptable.
Thanks for the support!
Best regards,
Adde