void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle, void *userData ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); pCblk->userData = userData; }
int dmacHw_initChannel(dmacHw_HANDLE_t handle ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); int module = pCblk->module; int channel = pCblk->channel; memset((void *)pCblk, 0, sizeof(dmacHw_CBLK_t)); pCblk->module = module; pCblk->channel = channel; dmacHw_DMA_ENABLE(pCblk->module); dmacHw_RESET_CONTROL_LO(pCblk->module, pCblk->channel); dmacHw_RESET_CONTROL_HI(pCblk->module, pCblk->channel); dmacHw_RESET_CONFIG_LO(pCblk->module, pCblk->channel); dmacHw_RESET_CONFIG_HI(pCblk->module, pCblk->channel); dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_STRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_DTRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); return 0; }
int dmacHw_initChannel(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); int module = pCblk->module; int channel = pCblk->channel; /* Reinitialize the control block */ memset((void *)pCblk, 0, sizeof(dmacHw_CBLK_t)); pCblk->module = module; pCblk->channel = channel; /* Enable DMA controller */ dmacHw_DMA_ENABLE(pCblk->module); /* Reset DMA channel */ dmacHw_RESET_CONTROL_LO(pCblk->module, pCblk->channel); dmacHw_RESET_CONTROL_HI(pCblk->module, pCblk->channel); dmacHw_RESET_CONFIG_LO(pCblk->module, pCblk->channel); dmacHw_RESET_CONFIG_HI(pCblk->module, pCblk->channel); /* Clear all raw interrupt status */ dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); /* Mask event specific interrupts */ dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_STRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_DTRAN_INT_DISABLE(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); return 0; }
void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ void *userData /* [ IN ] User data */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); pCblk->userData = userData; }
void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); }
void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ void *pDescriptor, /* [ IN ] Descriptor buffer */ int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); DisplayRegisterContents(pCblk->module, pCblk->channel, fpPrint); DisplayDescRing(pDescriptor, fpPrint); }
void dmacHw_stopTransfer(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ ) { dmacHw_CBLK_t *pCblk; pCblk = dmacHw_HANDLE_TO_CBLK(handle); /* Stop the channel */ dmacHw_DMA_STOP(pCblk->module, pCblk->channel); }
void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle, void *pDescriptor, int (*fpPrint) (const char *, ...) ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); DisplayRegisterContents(pCblk->module, pCblk->channel, fpPrint); DisplayDescRing(pDescriptor, fpPrint); }
void dmacHw_stopTransfer(dmacHw_HANDLE_t handle ) { dmacHw_CBLK_t *pCblk; pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_DMA_STOP(pCblk->module, pCblk->channel); }
dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { return dmacHw_TRANSFER_STATUS_BUSY; } else if (dmacHw_REG_INT_RAW_ERROR(pCblk->module) & (0x00000001 << pCblk->channel)) { return dmacHw_TRANSFER_STATUS_ERROR; } return dmacHw_TRANSFER_STATUS_DONE; }
uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle, void *pDescriptor ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); if (!CHANNEL_BUSY(pCblk->module, pCblk->channel)) { if (pRing->pEnd) { return 1; } } return 0; }
uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ void *pDescriptor /* [ IN ] Descriptor buffer */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); /* Make sure channel is not busy */ if (!CHANNEL_BUSY(pCblk->module, pCblk->channel)) { /* Check if pEnd is not processed */ if (pRing->pEnd) { /* Something left for processing */ return 1; } } return 0; }
dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_INTERRUPT_STATUS_e status = dmacHw_INTERRUPT_STATUS_NONE; if (dmacHw_REG_INT_STAT_TRAN(pCblk->module) & ((0x00000001 << pCblk->channel))) { status |= dmacHw_INTERRUPT_STATUS_TRANS; } if (dmacHw_REG_INT_STAT_BLOCK(pCblk->module) & ((0x00000001 << pCblk->channel))) { status |= dmacHw_INTERRUPT_STATUS_BLOCK; } if (dmacHw_REG_INT_STAT_ERROR(pCblk->module) & ((0x00000001 << pCblk->channel))) { status |= dmacHw_INTERRUPT_STATUS_ERROR; } return status; }
static uint32_t GetFifoSize(dmacHw_HANDLE_t handle ) { uint32_t val = 0; dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_MISC_t *pMiscReg = (dmacHw_MISC_t *) dmacHw_REG_MISC_BASE(pCblk->module); switch (pCblk->channel) { case 0: val = (pMiscReg->CompParm2.lo & 0x70000000) >> 28; break; case 1: val = (pMiscReg->CompParm3.hi & 0x70000000) >> 28; break; case 2: val = (pMiscReg->CompParm3.lo & 0x70000000) >> 28; break; case 3: val = (pMiscReg->CompParm4.hi & 0x70000000) >> 28; break; case 4: val = (pMiscReg->CompParm4.lo & 0x70000000) >> 28; break; case 5: val = (pMiscReg->CompParm5.hi & 0x70000000) >> 28; break; case 6: val = (pMiscReg->CompParm5.lo & 0x70000000) >> 28; break; case 7: val = (pMiscReg->CompParm6.hi & 0x70000000) >> 28; break; } if (val <= 0x4) { return 8 << val; } else { dmacHw_ASSERT(0); } return 0; }
uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle, dmacHw_CONTROLLER_ATTRIB_e attr ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); switch (attr) { case dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM: return dmacHw_GET_NUM_CHANNEL(pCblk->module); case dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE: return (1 << (dmacHw_GET_MAX_BLOCK_SIZE (pCblk->module, pCblk->module) + 2)) - 8; case dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM: return dmacHw_GET_NUM_INTERFACE(pCblk->module); case dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH: return 32 << dmacHw_GET_CHANNEL_DATA_WIDTH(pCblk->module, pCblk->channel); case dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE: return GetFifoSize(handle); } dmacHw_ASSERT(0); return 0; }
void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); return pCblk->userData; }
int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle, dmacHw_CONFIG_t *pConfig, void *pDescriptor, uint32_t srcAddr, void *(*fpAlloc) (int len), int len, int num ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_DESC_t *pProg = NULL; dmacHw_DESC_t *pLast = NULL; dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); uint32_t dstAddr; uint32_t controlParam; int i; dmacHw_ASSERT(pConfig->transferType == dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM); if (num > pRing->num) { return -1; } pLast = pRing->pEnd; pProg = pRing->pHead; controlParam = pConfig->srcUpdate | pConfig->dstUpdate | pConfig->srcMaxTransactionWidth | pConfig->dstMaxTransactionWidth | pConfig->srcMasterInterface | pConfig->dstMasterInterface | pConfig->srcMaxBurstWidth | pConfig->dstMaxBurstWidth | dmacHw_REG_CTL_TTFC_PM_PERI | dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN; for (i = 0; i < num; i++) { if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) || ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail) ) { break; } pRing->pHead->sar = srcAddr; if (fpAlloc) { dstAddr = (uint32_t) (*fpAlloc) (len); if (dstAddr == 0) { if (i == 0) { return -1; } break; } pRing->pHead->dar = dstAddr; } pRing->pHead->ctl.lo = controlParam; pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY; pRing->pHead->ctl.hi = 0; pRing->pEnd = pRing->pHead; dmacHw_NEXT_DESC(pRing, pHead); } pRing->pEnd->ctl.lo &= ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); if (pLast != pProg) { pLast->ctl.lo |= dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN; } pCblk->descUpdated = 1; if (!pCblk->varDataStarted) { dmacHw_SET_LLP(pCblk->module, pCblk->channel, (uint32_t) pProg - pRing->virt2PhyOffset); pCblk->varDataStarted = 1; } return i; }
int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ void *pDescriptor, /* [ IN ] Descriptor buffer */ uint32_t srcAddr, /* [ IN ] Source peripheral address */ void *(*fpAlloc) (int len), /* [ IN ] Function pointer that provides destination memory */ int len, /* [ IN ] Number of bytes "fpAlloc" will allocate for destination */ int num /* [ IN ] Number of descriptor to set */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); dmacHw_DESC_t *pProg = NULL; dmacHw_DESC_t *pLast = NULL; dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); uint32_t dstAddr; uint32_t controlParam; int i; dmacHw_ASSERT(pConfig->transferType == dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM); if (num > pRing->num) { return -1; } pLast = pRing->pEnd; /* Last descriptor updated */ pProg = pRing->pHead; /* First descriptor in the new list */ controlParam = pConfig->srcUpdate | pConfig->dstUpdate | pConfig->srcMaxTransactionWidth | pConfig->dstMaxTransactionWidth | pConfig->srcMasterInterface | pConfig->dstMasterInterface | pConfig->srcMaxBurstWidth | pConfig->dstMaxBurstWidth | dmacHw_REG_CTL_TTFC_PM_PERI | dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN; for (i = 0; i < num; i++) { /* Allocate Rx buffer only for idle descriptor */ if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) || ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail) ) { /* Rx descriptor is not idle */ break; } /* Set source address */ pRing->pHead->sar = srcAddr; if (fpAlloc) { /* Allocate memory for buffer in descriptor */ dstAddr = (uint32_t) (*fpAlloc) (len); /* Check the destination address */ if (dstAddr == 0) { if (i == 0) { /* Not a single descriptor is available */ return -1; } break; } /* Set destination address */ pRing->pHead->dar = dstAddr; } /* Set control information */ pRing->pHead->ctl.lo = controlParam; /* Use "devCtl" to mark the memory that need to be freed later */ pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY; /* Descriptor is now owned by the channel */ pRing->pHead->ctl.hi = 0; /* Remember the descriptor last updated */ pRing->pEnd = pRing->pHead; /* Update next descriptor */ dmacHw_NEXT_DESC(pRing, pHead); } /* Mark the end of the list */ pRing->pEnd->ctl.lo &= ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); /* Connect the list */ if (pLast != pProg) { pLast->ctl.lo |= dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN; } /* Mark the descriptors are updated */ pCblk->descUpdated = 1; if (!pCblk->varDataStarted) { /* LLP must be pointing to the first descriptor */ dmacHw_SET_LLP(pCblk->module, pCblk->channel, (uint32_t) pProg - pRing->virt2PhyOffset); /* Channel, handling variable data started */ pCblk->varDataStarted = 1; } return i; }
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); }
int dmacHw_configChannel(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ dmacHw_CONFIG_t *pConfig /* [ IN ] Configuration settings */ ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); uint32_t cfgHigh = 0; int srcTrSize; int dstTrSize; pCblk->varDataStarted = 0; pCblk->userData = NULL; /* Configure - Burst transaction when enough data in available in FIFO - AHB Access protection 1 - Source and destination peripheral ports */ cfgHigh = dmacHw_REG_CFG_HI_FIFO_ENOUGH | dmacHw_REG_CFG_HI_AHB_HPROT_1 | dmacHw_SRC_PERI_INTF(pConfig-> srcPeripheralPort) | dmacHw_DST_PERI_INTF(pConfig->dstPeripheralPort); /* Set priority */ dmacHw_SET_CHANNEL_PRIORITY(pCblk->module, pCblk->channel, pConfig->channelPriority); if (pConfig->dstStatusRegisterAddress != 0) { /* Destination status update enable */ cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_DST_STAT; /* Configure status registers */ dmacHw_SET_DSTATAR(pCblk->module, pCblk->channel, pConfig->dstStatusRegisterAddress); } if (pConfig->srcStatusRegisterAddress != 0) { /* Source status update enable */ cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_SRC_STAT; /* Source status update enable */ dmacHw_SET_SSTATAR(pCblk->module, pCblk->channel, pConfig->srcStatusRegisterAddress); } /* Configure the config high register */ dmacHw_GET_CONFIG_HI(pCblk->module, pCblk->channel) = cfgHigh; /* Clear all raw interrupt status */ dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); /* Configure block interrupt */ if (pConfig->blockTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_BLOCK_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); } /* Configure complete transfer interrupt */ if (pConfig->completeTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_TRAN_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); } /* Configure error interrupt */ if (pConfig->errorInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_ERROR_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); } /* Configure gather register */ if (pConfig->srcGatherWidth) { srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); if (! ((pConfig->srcGatherWidth % srcTrSize) && (pConfig->srcGatherJump % srcTrSize))) { dmacHw_REG_SGR_LO(pCblk->module, pCblk->channel) = ((pConfig->srcGatherWidth / srcTrSize) << 20) | (pConfig->srcGatherJump / srcTrSize); } else { return -1; } } /* Configure scatter register */ if (pConfig->dstScatterWidth) { dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); if (! ((pConfig->dstScatterWidth % dstTrSize) && (pConfig->dstScatterJump % dstTrSize))) { dmacHw_REG_DSR_LO(pCblk->module, pCblk->channel) = ((pConfig->dstScatterWidth / dstTrSize) << 20) | (pConfig->dstScatterJump / dstTrSize); } else { return -1; } } return 0; }
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); }
int dmacHw_configChannel(dmacHw_HANDLE_t handle, dmacHw_CONFIG_t *pConfig ) { dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); uint32_t cfgHigh = 0; int srcTrSize; int dstTrSize; pCblk->varDataStarted = 0; pCblk->userData = NULL; cfgHigh = dmacHw_REG_CFG_HI_FIFO_ENOUGH | dmacHw_REG_CFG_HI_AHB_HPROT_1 | dmacHw_SRC_PERI_INTF(pConfig-> srcPeripheralPort) | dmacHw_DST_PERI_INTF(pConfig->dstPeripheralPort); dmacHw_SET_CHANNEL_PRIORITY(pCblk->module, pCblk->channel, pConfig->channelPriority); if (pConfig->dstStatusRegisterAddress != 0) { cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_DST_STAT; dmacHw_SET_DSTATAR(pCblk->module, pCblk->channel, pConfig->dstStatusRegisterAddress); } if (pConfig->srcStatusRegisterAddress != 0) { cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_SRC_STAT; dmacHw_SET_SSTATAR(pCblk->module, pCblk->channel, pConfig->srcStatusRegisterAddress); } dmacHw_GET_CONFIG_HI(pCblk->module, pCblk->channel) = cfgHigh; dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); if (pConfig->blockTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_BLOCK_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); } if (pConfig->completeTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_TRAN_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); } if (pConfig->errorInterrupt == dmacHw_INTERRUPT_ENABLE) { dmacHw_ERROR_INT_ENABLE(pCblk->module, pCblk->channel); } else { dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); } if (pConfig->srcGatherWidth) { srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); if (! ((pConfig->srcGatherWidth % srcTrSize) && (pConfig->srcGatherJump % srcTrSize))) { dmacHw_REG_SGR_LO(pCblk->module, pCblk->channel) = ((pConfig->srcGatherWidth / srcTrSize) << 20) | (pConfig->srcGatherJump / srcTrSize); } else { return -1; } } if (pConfig->dstScatterWidth) { dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); if (! ((pConfig->dstScatterWidth % dstTrSize) && (pConfig->dstScatterJump % dstTrSize))) { dmacHw_REG_DSR_LO(pCblk->module, pCblk->channel) = ((pConfig->dstScatterWidth / dstTrSize) << 20) | (pConfig->dstScatterJump / dstTrSize); } else { return -1; } } return 0; }