static bool spi_allocate_dma(spi_t *obj, uint32_t handler) { dma_request_source_t dma_rx_requests[] = SPI_DMA_RX_REQUEST_NUMBERS; dma_request_source_t dma_tx_requests[] = SPI_DMA_TX_REQUEST_NUMBERS; edma_config_t userConfig; /* Allocate the DMA channels */ /* Allocate the RX channel */ obj->spi.spiDmaMasterRx.dmaChannel = dma_channel_allocate(dma_rx_requests[obj->spi.instance]); if (obj->spi.spiDmaMasterRx.dmaChannel == DMA_ERROR_OUT_OF_CHANNELS) { return false; } /* Check if we have separate DMA requests for TX & RX */ if (dma_tx_requests[obj->spi.instance] != dma_rx_requests[obj->spi.instance]) { /* Allocate the TX channel with the DMA TX request number set as source */ obj->spi.spiDmaMasterTx.dmaChannel = dma_channel_allocate(dma_tx_requests[obj->spi.instance]); } else { /* Allocate the TX channel without setting source */ obj->spi.spiDmaMasterTx.dmaChannel = dma_channel_allocate(kDmaRequestMux0Disable); } if (obj->spi.spiDmaMasterTx.dmaChannel == DMA_ERROR_OUT_OF_CHANNELS) { dma_channel_free(obj->spi.spiDmaMasterRx.dmaChannel); return false; } /* Allocate an intermediary DMA channel */ obj->spi.spiDmaMasterIntermediary.dmaChannel = dma_channel_allocate(kDmaRequestMux0Disable); if (obj->spi.spiDmaMasterIntermediary.dmaChannel == DMA_ERROR_OUT_OF_CHANNELS) { dma_channel_free(obj->spi.spiDmaMasterRx.dmaChannel); dma_channel_free(obj->spi.spiDmaMasterTx.dmaChannel); return false; } /* EDMA init*/ /* * userConfig.enableRoundRobinArbitration = false; * userConfig.enableHaltOnError = true; * userConfig.enableContinuousLinkMode = false; * userConfig.enableDebugMode = false; */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(DMA0, &userConfig); /* Set up dspi master */ memset(&(obj->spi.spiDmaMasterRx.handle), 0, sizeof(obj->spi.spiDmaMasterRx.handle)); memset(&(obj->spi.spiDmaMasterTx.handle), 0, sizeof(obj->spi.spiDmaMasterTx.handle)); memset(&(obj->spi.spiDmaMasterIntermediary.handle), 0, sizeof(obj->spi.spiDmaMasterIntermediary.handle)); EDMA_CreateHandle(&(obj->spi.spiDmaMasterRx.handle), DMA0, obj->spi.spiDmaMasterRx.dmaChannel); EDMA_CreateHandle(&(obj->spi.spiDmaMasterIntermediary.handle), DMA0, obj->spi.spiDmaMasterIntermediary.dmaChannel); EDMA_CreateHandle(&(obj->spi.spiDmaMasterTx.handle), DMA0, obj->spi.spiDmaMasterTx.dmaChannel); DSPI_MasterTransferCreateHandleEDMA(spi_address[obj->spi.instance], &obj->spi.spi_dma_master_handle, (dspi_master_edma_transfer_callback_t)handler, NULL, &obj->spi.spiDmaMasterRx.handle, &obj->spi.spiDmaMasterIntermediary.handle, &obj->spi.spiDmaMasterTx.handle); return true; }
/*! * @brief Main function */ int main(void) { uint32_t srcAddr[BUFFER_LENGTH] = {0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U}; uint32_t destAddr[BUFFER_LENGTH] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; uint32_t i = 0; edma_transfer_config_t transferConfig; edma_tcd_t *tcdMemoryPoolPtr; edma_config_t userConfig; BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); /* Print source buffer */ PRINTF("EDMA memory to memory transfer example begin.\r\n\r\n"); PRINTF("Destination Buffer:\r\n"); for (i = 0; i < BUFFER_LENGTH; i++) { PRINTF("%d\t", destAddr[i]); } /* Configure DMAMUX */ DMAMUX_Init(DMAMUX0); DMAMUX_SetSource(DMAMUX0, 0, 63); DMAMUX_EnableChannel(DMAMUX0, 0); /* Configure EDMA one shot transfer */ /* * userConfig.enableRoundRobinArbitration = false; * userConfig.enableHaltOnError = true; * userConfig.enableContinuousLinkMode = false; * userConfig.enableDebugMode = false; */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(DMA0, &userConfig); EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0); EDMA_SetCallback(&g_EDMA_Handle, EDMA_Callback, NULL); EDMA_ResetChannel(g_EDMA_Handle.base, g_EDMA_Handle.channel); /* Allocate TCD memory poll */ tcdMemoryPoolPtr = (edma_tcd_t *)malloc(sizeof(edma_tcd_t) * (TCD_QUEUE_SIZE + 1)); if (tcdMemoryPoolPtr != NULL) { tcdMemoryPoolPtr = (edma_tcd_t *)((uint32_t)(tcdMemoryPoolPtr + 1) & (~0x1FU)); EDMA_InstallTCDMemory(&g_EDMA_Handle, tcdMemoryPoolPtr, TCD_QUEUE_SIZE); /* Configure and submit transfer structure 1 */ EDMA_PrepareTransfer(&transferConfig, srcAddr, sizeof(srcAddr[0]), destAddr, sizeof(destAddr[0]), sizeof(srcAddr[0]), sizeof(srcAddr[0]) * HALF_BUFFER_LENGTH, kEDMA_MemoryToMemory); EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig); /* Configure and submit transfer structure 2 */ EDMA_PrepareTransfer(&transferConfig, &srcAddr[4], sizeof(srcAddr[0]), &destAddr[4], sizeof(destAddr[0]), sizeof(srcAddr[0]), sizeof(srcAddr[0]) * HALF_BUFFER_LENGTH, kEDMA_MemoryToMemory); EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig); } EDMA_StartTransfer(&g_EDMA_Handle); /* Wait for EDMA transfer finish */ while (g_Transfer_Done != true) { } /* Print destination buffer */ PRINTF("\r\n\r\nEDMA memory to memory transfer example finish.\r\n\r\n"); PRINTF("Destination Buffer:\r\n"); for (i = 0; i < BUFFER_LENGTH; i++) { PRINTF("%d\t", destAddr[i]); } while (1) { } }
static rt_err_t icodec_init(struct rt_audio_device *audio) { sai_config_t config; uint32_t mclkSourceClockHz = 0U; edma_config_t dmaConfig = {0}; lpi2c_master_config_t i2cConfig = {0}; uint32_t i2cSourceClock; clock_audio_pll_config_t audioPllConfig = {32, 1, 77, 100}; struct imxcodec *icodec = audio->parent.user_data; sai_transfer_format_t *format; icodec->sai = DEMO_SAI; format = &icodec->format; _InitPins(); CLOCK_InitAudioPll(&audioPllConfig); /*Clock setting for LPI2C*/ CLOCK_SetMux(kCLOCK_Lpi2cMux, DEMO_LPI2C_CLOCK_SOURCE_SELECT); CLOCK_SetDiv(kCLOCK_Lpi2cDiv, DEMO_LPI2C_CLOCK_SOURCE_DIVIDER); /*Clock setting for SAI1*/ CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT); CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER); CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER); /*Enable MCLK clock*/ BOARD_EnableSaiMclkOutput(true); /* Create EDMA handle */ EDMA_GetDefaultConfig(&dmaConfig); EDMA_Init(EXAMPLE_DMA, &dmaConfig); EDMA_CreateHandle(&icodec->dmaHandle, EXAMPLE_DMA, EXAMPLE_CHANNEL); DMAMUX_Init(DMAMUX0); DMAMUX_SetSource(DMAMUX0, EXAMPLE_CHANNEL, EXAMPLE_SAI_TX_SOURCE); DMAMUX_EnableChannel(DMAMUX0, EXAMPLE_CHANNEL); /* Init SAI module */ SAI_TxGetDefaultConfig(&config); config.protocol = kSAI_BusLeftJustified; SAI_TxInit(DEMO_SAI, &config); /* Configure the audio format */ format->bitWidth = kSAI_WordWidth16bits; format->channel = 0U; format->sampleRate_Hz = kSAI_SampleRate48KHz; format->masterClockHz = DEMO_SAI_CLK_FREQ; format->protocol = config.protocol; format->stereo = kSAI_Stereo; format->isFrameSyncCompact = 0; format->watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U; /* Configure Sgtl5000 I2C */ icodec->codecHandle.base = DEMO_I2C; icodec->codecHandle.i2cHandle = &icodec->i2cHandle; i2cSourceClock = DEMO_I2C_CLK_FREQ; LPI2C_MasterGetDefaultConfig(&i2cConfig); LPI2C_MasterInit(DEMO_I2C, &i2cConfig, i2cSourceClock); LPI2C_MasterTransferCreateHandle(DEMO_I2C, &icodec->i2cHandle, NULL, NULL); WM8960_Init(&icodec->codecHandle, NULL); WM8960_ConfigDataFormat(&icodec->codecHandle, format->masterClockHz, format->sampleRate_Hz, format->bitWidth); SAI_TransferTxCreateHandleEDMA(icodec->sai, &icodec->txHandle, saidma_callback, audio, &icodec->dmaHandle); mclkSourceClockHz = DEMO_SAI_CLK_FREQ; SAI_TransferTxSetFormatEDMA(icodec->sai, &icodec->txHandle, format, mclkSourceClockHz, format->masterClockHz); return RT_EOK; }
/*! * @brief Main function */ int main(void) { BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); PRINTF("DSPI edma example start.\r\n"); PRINTF("This example use one dspi instance as master and another as slave on one board.\r\n"); PRINTF("Master use edma way , slave uses interrupt.\r\n"); PRINTF("Please make sure you make the correct line connection. Basically, the connection is: \r\n"); PRINTF("DSPI_master -- DSPI_slave \r\n"); PRINTF(" CLK -- CLK \r\n"); PRINTF(" PCS -- PCS \r\n"); PRINTF(" SOUT -- SIN \r\n"); PRINTF(" SIN -- SOUT \r\n"); /* DMA Mux setting and EDMA init */ uint32_t masterRxChannel, masterIntermediaryChannel, masterTxChannel; uint32_t slaveRxChannel, slaveTxChannel; edma_config_t userConfig; masterRxChannel = 0U; masterIntermediaryChannel = 1U; masterTxChannel = 2U; slaveRxChannel = 3U; slaveTxChannel = 4U; /* DMA MUX init */ DMAMUX_Init(EXAMPLE_DSPI_MASTER_DMA_MUX_BASEADDR); #if (defined EXAMPLE_DSPI_MASTER_DMA_MUX_BASE) && (defined EXAMPLE_DSPI_SLAVE_DMA_MUX_BASE) && \ (EXAMPLE_DSPI_MASTER_DMA_MUX_BASE != EXAMPLE_DSPI_SLAVE_DMA_MUX_BASE) DMAMUX_Init(EXAMPLE_DSPI_SLAVE_DMA_MUX_BASEADDR); #endif DMAMUX_SetSource(EXAMPLE_DSPI_MASTER_DMA_MUX_BASEADDR, masterRxChannel, EXAMPLE_DSPI_MASTER_DMA_RX_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_DSPI_MASTER_DMA_MUX_BASEADDR, masterRxChannel); #if (defined EXAMPLE_DSPI_MASTER_DMA_TX_REQUEST_SOURCE) DMAMUX_SetSource(EXAMPLE_DSPI_MASTER_DMA_MUX_BASEADDR, masterTxChannel, EXAMPLE_DSPI_MASTER_DMA_TX_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_DSPI_MASTER_DMA_MUX_BASEADDR, masterTxChannel); #endif DMAMUX_SetSource(EXAMPLE_DSPI_SLAVE_DMA_MUX_BASEADDR, slaveRxChannel, EXAMPLE_DSPI_SLAVE_DMA_RX_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_DSPI_SLAVE_DMA_MUX_BASEADDR, slaveRxChannel); #if (defined EXAMPLE_DSPI_SLAVE_DMA_TX_REQUEST_SOURCE) DMAMUX_SetSource(EXAMPLE_DSPI_SLAVE_DMA_MUX_BASEADDR, slaveTxChannel, EXAMPLE_DSPI_SLAVE_DMA_TX_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_DSPI_SLAVE_DMA_MUX_BASEADDR, slaveTxChannel); #endif /* EDMA init*/ /* * userConfig.enableRoundRobinArbitration = false; * userConfig.enableHaltOnError = true; * userConfig.enableContinuousLinkMode = false; * userConfig.enableDebugMode = false; */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(EXAMPLE_DSPI_MASTER_DMA_BASEADDR, &userConfig); #if (defined EXAMPLE_DSPI_SLAVE_DMA_BASE) && (defined EXAMPLE_DSPI_MASTER_DMA_BASE) && \ (EXAMPLE_DSPI_SLAVE_DMA_BASE != EXAMPLE_DSPI_MASTER_DMA_BASE) EDMA_Init(EXAMPLE_DSPI_SLAVE_DMA_BASEADDR, &userConfig); #endif /*DSPI init*/ uint32_t srcClock_Hz; uint32_t errorCount; uint32_t i; dspi_master_config_t masterConfig; dspi_slave_config_t slaveConfig; dspi_transfer_t masterXfer; dspi_transfer_t slaveXfer; /*Master config*/ masterConfig.whichCtar = kDSPI_Ctar0; masterConfig.ctarConfig.baudRate = TRANSFER_BAUDRATE; masterConfig.ctarConfig.bitsPerFrame = 8U; masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; masterConfig.ctarConfig.direction = kDSPI_MsbFirst; masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / TRANSFER_BAUDRATE; masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / TRANSFER_BAUDRATE; masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / TRANSFER_BAUDRATE; masterConfig.whichPcs = EXAMPLE_DSPI_MASTER_PCS_FOR_INIT; masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; masterConfig.enableContinuousSCK = false; masterConfig.enableRxFifoOverWrite = false; masterConfig.enableModifiedTimingFormat = false; masterConfig.samplePoint = kDSPI_SckToSin0Clock; srcClock_Hz = CLOCK_GetFreq(DSPI_MASTER_CLK_SRC); DSPI_MasterInit(EXAMPLE_DSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz); /*Slave config*/ slaveConfig.whichCtar = kDSPI_Ctar0; slaveConfig.ctarConfig.bitsPerFrame = masterConfig.ctarConfig.bitsPerFrame; slaveConfig.ctarConfig.cpol = masterConfig.ctarConfig.cpol; slaveConfig.ctarConfig.cpha = masterConfig.ctarConfig.cpha; slaveConfig.enableContinuousSCK = masterConfig.enableContinuousSCK; slaveConfig.enableRxFifoOverWrite = masterConfig.enableRxFifoOverWrite; slaveConfig.enableModifiedTimingFormat = masterConfig.enableModifiedTimingFormat; slaveConfig.samplePoint = masterConfig.samplePoint; DSPI_SlaveInit(EXAMPLE_DSPI_SLAVE_BASEADDR, &slaveConfig); /* Set up the transfer data */ for (i = 0U; i < TRANSFER_SIZE; i++) { masterTxData[i] = i % 256U; masterRxData[i] = 0U; slaveTxData[i] = ~masterTxData[i]; slaveRxData[i] = 0U; } /* Set up dspi slave first */ memset(&(dspiEdmaSlaveRxRegToRxDataHandle), 0, sizeof(dspiEdmaSlaveRxRegToRxDataHandle)); memset(&(dspiEdmaSlaveTxDataToTxRegHandle), 0, sizeof(dspiEdmaSlaveTxDataToTxRegHandle)); EDMA_CreateHandle(&(dspiEdmaSlaveRxRegToRxDataHandle), EXAMPLE_DSPI_SLAVE_DMA_BASEADDR, slaveRxChannel); EDMA_CreateHandle(&(dspiEdmaSlaveTxDataToTxRegHandle), EXAMPLE_DSPI_SLAVE_DMA_BASEADDR, slaveTxChannel); isTransferCompleted = false; DSPI_SlaveTransferCreateHandleEDMA(EXAMPLE_DSPI_SLAVE_BASEADDR, &g_dspi_edma_s_handle, DSPI_SlaveUserCallback, NULL, &dspiEdmaSlaveRxRegToRxDataHandle, &dspiEdmaSlaveTxDataToTxRegHandle); slaveXfer.txData = slaveTxData; slaveXfer.rxData = slaveRxData; slaveXfer.dataSize = TRANSFER_SIZE; slaveXfer.configFlags = kDSPI_SlaveCtar0; if (kStatus_Success != DSPI_SlaveTransferEDMA(EXAMPLE_DSPI_SLAVE_BASEADDR, &g_dspi_edma_s_handle, &slaveXfer)) { PRINTF("There is error when start DSPI_SlaveTransferEDMA \r\n"); } /* Set up dspi master */ memset(&(dspiEdmaMasterRxRegToRxDataHandle), 0, sizeof(dspiEdmaMasterRxRegToRxDataHandle)); memset(&(dspiEdmaMasterTxDataToIntermediaryHandle), 0, sizeof(dspiEdmaMasterTxDataToIntermediaryHandle)); memset(&(dspiEdmaMasterIntermediaryToTxRegHandle), 0, sizeof(dspiEdmaMasterIntermediaryToTxRegHandle)); EDMA_CreateHandle(&(dspiEdmaMasterRxRegToRxDataHandle), EXAMPLE_DSPI_MASTER_DMA_BASEADDR, masterRxChannel); EDMA_CreateHandle(&(dspiEdmaMasterTxDataToIntermediaryHandle), EXAMPLE_DSPI_MASTER_DMA_BASEADDR, masterIntermediaryChannel); EDMA_CreateHandle(&(dspiEdmaMasterIntermediaryToTxRegHandle), EXAMPLE_DSPI_MASTER_DMA_BASEADDR, masterTxChannel); DSPI_MasterTransferCreateHandleEDMA(EXAMPLE_DSPI_MASTER_BASEADDR, &g_dspi_edma_m_handle, DSPI_MasterUserCallback, NULL, &dspiEdmaMasterRxRegToRxDataHandle, &dspiEdmaMasterTxDataToIntermediaryHandle, &dspiEdmaMasterIntermediaryToTxRegHandle); /* Start master transfer */ masterXfer.txData = masterTxData; masterXfer.rxData = masterRxData; masterXfer.dataSize = TRANSFER_SIZE; masterXfer.configFlags = kDSPI_MasterCtar0 | EXAMPLE_DSPI_MASTER_PCS_FOR_TRANSFER | kDSPI_MasterPcsContinuous; if (kStatus_Success != DSPI_MasterTransferEDMA(EXAMPLE_DSPI_MASTER_BASEADDR, &g_dspi_edma_m_handle, &masterXfer)) { PRINTF("There is error when start DSPI_MasterTransferEDMA \r\n "); } /* Wait until transfer completed */ while (!isTransferCompleted) { } /* Check the data */ errorCount = 0U; for (i = 0U; i < TRANSFER_SIZE; i++) { if (masterTxData[i] != slaveRxData[i]) { errorCount++; } if (slaveTxData[i] != masterRxData[i]) { errorCount++; } } if (errorCount == 0) { PRINTF("DSPI transfer all data matched! \r\n"); } else { PRINTF("Error occured in DSPI transfer ! \r\n"); } DSPI_Deinit(EXAMPLE_DSPI_MASTER_BASEADDR); DSPI_Deinit(EXAMPLE_DSPI_SLAVE_BASEADDR); while (1) { } }