void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle, dmacHw_CONFIG_t *pConfig, void *pDescriptor ) { dmacHw_DESC_RING_t *pRing; dmacHw_DESC_t *pProg; dmacHw_CBLK_t *pCblk; pCblk = dmacHw_HANDLE_TO_CBLK(handle); pRing = dmacHw_GET_DESC_RING(pDescriptor); if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { return; } if (pCblk->varDataStarted) { if (pCblk->descUpdated) { pCblk->descUpdated = 0; pProg = (dmacHw_DESC_t *) ((uint32_t) dmacHw_REG_LLP(pCblk->module, pCblk->channel) + pRing->virt2PhyOffset); if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) { dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = pProg->ctl.lo; dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = pProg->ctl.hi; } else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) { return; } else { dmacHw_ASSERT(0); } } else { return; } } else { if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) { pProg = pRing->pHead; dmacHw_NEXT_DESC(pRing, pHead); } else { if (pRing->pEnd == NULL) { return; } pProg = pRing->pProg; if (pConfig->transferMode == dmacHw_TRANSFER_MODE_CONTINUOUS) { dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd-> llp == pRing->pProg); dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg == pRing->pHead); do { pRing->pProg->ctl.lo |= (dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); pRing->pProg = (dmacHw_DESC_t *) pRing->pProg->llp; } while (pRing->pProg != pRing->pHead); } else { while (pRing->pProg != pRing->pEnd) { pRing->pProg->ctl.lo |= (dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); pRing->pProg = (dmacHw_DESC_t *) pRing->pProg->llp; } } } dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); dmacHw_SET_LLP(pCblk->module, pCblk->channel, (uint32_t) pProg - pRing->virt2PhyOffset); dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = pProg->ctl.lo; dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = pProg->ctl.hi; if (pRing->pEnd) { pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp; } pRing->pEnd = (dmacHw_DESC_t *) NULL; } dmacHw_DMA_START(pCblk->module, pCblk->channel); }
void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ void *pDescriptor /* [ IN ] Descriptor buffer */ ) { dmacHw_DESC_RING_t *pRing; dmacHw_DESC_t *pProg; dmacHw_CBLK_t *pCblk; pCblk = dmacHw_HANDLE_TO_CBLK(handle); pRing = dmacHw_GET_DESC_RING(pDescriptor); if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { /* Not safe yet to program the channel */ return; } if (pCblk->varDataStarted) { if (pCblk->descUpdated) { pCblk->descUpdated = 0; pProg = (dmacHw_DESC_t *) ((uint32_t) dmacHw_REG_LLP(pCblk->module, pCblk->channel) + pRing->virt2PhyOffset); /* Load descriptor if not loaded */ if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) { dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = pProg->ctl.lo; dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = pProg->ctl.hi; } else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) { /* Return as end descriptor is processed */ return; } else { dmacHw_ASSERT(0); } } else { return; } } else { if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) { /* Do not make a single chain, rather process one descriptor at a time */ pProg = pRing->pHead; /* Point to the next descriptor for next iteration */ dmacHw_NEXT_DESC(pRing, pHead); } else { /* Return if no more pending descriptor */ if (pRing->pEnd == NULL) { return; } pProg = pRing->pProg; if (pConfig->transferMode == dmacHw_TRANSFER_MODE_CONTINUOUS) { /* Make sure a complete ring can be formed */ dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd-> llp == pRing->pProg); /* Make sure pProg pointing to the pHead */ dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg == pRing->pHead); /* Make a complete ring */ do { pRing->pProg->ctl.lo |= (dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); pRing->pProg = (dmacHw_DESC_t *) pRing->pProg->llp; } while (pRing->pProg != pRing->pHead); } else { /* Make a single long chain */ while (pRing->pProg != pRing->pEnd) { pRing->pProg->ctl.lo |= (dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); pRing->pProg = (dmacHw_DESC_t *) pRing->pProg->llp; } } } /* Program the channel registers */ dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); dmacHw_SET_LLP(pCblk->module, pCblk->channel, (uint32_t) pProg - pRing->virt2PhyOffset); dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = pProg->ctl.lo; dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = pProg->ctl.hi; if (pRing->pEnd) { /* Remember the descriptor to use next */ pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp; } /* Indicate no more pending descriptor */ pRing->pEnd = (dmacHw_DESC_t *) NULL; } /* Start DMA operation */ dmacHw_DMA_START(pCblk->module, pCblk->channel); }