/** * @brief Sets the number of transfers to be performed. * @note This function can be invoked in both ISR or thread context. * * @pre The channel must have been allocated using @p dmaChannelAllocate(). * @post After use the channel can be released using @p dmaChannelRelease(). * * @param[in] dmastp pointer to a sama_dma_channel_t structure * @param[in] size value to be written in the XDMAC_CUBC register * * @special * */ void dmaChannelSetTransactionSize(sama_dma_channel_t *dmachp, size_t n) { uint32_t i; uint32_t divisor; /* Single block single microblock */ if (n <= XDMAC_MAX_BT_SIZE) { (dmachp)->xdmac->XDMAC_CHID[(dmachp)->chid].XDMAC_CUBC = XDMAC_CUBC_UBLEN(n); } /* Single block multiple microblocks */ else { /* If n exceeds XDMAC_MAX_BT_SIZE, split the transfer in microblocks */ for (i = 2; i < XDMAC_MAX_BT_SIZE; i++) { divisor = XDMAC_MAX_BT_SIZE / i; if (n % divisor) continue; if ((n / divisor) <= (XDMAC_MAX_BLOCK_LEN + 1)) { (dmachp)->xdmac->XDMAC_CHID[(dmachp)->chid].XDMAC_CUBC = XDMAC_CUBC_UBLEN(i); (dmachp)->xdmac->XDMAC_CHID[(dmachp)->chid].XDMAC_CBC = XDMAC_CBC_BLEN((n / divisor) - 1); break; } } osalDbgAssert(i != XDMAC_MAX_BT_SIZE, "unsupported DMA transfer size"); } }
/** * \brief Prepare link list for USART RX * Ringed link list initialized for 2 USART buffer. */ static void _UsartDmaRxSetup(void) { Usart *pUs = BASE_USART; dmaRxLinkList.mbr_ubc = XDMA_UBC_NVIEW_NDV1 | XDMA_UBC_NDE_FETCH_EN | XDMA_UBC_NSEN_UPDATED | XDMAC_CUBC_UBLEN(DATAPACKETSIZE); dmaRxLinkList.mbr_sa = (uint32_t)&pUs->US_RHR; dmaRxLinkList.mbr_da = (uint32_t)usartBuffers[0]; }
static uint8_t _Dac_configureLinkList(Dacc *pDacHw, void *pXdmad, DacCmd *pCommand) { uint32_t xdmaCndc; sXdmadCfg xdmadCfg; uint32_t *pBuffer; /* Setup TX Link List */ uint8_t i; pBuffer = (uint32_t *)pCommand->pTxBuff; for (i = 0; i < pCommand->TxSize; i++) { dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 | XDMA_UBC_NDE_FETCH_EN | XDMA_UBC_NSEN_UPDATED | XDMAC_CUBC_UBLEN(4); dmaWriteLinkList[i].mbr_sa = (uint32_t)pBuffer; dmaWriteLinkList[i].mbr_da = (uint32_t) & (pDacHw->DACC_CDR[pCommand->dacChannel]); if (i == (pCommand->TxSize - 1)) { if (pCommand->loopback) dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0]; else dmaWriteLinkList[i].mbr_nda = 0; } else dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i + 1]; pBuffer++; } xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD | XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF1 | XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM | XDMAC_CC_PERID( XDMAIF_Get_ChannelNumber(ID_DACC, XDMAD_TRANSFER_TX)); xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED; XDMAD_ConfigureTransfer(pXdmad, dacDmaTxChannel, &xdmadCfg, xdmaCndc, (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE); return DAC_OK; }
/** * \brief xDMA transfer PWM duty */ static void _PwmDmaTransfer(void) { sXdmadCfg xdmadCfg; uint32_t xdmaCndc; uint32_t i; for(i = 0; i < DUTY_BUFFER_LENGTH; i++){ dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 | XDMA_UBC_NDE_FETCH_EN | XDMA_UBC_NSEN_UPDATED | XDMAC_CUBC_UBLEN(1); dmaWriteLinkList[i].mbr_sa = (uint32_t)(&dwDutys[i]); dmaWriteLinkList[i].mbr_da = (uint32_t)(&(PWM0->PWM_DMAR)); if ( i == (DUTY_BUFFER_LENGTH - 1 )) { dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0]; } else { dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i+1]; } } xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_HALFWORD | XDMAC_CC_SIF_AHB_IF0 | XDMAC_CC_DIF_AHB_IF1 | XDMAC_CC_SAM_FIXED_AM | XDMAC_CC_DAM_FIXED_AM | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_PWM0, XDMAD_TRANSFER_TX )); xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ; XDMAD_ConfigureTransfer( &dmad, pwmDmaTxChannel, &xdmadCfg, xdmaCndc, (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE); SCB_CleanInvalidateDCache(); XDMAD_StartTransfer( &dmad, pwmDmaTxChannel); }
/** * \brief Receive and play audio with DMA. */ static void PlayRecording(void) { uint32_t src; uint8_t i; uint32_t xdmaCndc; src = 0x20440000; for(i = 0; i < TOTAL_Buffers; i++){ dmaReadLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 | XDMA_UBC_NDE_FETCH_EN | XDMA_UBC_NSEN_UPDATED | XDMAC_CUBC_UBLEN(0x1000); dmaReadLinkList[i].mbr_sa = (uint32_t)&(AUDIO_IF->SSC_RHR); dmaReadLinkList[i].mbr_da = (uint32_t)(src ); if ( i == (TOTAL_Buffers - 1)){ dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[0]; } else { dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[i + 1]; } src += (0x1000 * (BITS_BY_SLOT/8)); } xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_PER2MEM | XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_HALFWORD | XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF0 | XDMAC_CC_SAM_FIXED_AM | XDMAC_CC_DAM_INCREMENTED_AM | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_RX )); xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ; XDMAD_ConfigureTransfer( &dmad, sscDmaRxChannel, &xdmadCfg, xdmaCndc, (uint32_t)&dmaReadLinkList[0],XDMAC_CIE_LIE); SCB_CleanInvalidateDCache(); src = 0x20440000; for(i = 0; i < TOTAL_Buffers; i++){ dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 | XDMA_UBC_NDE_FETCH_EN | XDMA_UBC_NSEN_UPDATED | XDMAC_CUBC_UBLEN(0x1000); dmaWriteLinkList[i].mbr_sa = (uint32_t)(src ); dmaWriteLinkList[i].mbr_da = (uint32_t)&(AUDIO_IF->SSC_THR); if ( i == (TOTAL_Buffers - 1 )) { dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0]; } else { dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i+1]; } src += (0x1000 * (BITS_BY_SLOT/8)); } xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_HALFWORD | XDMAC_CC_SIF_AHB_IF0 | XDMAC_CC_DIF_AHB_IF1 | XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_TX )); xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ; XDMAD_ConfigureTransfer( &dmad, sscDmaTxChannel, &xdmadCfg, xdmaCndc, (uint32_t)&dmaWriteLinkList[0],XDMAC_CIE_LIE); SCB_CleanInvalidateDCache(); XDMAD_StartTransfer( &dmad, sscDmaRxChannel ); SSC_EnableReceiver(AUDIO_IF); Wait(3000); /* Enable playback(SSC TX) */ SCB_CleanInvalidateDCache(); XDMAD_StartTransfer( &dmad, sscDmaTxChannel); SSC_EnableTransmitter(AUDIO_IF); }
/** * \brief Set microblock length for the relevant channel of given XDMA. * * \param pXdmac Pointer to the XDMAC peripheral. * \param channel Particular channel number. * \param ublen Microblock length. */ void XDMAC_SetMicroblockControl(Xdmac *pXdmac, uint8_t channel, uint32_t ublen) { assert(pXdmac); assert(channel < XDMAC_CHANNEL_NUM); pXdmac->XDMAC_CHID[channel].XDMAC_CUBC = XDMAC_CUBC_UBLEN(ublen); }