/***************************************************************************//** * @brief * Start a LDMA transfer. * * @details * This function can only be used on LDMA when @ref EMDRV_DMADRV_USE_NATIVE_API * is defined. It is a wrapper around similar emlib ldma function. * * @param[in] channelId * The channel Id to use. * * @param[in] transfer * DMA transfer configuration data structure. * * @param[in] descriptor * DMA transfer descriptor, can be an array of descriptors linked together. * * @param[in] callback * Optional callback function for signalling completion. May be NULL if not * needed. * * @param[in] cbUserParam * Optional user parameter to feed to the callback function. May be NULL if * not needed. * * @return * @ref ECODE_EMDRV_DMADRV_OK on success. On failure an appropriate * DMADRV @ref Ecode_t is returned. ******************************************************************************/ Ecode_t DMADRV_LdmaStartTransfer( int channelId, LDMA_TransferCfg_t *transfer, LDMA_Descriptor_t *descriptor, DMADRV_Callback_t callback, void *cbUserParam ) { ChTable_t *ch; if ( !initialized ) { return ECODE_EMDRV_DMADRV_NOT_INITIALIZED; } if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT ) { return ECODE_EMDRV_DMADRV_PARAM_ERROR; } ch = &chTable[ channelId ]; if ( ch->allocated == false ) { return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED; } ch->callback = callback; ch->userParam = cbUserParam; ch->callbackCount = 0; LDMA_StartTransfer( channelId, transfer, descriptor ); return ECODE_EMDRV_DMADRV_OK; }
void LDMAx_StartTransfer( int ch, LDMA_TransferCfg_t *transfer, LDMA_Descriptor_t *descriptor, LDMAx_CBFunc_t cbFunc, void *userData ) { ldmaCallback[ch].callback = cbFunc; ldmaCallback[ch].userdata = userData; LDMA_StartTransfer(ch, transfer, descriptor); }
/***************************************************************************//** * @brief * Start a LDMA transfer. ******************************************************************************/ static Ecode_t StartTransfer( DmaMode_t mode, DmaDirection_t direction, unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *buf0, void *buf1, void *buf2, bool bufInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam ) { ChTable_t *ch; LDMA_TransferCfg_t xfer; LDMA_Descriptor_t *desc; if ( !initialized ) { return ECODE_EMDRV_DMADRV_NOT_INITIALIZED; } if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT ) || ( buf0 == NULL ) || ( buf1 == NULL ) || ( len > DMADRV_MAX_XFER_COUNT ) || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) ) { return ECODE_EMDRV_DMADRV_PARAM_ERROR; } ch = &chTable[ channelId ]; if ( ch->allocated == false ) { return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED; } xfer = xferCfg; desc = &dmaXfer[ channelId ].desc[0]; if ( direction == dmaDirectionMemToPeripheral ) { *desc = m2p; if ( !bufInc ) { desc->xfer.srcInc = ldmaCtrlSrcIncNone; } } else { *desc = p2m; if ( !bufInc ) { desc->xfer.dstInc = ldmaCtrlDstIncNone; } } xfer.ldmaReqSel = peripheralSignal; desc->xfer.xferCnt = len - 1; desc->xfer.dstAddr = (uint32_t)buf0; desc->xfer.srcAddr = (uint32_t)buf1; desc->xfer.size = size; if ( mode == dmaModePingPong ) { desc->xfer.linkMode = ldmaLinkModeRel; desc->xfer.link = 1; desc->xfer.linkAddr = 4; /* Refer to "pong" descriptor. */ /* Set the "pong" descriptor equal to the "ping" descriptor. */ dmaXfer[ channelId ].desc[1] = *desc; /* Refer to "ping" descriptor. */ dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4; dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2; if ( direction == dmaDirectionPeripheralToMem ) { dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1; desc->xfer.srcAddr = (uint32_t)buf2; } } /* Interrupt needed ? */ if ( ( callback == NULL ) && ( mode == dmaModeBasic ) ) { desc->xfer.doneIfs = 0; } ch->callback = callback; ch->userParam = cbUserParam; ch->callbackCount = 0; ch->mode = mode; LDMA_StartTransfer( channelId, &xfer, desc ); return ECODE_EMDRV_DMADRV_OK; }