OSStatus host_platform_spi_transfer( bus_transfer_direction_t dir, uint8_t* buffer, uint16_t buffer_length ) { OSStatus result; int i; for(i=0; i<buffer_length; i++) { buffer_temp_32[i] = SPI0_TXCMD | (uint32_t)buffer[i];; } dmaSPITX.dmaChStcd = (edma_software_tcd_t *)mem_align(2 * sizeof(edma_software_tcd_t) * dmaSPITX.period, 32); dmaSPITX.srcAddr = (uint32_t)buffer_temp_32; dmaSPITX.length = buffer_length * 4; dmaSPIRX.dmaChStcd = (edma_software_tcd_t *)mem_align(2 * sizeof(edma_software_tcd_t) * dmaSPIRX.period, 32); dmaSPIRX.destAddr = (uint32_t)buffer; dmaSPIRX.length = buffer_length; MCU_CLOCKS_NEEDED(); SPI0_CS_ENABLE; setup_edma_loop(&dmaSPITX); setup_edma_loop(&dmaSPIRX); EDMA_DRV_StartChannel(dmaSPIRX.dmaCh); EDMA_DRV_StartChannel(dmaSPITX.dmaCh); result = mico_rtos_get_semaphore( &spi_transfer_finished_semaphore, 100 ); disable_edma_loop(&dmaSPIRX); disable_edma_loop(&dmaSPITX); SPI0_CS_DISABLE; MCU_CLOCKS_NOT_NEEDED(); free_align(dmaSPITX.dmaChStcd); free_align(dmaSPIRX.dmaChStcd); return result; }
OSStatus spi_dma_transfer(const uint8_t* data_out, uint8_t* data_in, uint32_t size ) { uint32_t i,loop_count = MAX_LOOP_COUNT; spi_dma_sem = 0; for(i=0;i<size;i++) spi_tx_buffer[i] = (uint32_t) *data_out++; write_dmaLoop.dmaChanNum = DMA_CH0; write_dmaLoop.dmaCh = &dmaCh0; write_dmaLoop.type = kEDMAMemoryToPeripheral; write_dmaLoop.chSource = kDmaRequestMux0SPI0Tx; write_dmaLoop.srcAddr = (uint32_t)spi_tx_buffer; write_dmaLoop.destAddr = (uint32_t)&SPI0->PUSHR; write_dmaLoop.length = size*4; write_dmaLoop.size = 4; write_dmaLoop.watermark = 4; write_dmaLoop.period = 1; write_dmaLoop.dmaCallBack = stop_tx_edma; setup_edma_loop(&write_dmaLoop); read_dmaLoop.dmaChanNum = DMA_CH1; read_dmaLoop.dmaCh = &dmaCh1; read_dmaLoop.type = kEDMAPeripheralToMemory; read_dmaLoop.chSource = kDmaRequestMux0SPI0Rx; read_dmaLoop.srcAddr = (uint32_t)&SPI0->POPR; read_dmaLoop.destAddr = (uint32_t)data_in; read_dmaLoop.length = size; read_dmaLoop.size = 1; read_dmaLoop.watermark = 1; read_dmaLoop.period = 1; read_dmaLoop.dmaCallBack = stop_rx_edma; setup_edma_loop(&read_dmaLoop); EDMA_DRV_StartChannel(read_dmaLoop.dmaCh); EDMA_DRV_StartChannel(write_dmaLoop.dmaCh); while(loop_count>0) { if(spi_dma_sem) return kNoErr; //loop_count--; } return kTimeoutErr; }
/*FUNCTION********************************************************************** * * Function Name : SND_RxConfigDataFormat * Description : Configure the audio file format in rx soundcard. * The soundcard includes a controller and a codec. The audio format includes * sample rate, bit length and so on. *END**************************************************************************/ snd_status_t SND_RxConfigDataFormat(sound_card_t *card, ctrl_data_format_t *format) { audio_controller_t *ctrl = &card->controller; audio_codec_t *codec = &card->codec; ctrl->ops->Ctrl_RxConfigDataFormat(ctrl->instance, format); codec->ops->Codec_ConfigDataFormat(codec->handler, format->mclk, format->sample_rate, format->bits); /* Configure dma */ #if USEDMA audio_buffer_t *buffer = &card->buffer; uint8_t sample_size = format->bits/8; uint32_t watermark = ctrl->ops->Ctrl_RxGetWatermark(ctrl->instance); if((sample_size == 3) || (format->bits & 0x7)) { sample_size = 4; } uint32_t * desAddr = ctrl->ops->Ctrl_RxGetFifoAddr(ctrl->instance,ctrl->fifo_channel); EDMA_DRV_ConfigLoopTransfer( &ctrl->dma_channel, ctrl->stcd, kEDMAPeripheralToMemory, (uint32_t)desAddr, (uint32_t)buffer->buff, sample_size, sample_size * watermark, AUDIO_BUFFER_SIZE, AUDIO_BUFFER_BLOCK); EDMA_DRV_StartChannel(&ctrl->dma_channel); #endif return kStatus_SND_Success; }
/*FUNCTION********************************************************************** * * Function Name : SND_RxStart * Description : This function is used to start rx receive. *END**************************************************************************/ void SND_RxStart(sound_card_t *card) { audio_controller_t *ctrl = &card->controller; #if !USEDMA audio_buffer_t *buffer = &card->buffer; ctrl->ops->Ctrl_ReceiveData(ctrl->instance, buffer->input_curbuff, buffer->size); ctrl->ops->Ctrl_RxSetIntCmd(ctrl->instance, true); #else ctrl->ops->Ctrl_RxSetDmaCmd(ctrl->instance,true); EDMA_DRV_StartChannel(&card->controller.dma_channel); #endif ctrl->ops->Ctrl_RxStart(ctrl->instance); }
/*FUNCTION********************************************************************** * * Function Name : UART_DRV_EdmaStartReceiveData * Description : Initiate (start) a receive by beginning the process of * receiving data and enabling the interrupt. * This is not a public API as it is called from other driver functions. * *END**************************************************************************/ static uart_status_t UART_DRV_EdmaStartReceiveData(uint32_t instance, uint8_t * rxBuff, uint32_t rxSize) { assert(instance < UART_INSTANCE_COUNT); UART_Type * base = g_uartBase[instance]; edma_transfer_config_t edmaRxConfig; edmaRxConfig.srcAddr = UART_HAL_GetDataRegAddr(base); edmaRxConfig.destAddr = (uint32_t)rxBuff; edmaRxConfig.srcTransferSize = kEDMATransferSize_1Bytes; edmaRxConfig.destTransferSize = kEDMATransferSize_1Bytes; edmaRxConfig.srcOffset = 0U; edmaRxConfig.destOffset = 1U; edmaRxConfig.srcLastAddrAdjust = 0U; edmaRxConfig.destLastAddrAdjust = 0U; edmaRxConfig.srcModulo = kEDMAModuloDisable; edmaRxConfig.destModulo = kEDMAModuloDisable; edmaRxConfig.minorLoopCount = 1U; edmaRxConfig.majorLoopCount = rxSize; edma_software_tcd_t stcd; /* Get current runtime structure. */ uart_edma_state_t * uartEdmaState = (uart_edma_state_t *)g_uartStatePtr[instance]; /* Check that we're not busy already receiving data from a previous function call. */ if (uartEdmaState->isRxBusy) { return kStatus_UART_RxBusy; } /* Update UART DMA run-time structure. */ uartEdmaState->isRxBusy = true; memset(&stcd, 0, sizeof(edma_software_tcd_t)); /* Sets the descriptor basic transfer for the descriptor. */ EDMA_DRV_PrepareDescriptorTransfer(&uartEdmaState->edmaUartRx, &stcd, &edmaRxConfig, true, true); /* Copies the software TCD configuration to the hardware TCD */ EDMA_DRV_PushDescriptorToReg(&uartEdmaState->edmaUartRx, &stcd); /* Start DMA channel */ EDMA_DRV_StartChannel(&uartEdmaState->edmaUartRx); return kStatus_UART_Success; }
/*FUNCTION********************************************************************* * * Function Name : FLEXIO_Camera_DRV_ResetEdmaRx * Description : Reset the EDMA transfer loop's destination address and loop * counter, which means the EDMA transfer would be reset to the initialized state. * This API would be called when VSYNC event happenned to make sure the data * from camera would not be misplaced. However, if there is other application * configuration can do the same thing, this API would not be necessary. * *END*************************************************************************/ flexio_camera_status_t FLEXIO_Camera_DRV_ResetEdmaRx( flexio_camera_edma_handler_t *handler) { uint32_t ret; edma_transfer_config_t rxEdmeConfigStruct; edma_software_tcd_t rxEdmaChnStcd[2]; flexio_camera_dev_t *flexioCameraHwConfigPtr = &(handler->flexioCameraHwConfig); EDMA_DRV_StopChannel(&handler->rxEdmaChnState); /* 3. Configure the channel. */ rxEdmeConfigStruct.srcAddr = FLEXIO_Camera_HAL_GetRxBufferAddr(flexioCameraHwConfigPtr); rxEdmeConfigStruct.destAddr = handler->userBufAddr; rxEdmeConfigStruct.srcTransferSize = kEDMATransferSize_32Bytes; rxEdmeConfigStruct.destTransferSize = kEDMATransferSize_32Bytes; rxEdmeConfigStruct.srcOffset = 0; rxEdmeConfigStruct.destOffset = 4U * (flexioCameraHwConfigPtr->shifterCount); /* 4 byte per shifter, typically 32 byte for 8 shifters. */ rxEdmeConfigStruct.srcLastAddrAdjust = 0; rxEdmeConfigStruct.destLastAddrAdjust = -(int32_t)(handler->userBufLenByte); rxEdmeConfigStruct.srcModulo = kEDMAModuloDisable; rxEdmeConfigStruct.destModulo = kEDMAModuloDisable; rxEdmeConfigStruct.minorLoopCount = rxEdmeConfigStruct.destOffset; /* the minor loop would read all the data in shifters one time per trigger. */ rxEdmeConfigStruct.majorLoopCount = (handler->userBufLenByte)/(rxEdmeConfigStruct.minorLoopCount); ret = EDMA_DRV_PrepareDescriptorTransfer( &handler->rxEdmaChnState, rxEdmaChnStcd, &rxEdmeConfigStruct, false, /* Always disable transfer done interrupt. */ false /* Always disable auto shutdown req. */ ); if (ret == kEDMAInvalidChannel) { return kStatus_FlexIO_Camera_Failed; } ret = EDMA_DRV_PushDescriptorToReg( &handler->rxEdmaChnState, rxEdmaChnStcd); if (ret == kEDMAInvalidChannel) { return kStatus_FlexIO_Camera_Failed; } EDMA_DRV_StartChannel(&handler->rxEdmaChnState); return kStatus_FlexIO_Camera_Success; }
/*FUNCTION********************************************************************* * * Function Name : FLEXIO_Camera_DRV_StartEdmaRx * Description : Start the flexio_camera_edma device. After the initializatioin, * the EDMA would be triggered and start the tranfer by calling this API. Then * the memory mapping can be executed. * *END*************************************************************************/ flexio_camera_status_t FLEXIO_Camera_DRV_StartEdmaRx( flexio_camera_edma_handler_t *handler) { uint32_t ret; flexio_camera_dev_t *flexioCameraHwConfigPtr = &(handler->flexioCameraHwConfig); /* Clear the flexio flags. */ FLEXIO_Camera_HAL_ClearRxBufferFullFlag(flexioCameraHwConfigPtr); /* Enable the DMA trigger of the first shifter. */ FLEXIO_Camera_HAL_SetRxBufferDmaCmd(flexioCameraHwConfigPtr, 0x01, true); ret = EDMA_DRV_StartChannel(&handler->rxEdmaChnState); if (ret == kEDMAInvalidChannel) { return kStatus_FlexIO_Camera_Failed; } return kStatus_FlexIO_Camera_Success; }
/*FUNCTION********************************************************************** * * Function Name : QSPI_DRV_ReadDataEdma * Description : Read data from QSPI rx FIFO/Buffer using EDMA way. This function * will open dma enable bit and transfer data in ISR. * *END**************************************************************************/ void QSPI_DRV_ReadDataEdma(uint32_t instance, uint32_t * addr, uint32_t size) { QuadSPI_Type * base = g_qspiBase[instance]; edma_transfer_config_t config = {0}; /* Update internal state */ g_qspiState[instance]->rxSize = size; g_qspiState[instance]->rxAddr = addr; g_qspiState[instance]->rxFinishedBytes = 0; if (!g_qspiState[instance]->rxUseDma) { /* Request edma channel */ uint8_t channel = 0; channel = EDMA_DRV_RequestChannel(kEDMAAnyChannel, g_qspiState[instance]->rxSource, &g_qspiState[instance]->rxEdmaChn); if (channel == kEDMAInvalidChannel) { return; } EDMA_DRV_InstallCallback(&g_qspiState[instance]->rxEdmaChn, QSPI_DRV_RxEdmaCallback, g_qspiState[instance]); g_qspiState[instance]->rxUseDma = true; } config.destAddr = (uint32_t)addr; config.destOffset = 4; config.destTransferSize = kEDMATransferSize_4Bytes; /* AHB buffer or ARDB */ config.srcAddr = QSPI_HAL_GetRxFifoAddr(base); config.srcTransferSize = kEDMATransferSize_4Bytes; config.srcOffset = 0; config.minorLoopCount = 4 * g_qspiState[instance]->rxWatermark; config.majorLoopCount = size/config.minorLoopCount; EDMA_DRV_PrepareDescriptorTransfer(&g_qspiState[instance]->rxEdmaChn, STCD_ADDR(g_qspiState[instance]->rxEdmaTCD), &config, true, true); EDMA_DRV_PushDescriptorToReg(&g_qspiState[instance]->rxEdmaChn, STCD_ADDR(g_qspiState[instance]->rxEdmaTCD)); EDMA_DRV_StartChannel(&g_qspiState[instance]->rxEdmaChn); /* Enable dma request */ QSPI_HAL_SetDmaCmd(base, kQspiRxBufferDrainDmaFlag, true); /* Enable interrupt to clear the underrun. */ QSPI_HAL_SetIntCmd(base, kQspiRxBufferOverflow, true); /* Enable module */ QSPI_HAL_EnableModule(base); g_qspiState[instance]->isRxBusy = true; }
/*FUNCTION********************************************************************** * * Function Name : QSPI_DRV_WriteDataEdma * Description : Write data into QSPI tx FIFO using EDMA. This function * will open dma enable bit and transfer data using EDMA. * *END**************************************************************************/ qspi_status_t QSPI_DRV_WriteDataEdma(uint32_t instance, uint32_t * addr, uint32_t size) { QuadSPI_Type * base = g_qspiBase[instance]; edma_transfer_config_t config = {0}; /* Update internal state */ g_qspiState[instance]->txSize = size; g_qspiState[instance]->txAddr = addr; g_qspiState[instance]->txFinishedBytes = 0; /* Request edma channel */ if (!g_qspiState[instance]->txUseDma) { uint8_t channel = 0; channel = EDMA_DRV_RequestChannel(kEDMAAnyChannel, g_qspiState[instance]->txSource, &g_qspiState[instance]->txEdmaChn); if (channel == kEDMAInvalidChannel) { return kStatus_QSPI_Fail; } EDMA_DRV_InstallCallback(&g_qspiState[instance]->txEdmaChn, QSPI_DRV_TxEdmaCallback, g_qspiState[instance]); g_qspiState[instance]->txUseDma = true; } config.srcAddr = (uint32_t)addr; config.destAddr = QSPI_HAL_GetTxFifoAddr(base); config.destTransferSize = kEDMATransferSize_4Bytes; config.srcTransferSize = kEDMATransferSize_4Bytes; config.destOffset = 0; config.srcOffset = 4; config.minorLoopCount = 4 * (FSL_FEATURE_QSPI_TXFIFO_DEPTH -g_qspiState[instance]->txWatermark); config.majorLoopCount = size/config.minorLoopCount; EDMA_DRV_PrepareDescriptorTransfer(&g_qspiState[instance]->txEdmaChn, STCD_ADDR(g_qspiState[instance]->txEdmaTCD), &config, true, true); EDMA_DRV_PushDescriptorToReg(&g_qspiState[instance]->txEdmaChn, STCD_ADDR(g_qspiState[instance]->txEdmaTCD)); EDMA_DRV_StartChannel(&g_qspiState[instance]->txEdmaChn); /* Enable dma request */ QSPI_HAL_SetDmaCmd(base, kQspiTxBufferFillDmaFlag, true); /* Enable interrupt to clear the underrun. */ QSPI_HAL_SetIntCmd(base, kQspiTxBufferUnderrun, true); /* Enable module */ QSPI_HAL_EnableModule(base); g_qspiState[instance]->isTxBusy = true; return kStatus_QSPI_Success; }