Logo Search packages:      
Sourcecode: linux version File versions  Download package

void dmacHw_initiateTransfer ( dmacHw_HANDLE_t  handle,
dmacHw_CONFIG_t pConfig,
void *  pDescriptor 
)

Program channel register to initiate transfer.

Returns:
void
Note:
  • Descriptor buffer MUST ALWAYS be flushed before calling this function
  • This function should also be called from ISR to program the channel with pending descriptors

Definition at line 109 of file dmacHw.c.

      {
      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);
}

Generated by  Doxygen 1.6.0   Back to index