Hi.I have an SPI issue, may I know how to handle it? The official routine spi_transfer_rma_stlave calls the EXAMPLE_MasterStartDMATransfer() function twice in a row in the main function. The captured SPI waveform shows that the second transfer will raise the CS for each data. We need to send data for the second time, and only raise CS after the data is sent. It's not like raising CS every time we send data
Solved! Go to Solution.
Hi,
If you want to call the function multiple times, you have to poll if the predefined number of data has been transferred, after the DMA transfer completed, then you can call again.
int main(void)
{
/* Initialize the boards */
/* Attach main clock to USART0 (debug console) */
CLOCK_Select(kUART0_Clk_From_MainClk);
BOARD_InitBootPins();
BOARD_BootClockFRO48M();
BOARD_InitDebugConsole();
/* Attach main clock to SPI0. */
CLOCK_Select(kSPI0_Clk_From_MainClk);
PRINTF("This is SPI dma transfer master example!\n\r");
PRINTF("To make sure the transfer work successfully, please start the slave board first!\n\r");
/* Initialize the SPI master with configuration. */
EXAMPLE_SPIMasterInit();
/* Set up DMA configuration. */
EXAMPLE_MasterDMASetup();
/* Start transfer with slave board. */
loop: __asm("nop");
EXAMPLE_MasterStartDMATransfer();
while(masterTxFinished) {}
masterTxFinished=false;
goto loop;
/* Check the received data. */
EXAMPLE_TransferDataCheck();
/* De-initialize the DMA. */
DMA_Deinit(EXAMPLE_SPI_MASTER_DMA_BASEADDR);
/* De-initialize the SPI. */
SPI_Deinit(EXAMPLE_SPI_MASTER);
while (1)
{
}
}
Hope it can help you
BR
XiangJun Rong
void EXAMPLE_MasterStartDMATransfer(void)
{
uint32_t i = 0U;
dma_transfer_config_t masterTxDmaConfig, masterRxDmaConfig;
/* Prepare buffer to send and receive data. */
for (i = 0U; i < BUFFER_SIZE; i++)
{
txBuffer[i] = i;
rxBuffer[i] = 0U;
}
/* Prepare and start DMA RX transfer. */
DMA_PrepareTransfer(&masterRxDmaConfig, (void *)&EXAMPLE_SPI_MASTER->RXDAT, rxBuffer, sizeof(uint8_t), BUFFER_SIZE,
kDMA_PeripheralToMemory, NULL);
DMA_SubmitTransfer(&masterRxHandle, &masterRxDmaConfig);
/* Start DMA TX transfer. */
DMA_StartTransfer(&masterRxHandle);
/* Set the last byte to be sent, This will de-assert the SSEL pin when transmission is completed.
* If users want to assert the SSEL pin when transmission is completed, there is no need to set up this descriptor.
*/
lastData = txBuffer[BUFFER_SIZE - 1] | kSPI_EndOfTransfer | (EXAMPLE_SPI_MASTER->TXCTL & 0xFFFF0000);
/* DMA transfer configuration setting. */
dma_xfercfg_t tmp_xfercfg = {0};
tmp_xfercfg.valid = true;
tmp_xfercfg.swtrig = true;
tmp_xfercfg.intA = true;
tmp_xfercfg.byteWidth = sizeof(uint32_t);
tmp_xfercfg.srcInc = 0;
tmp_xfercfg.dstInc = 0;
tmp_xfercfg.transferCount = 1;
/* Create chained descriptor to transmit last word */
DMA_CreateDescriptor(&txDescriptor, &tmp_xfercfg, &lastData, (void *)&EXAMPLE_SPI_MASTER->TXDATCTL, NULL);
/* Add confifuration parameter to descriptor. */
DMA_PrepareTransfer(&masterTxDmaConfig, txBuffer, (void *)&EXAMPLE_SPI_MASTER->TXDAT, sizeof(uint8_t),
BUFFER_SIZE - 1, kDMA_MemoryToPeripheral, &txDescriptor);
/* Disable interrupts for first descriptor to avoid calling callback twice. */
masterTxDmaConfig.xfercfg.intA = false;
masterTxDmaConfig.xfercfg.intB = false;
DMA_SubmitTransfer(&masterTxHandle, &masterTxDmaConfig);
/* Start DMA TX transfer. */
DMA_StartTransfer(&masterTxHandle);
}
How can I modify this function? Or add other configurations? Thank you.
Hi,
Can you send us the project so that we can know the code context?
BR
Xiangjun Rong
Is there any result yet?
Hi,
As you know that the SPI is Full Duplex protocol, the transmitter and receiver work synchronously, the spi uses two DMA channels, one is for receiver, another is for transmitter
Hope it can help you
BR
XiangJun Rong
I don't know why I called this function twice. The first time I called this function to send data, CS was pulled down during the entire data transmission process. The second time I called it, CS was indeed pulled up for each data transmission.
Hi,
As the following screenshot,
EXAMPLE_MasterStartDMATransfer();
is called only once.
BR
XiangJun Rong
yes,demo is called once.
But. I need to modify this demo by calling this function multiple times. How can I avoid a second call where the master sends a data and then raises the CS value? For example. I need to send 8 bytes of data, and I hope to send all 8 bytes of data before raising the CS. The current practice is to go to the initial SPI(EXAMPLE-SPIMasterInit()), before call this function;... It shouldn't be used that way, right?
Hi,
If you want to call the function multiple times, you have to poll if the predefined number of data has been transferred, after the DMA transfer completed, then you can call again.
int main(void)
{
/* Initialize the boards */
/* Attach main clock to USART0 (debug console) */
CLOCK_Select(kUART0_Clk_From_MainClk);
BOARD_InitBootPins();
BOARD_BootClockFRO48M();
BOARD_InitDebugConsole();
/* Attach main clock to SPI0. */
CLOCK_Select(kSPI0_Clk_From_MainClk);
PRINTF("This is SPI dma transfer master example!\n\r");
PRINTF("To make sure the transfer work successfully, please start the slave board first!\n\r");
/* Initialize the SPI master with configuration. */
EXAMPLE_SPIMasterInit();
/* Set up DMA configuration. */
EXAMPLE_MasterDMASetup();
/* Start transfer with slave board. */
loop: __asm("nop");
EXAMPLE_MasterStartDMATransfer();
while(masterTxFinished) {}
masterTxFinished=false;
goto loop;
/* Check the received data. */
EXAMPLE_TransferDataCheck();
/* De-initialize the DMA. */
DMA_Deinit(EXAMPLE_SPI_MASTER_DMA_BASEADDR);
/* De-initialize the SPI. */
SPI_Deinit(EXAMPLE_SPI_MASTER);
while (1)
{
}
}
Hope it can help you
BR
XiangJun Rong