123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- /*
- * @brief DMA controller ROM API declarations and functions
- *
- * @note
- * Copyright(C) NXP Semiconductors, 2014
- * All rights reserved.
- *
- * @par
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * LPC products. This software is supplied "AS IS" without any warranties of
- * any kind, and NXP Semiconductors and its licensor disclaim any and
- * all warranties, express or implied, including all implied warranties of
- * merchantability, fitness for a particular purpose and non-infringement of
- * intellectual property rights. NXP Semiconductors assumes no responsibility
- * or liability for the use of the software, conveys no license or rights under any
- * patent, copyright, mask work right, or any other intellectual property rights in
- * or to any products. NXP Semiconductors reserves the right to make changes
- * in the software without notification. NXP Semiconductors also makes no
- * representation or warranty that such application will be suitable for the
- * specified use without further testing or modification.
- *
- * @par
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, under NXP Semiconductors' and its
- * licensor's relevant copyrights in the software, without fee, provided that it
- * is used in conjunction with NXP Semiconductors microcontrollers. This
- * copyright, permission, and disclaimer notice must appear in all copies of
- * this code.
- */
- #include <stdint.h>
- #include <string.h>
- #include "hw_dmaaltd.h"
- #define DRVVERSION 0x0100
- typedef PRE_PACK struct POST_PACK {
- uint32_t xfercfg; /*!< DMA Configuration register */
- uint32_t src; /*!< DMA source address */
- uint32_t dest; /*!< DMA destination address */
- ROM_DMA_DESC_T *pNextLink; /*!< Pointer to next descriptor link in a chain, NULL to end */
- } ROM_DMA_PRVXFERDESC_T;
- /* Private data structure used for the DMA controller driver, holds the driver and
- peripheral context */
- typedef struct {
- void *pUserData; /*!< Pointer to user data used by driver instance, use NULL if not used */
- LPC_DMA_T *base; /*!< Base address of DMA controller to use */
- ROM_DMA_PRVXFERDESC_T *sramBase; /*!< SRAM descriptor table (all channels) */
- ROM_DMA_QUEUE_T *pQueueHead; /*!< Pointer to linked list of queue descriptors */
- } DMA_DATACONTEXT_T;
- static const uint8_t mskAlign[3] = {0x0, 0x1, 0x3};
- static const uint8_t widthBytes[3] = {0x1, 0x2, 0x4};
- #define _dma_ch_int_enable(p, ch) ((p)->DMACOMMON[0].INTENSET = (1 << (ch))) /* Enable interrupts for a channel */
- #define _dma_ch_int_disable(p, ch) ((p)->DMACOMMON[0].INTENCLR = (1 << (ch))) /* Disable interrupts for a channel */
- #define _dma_ch_enable(p, ch) ((p)->DMACOMMON[0].ENABLESET = (1 << (ch))) /* Enable a channel */
- #define _dma_ch_disable(p, ch) ((p)->DMACOMMON[0].ENABLECLR = (1 << (ch))) /* Disable a channel */
- static void _dma_abort_ch(LPC_DMA_T *pDMA, uint8_t dmaCh)
- {
- _dma_ch_disable(pDMA, dmaCh);
- /* Wait for channel to go unbusy */
- while ((pDMA->DMACOMMON[0].BUSY & (1 << dmaCh)) != 0) {}
- /* Abort */
- pDMA->DMACOMMON[0].ABORT = (1 << dmaCh);
- }
- static void _dma_start_desc_chain(DMA_DATACONTEXT_T *pDrv, uint8_t dmaCh, ROM_DMA_DESC_T *pDesc)
- {
- /* Switch to busy state */
- pDesc->status = ROM_DMA_DESC_STS_BUSY;
- /* Move transfer descriptor to DMA table */
- pDrv->sramBase[dmaCh].xfercfg = pDesc->xfercfg;
- pDrv->sramBase[dmaCh].src = pDesc->src;
- pDrv->sramBase[dmaCh].dest = pDesc->dest;
- pDrv->sramBase[dmaCh].pNextLink = (ROM_DMA_DESC_T *) pDesc->pNextLink;
- /* Start transfer */
- pDrv->base->DMACH[dmaCh].XFERCFG = pDesc->xfercfg;
- }
- // **********************************************************
- uint32_t dmaalt_get_mem_size(void)
- {
- return sizeof(DMA_DATACONTEXT_T);
- }
- ROM_DMA_HANDLE_T dmaalt_init(void *mem, const ROM_DMA_INIT_T *pInit)
- {
- DMA_DATACONTEXT_T *pDrv;
- /* Verify alignment is at least 4 bytes */
- if (((uint32_t) mem & 0x3) != 0) {
- return NULL;
- }
- pDrv = (DMA_DATACONTEXT_T *) mem;
- memset(pDrv, 0, sizeof(DMA_DATACONTEXT_T));
- /* Save pointer to user data */
- pDrv->pUserData = pInit->pUserData;
- pDrv->base = (LPC_DMA_T *) pInit->base;
- pDrv->sramBase = (ROM_DMA_PRVXFERDESC_T *) pInit->sramBase;
- /* Enable DMA controller */
- pDrv->base->CTRL = 1;
- pDrv->base->SRAMBASE = (uint32_t) pInit->sramBase;
- return (ROM_DMA_HANDLE_T) pDrv;
- }
- ErrorCode_t dmaalt_setup_channel(ROM_DMA_HANDLE_T pHandle, ROM_DMA_CHAN_CFG_T *pCfg, uint8_t dmaCh)
- {
- uint32_t cfg;
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- /* Parameter checks */
- if ((pCfg->burstSize > (uint32_t) ROM_DMA_BURSTPOWER_1024) || (pCfg->channelPrio > 7)) {
- return ERR_DMA_PARAM;
- }
- /* Enable DMA channel, clear any errors, enable interrupts */
- pDrv->base->DMACOMMON[0].ENABLECLR = (1 << dmaCh);
- pDrv->base->DMACOMMON[0].ERRINT = (1 << dmaCh);
- pDrv->base->DMACOMMON[0].INTA = (1 << dmaCh);
- pDrv->base->DMACOMMON[0].INTB = (1 << dmaCh);
- /* Basic DMA configuration */
- if (pCfg->periphReq) {
- cfg = DMA_CFG_PERIPHREQEN;
- }
- else {
- /* Hardware triggering */
- cfg = DMA_CFG_HWTRIGEN;
- cfg |= (pCfg->triggerPolHi << 4) | (pCfg->triggerLevel << 5) | (pCfg->triggerBurst << 6);
- }
- cfg |= (pCfg->burstSize << 8) | (pCfg->srcBurstWrap << 14) | (pCfg->dstBurstWrap << 15) | (pCfg->channelPrio << 16);
- pDrv->base->DMACH[dmaCh].CFG = cfg;
- return LPC_OK;
- }
- ErrorCode_t dmaalt_init_queue(ROM_DMA_HANDLE_T pHandle, uint8_t dmaCh, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- /* Check queue structure alignment */
- if (((uint32_t) pQueue & 0x3) != 0) {
- /* Not aligned at 4 bytes, error */
- return ERR_DMA_NOT_ALIGNMENT;
- }
- memset(pQueue, 0, sizeof(ROM_DMA_QUEUE_T));
- /* Save DMA channekl for this queue */
- pQueue->dmaCh = dmaCh;
- /* Append to existing queue */
- if (pDrv->pQueueHead) {
- pQueue->pQueueHead = (struct ROM_DMA_QUEUE *) pDrv->pQueueHead;
- }
- pDrv->pQueueHead = pQueue;
- pQueue->queueSt = (uint8_t) ROM_QUEUE_ST_IDLE;
- return LPC_OK;
- }
- void dmaalt_register_queue_callback(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue, uint32_t cbIndex, void *pCB)
- {
- switch (cbIndex) {
- case ROM_DMA_XFERCOMPLETE_CB:
- pQueue->dmaCompCB = (dmaTransferCompleteCB) pCB;
- break;
- case ROM_DMA_XFERDESCCOMPLETE_CB:
- pQueue->dmaDescCompCB = (dmaTransferDescCompleteCB) pCB;
- break;
- case ROM_DMA_XFERERROR_CB:
- pQueue->dmaErrorCB = (dmaTransferErrorCB) pCB;
- break;
- }
- }
- ErrorCode_t dmaalt_build_descriptor_chain(ROM_DMA_HANDLE_T pHandle,
- ROM_DMA_XFERDESC_CFG_T *pXferCfg,
- ROM_DMA_DESC_T *pDesc,
- ROM_DMA_DESC_T *pDescPrev)
- {
- uint32_t cfg, xfercnt, burstSize;
- uint8_t srcWrap, destWrap;
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- /* Parameter checks */
- if (pDesc == NULL) {
- return ERR_DMA_PARAM;
- }
- /* Passed descriptor must be correctly aligned */
- if (((uint32_t) pDesc & 0xF) != 0) {
- return ERR_DMA_NOT_ALIGNMENT;
- }
- /* Parameter checks */
- if (pXferCfg->width > (uint8_t) ROM_DMA_WIDTH_4) {
- return ERR_DMA_PARAM;
- }
- if ((pXferCfg->srcInc > (uint8_t) ROM_DMA_ADDRINC_4X) ||
- (pXferCfg->dstInc > (uint8_t) ROM_DMA_ADDRINC_4X)) {
- return ERR_DMA_PARAM;
- }
- if ((pXferCfg->xferCount < 1) || (pXferCfg->xferCount > 1024)) {
- return ERR_DMA_PARAM;
- }
- xfercnt = pXferCfg->xferCount - 1; /* Adjust for use with DMA */
- /* Check source and destination address alignment */
- if (((uint32_t) pXferCfg->src & mskAlign[pXferCfg->width]) != 0) {
- return ERR_DMA_NOT_ALIGNMENT;
- }
- if (((uint32_t) pXferCfg->dest & mskAlign[pXferCfg->width]) != 0) {
- return ERR_DMA_NOT_ALIGNMENT;
- }
- /* Get source and destination wrap states for the channel */
- cfg = pDrv->base->DMACH[pXferCfg->dmaCh].CFG;
- /* Get burst size in datum count, used for wrap end address, offset by
- (-1) for end address computation */
- burstSize = (1 << ((cfg >> 8) & 0xF)) - 1;
- /* Setup source transfer address */
- if (pXferCfg->srcInc == ROM_DMA_ADDRINC_0X) {
- /* No address increment - even with burst - so source address doesn't need
- to be adjusted */
- pDesc->src = (uint32_t) pXferCfg->src;
- }
- else {
- srcWrap = (uint8_t) ((cfg & (1 << 14)) != 0);
- if (srcWrap) {
- /* Wrap enabled - compute end address based on burst size and datum width */
- pDesc->src = (uint32_t) pXferCfg->src + ((uint32_t) widthBytes[pXferCfg->width] *
- burstSize * (1 << ((uint32_t) pXferCfg->srcInc - 1)));
- }
- else {
- /* No wrap - compute end address based on transfer size and datum width */
- pDesc->src = (uint32_t) pXferCfg->src + ((uint32_t) widthBytes[pXferCfg->width] *
- xfercnt * (1 << ((uint32_t) pXferCfg->srcInc - 1)));
- }
- }
- /* Setup destination transfer address */
- if (pXferCfg->dstInc == ROM_DMA_ADDRINC_0X) {
- /* No address increment - even with burst - so destination address doesn't need
- to be adjusted */
- pDesc->dest = (uint32_t) pXferCfg->dest;
- }
- else {
- destWrap = (uint8_t) ((cfg & (1 << 15)) != 0);
- if (destWrap) {
- /* Wrap enabled - compute end address based on burst size and datum width */
- pDesc->dest = (uint32_t) pXferCfg->dest + ((uint32_t) widthBytes[pXferCfg->width] *
- burstSize * (1 << ((uint32_t) pXferCfg->dstInc - 1)));
- }
- else {
- /* No wrap - compute end address based on transfer size and datum width */
- pDesc->dest = (uint32_t) pXferCfg->dest + ((uint32_t) widthBytes[pXferCfg->width] *
- xfercnt * (1 << ((uint32_t) pXferCfg->dstInc - 1)));
- }
- }
- /* Save pointer to user data context */
- pDesc->pUserData = pXferCfg->pUserData;
- /* Is the descriptor linked from a previous descriptor? */
- if (pDescPrev) {
- pDescPrev->pNextLink = (struct ROM_DMA_DESC *) pDesc;
- if (pXferCfg->enabCirc == 0) {
- pDescPrev->xfercfg &= ~(1 << 5);/* Disables INTB on previous descriptor link */
- pDescPrev->xfercfg |= (1 << 1); /* Reload on chained links */
- }
- }
- else {
- pDesc->pNextLink = NULL;
- }
- /* NULL out next chain descriptor pointers. The next chain descriptor is
- managed by the queue function, while the next link descriptor indicates the end
- of a chain. */
- pDesc->pNextChain = NULL;
- /* Current descriptor status is queueing. Status only applies to the first descriptor
- in a chain. */
- pDesc->status = ROM_DMA_DESC_STS_QUEUEING;
- pDesc->savedXferSize = pXferCfg->xferCount;
- /* Normalize parameters that are multibit to single bit */
- pXferCfg->swTrig = (pXferCfg->swTrig != 0);
- pXferCfg->clrTrig = (pXferCfg->clrTrig != 0);
- pXferCfg->fireDescCB = (pXferCfg->fireDescCB != 0);
- if (pXferCfg->enabCirc) {
- cfg = (1 << 1); /* Reload on chained links */
- }
- else {
- cfg = (1 << 5); /* INTB support for completion and next descriptor */
- }
- if (pXferCfg->stallDesc == 0) {
- cfg |= 0x1; /* CFGVALID */
- }
- /* Setup transfer configuration */
- cfg |= (pXferCfg->swTrig << 2) | (pXferCfg->clrTrig << 3) |
- (pXferCfg->fireDescCB << 4) | (pXferCfg->width << 8) | (pXferCfg->srcInc << 12) |
- (pXferCfg->dstInc << 14);
- cfg |= (xfercnt << 16);
- pDesc->xfercfg = cfg;
- return LPC_OK;
- }
- uint32_t dmaalt_get_transfer_count(ROM_DMA_HANDLE_T pHandle, ROM_DMA_DESC_T *pDesc)
- {
- uint32_t dataCount = 0;
- /* Count is only valid if descriptor is used */
- while (pDesc != NULL) {
- if (pDesc->status == ROM_DMA_DESC_STS_SPENT) {
- dataCount += (uint32_t) pDesc->savedXferSize;
- }
- pDesc = (ROM_DMA_DESC_T *) pDesc->pNextLink;
- }
- return dataCount;
- }
- void dmaalt_unstall_descriptor_chain(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- pDrv->base->DMACOMMON[0].SETVALID = (1 << pQueue->dmaCh);
- }
- void dmaalt_queue_descriptor(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue, ROM_DMA_DESC_T *pDescChainHead)
- {
- /* Add the link to the passed descriptor to the end of the queue */
- if (pQueue->pDescEnd != NULL) {
- pQueue->pDescEnd->pNextChain = (struct ROM_DMA_DESC *) pDescChainHead;
- }
- pQueue->pDescEnd = pDescChainHead;
- /* Next descriptor in queue */
- if (pQueue->pDescNext == NULL) {
- pQueue->pDescNext = pDescChainHead;
- }
- /* Descriptor is ready */
- pDescChainHead->status = ROM_DMA_DESC_STS_READY;
- }
- ROM_DMA_DESC_STS_T dmaalt_get_queue_pop_descriptor_status(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- if (pQueue->pDescPop) {
- return (ROM_DMA_DESC_STS_T) pQueue->pDescPop->status;
- }
- return ROM_DMA_DESC_STS_INVALID;
- }
- ROM_DMA_DESC_T *dmaalt_unqueue_descriptor(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- ROM_DMA_DESC_T *pDesc = NULL;
- /* Get current queue pop descriptor */
- if (pQueue->pDescPop) {
- /* Only expired (spent, error, or aborted descriptors can be unqueued. Use StopQueue to halt all
- descriptors queued. */
- if (pQueue->pDescPop->status >= ROM_DMA_DESC_STS_SPENT) {
- pDesc = (ROM_DMA_DESC_T *) pQueue->pDescPop;
- pQueue->pDescPop = (ROM_DMA_DESC_T *) pQueue->pDescPop->pNextChain;
- }
- }
- return pDesc;
- }
- ErrorCode_t dmaalt_start_queue(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- /* Is DMA already running? No need to restart */
- if ((pDrv->base->DMACOMMON[0].ACTIVE & (1 << pQueue->dmaCh)) != 0) {
- return LPC_OK;
- }
- /* Is queue empty? */
- if (pQueue->pDescNext == NULL) {
- return ERR_DMA_QUEUE_EMPTY;
- }
- /* Does the queue currently have a descriptor in it? */
- if (pQueue->pDescNext) {
- /* Is current descriptor chain ready? */
- if (pQueue->pDescNext->status == ROM_DMA_DESC_STS_READY) {
- /* Queue is now running */
- pQueue->queueSt = (uint8_t) ROM_QUEUE_ST_RUNNING;
- /* Enable this channel */
- _dma_ch_enable(pDrv->base, pQueue->dmaCh);
- _dma_ch_int_enable(pDrv->base, pQueue->dmaCh);
- _dma_start_desc_chain(pDrv, pQueue->dmaCh, pQueue->pDescNext);
- }
- }
- return LPC_OK;
- }
- ErrorCode_t dmaalt_stop_queue(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- ErrorCode_t error = LPC_OK;
- /* Disable interrupts for this channel */
- _dma_ch_int_disable(pDrv->base, pQueue->dmaCh);
- /* If queue is empty, no need to stop */
- if (pQueue->pDescNext == NULL) {
- return LPC_OK;
- }
- /* If current transfer is queued or ready, then switch it to aborted status
- and call completion callback if needed. */
- if (pQueue->pDescNext->status == ROM_DMA_DESC_STS_BUSY) {
- /* Abort transfer */
- _dma_abort_ch(pDrv->base, pQueue->dmaCh);
- }
- else if (!((pQueue->pDescNext->status == ROM_DMA_DESC_STS_QUEUEING) ||
- (pQueue->pDescNext->status == ROM_DMA_DESC_STS_READY))) {
- /* Other statuses are not legal for a queued descriptor */
- error = ERR_DMA_GENERAL;
- }
- /* Unlatch interrupts */
- pDrv->base->DMACOMMON[0].ERRINT = (1 << pQueue->dmaCh);
- pDrv->base->DMACOMMON[0].INTA = (1 << pQueue->dmaCh);
- pDrv->base->DMACOMMON[0].INTB = (1 << pQueue->dmaCh);
- /* Call completion callback to indicate abort state */
- pQueue->pDescNext->status = ROM_DMA_DESC_STS_ABORT;
- if (pQueue->dmaCompCB) {
- pQueue->dmaCompCB(pHandle, (struct ROM_DMA_QUEUE *) pQueue, pQueue->pDescNext);
- }
- /* Increment to next available descriptor since this one was aborted */
- pQueue->pDescNext = (ROM_DMA_DESC_T *) pQueue->pDescNext->pNextChain;
- /* Queue is now idle */
- pQueue->queueSt = (uint8_t) ROM_QUEUE_ST_IDLE;
- return error;
- }
- void dmaalt_flush_queue(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- /* Disable interrupts for this channel */
- _dma_ch_int_disable(pDrv->base, pQueue->dmaCh);
- /* Abort transfer */
- _dma_abort_ch(pDrv->base, pQueue->dmaCh);
- /* Unlatch interrupts */
- pDrv->base->DMACOMMON[0].ERRINT = (1 << pQueue->dmaCh);
- pDrv->base->DMACOMMON[0].INTA = (1 << pQueue->dmaCh);
- pDrv->base->DMACOMMON[0].INTB = (1 << pQueue->dmaCh);
- /* No callbacks on abort, all descriptors flushed */
- pQueue->pDescEnd = pQueue->pDescNext = pQueue->pDescPop = NULL;
- /* Queue is now idle */
- pQueue->queueSt = (uint8_t) ROM_QUEUE_ST_IDLE;
- }
- uint8_t dmaalt_get_queue_state(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- return pQueue->queueSt;
- }
- void dmaalt_force_trigger(ROM_DMA_HANDLE_T pHandle, ROM_DMA_QUEUE_T *pQueue)
- {
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- pDrv->base->DMACOMMON[0].SETTRIG = (1 << pQueue->dmaCh);
- }
- // Otime = "optimize for speed of code execution"
- // ...add this pragma 1 line above the interrupt service routine function.
- void dmaalt_handler(ROM_DMA_HANDLE_T pHandle)
- {
- uint32_t err, inta, intb, all, dmaChMask;
- ROM_DMA_QUEUE_T *pQueue;
- ROM_DMA_DESC_T *pDesc;
- DMA_DATACONTEXT_T *pDrv = (DMA_DATACONTEXT_T *) pHandle;
- uint8_t nextChain = 0;
- /* DMA interrupt fires on one of three possible events:
- 1) ERROR : A DMA error has occured
- Calls error callback and stops queue
- 2) INTA on descriptor completion
- Calls descriptor completed callback
- 3) INTB on descriptor chain completion
- Calls descriptor chain completion callback */
- /* Loop through all enabled DMA channels */
- pQueue = pDrv->pQueueHead;
- err = pDrv->base->DMACOMMON[0].ERRINT;
- inta = pDrv->base->DMACOMMON[0].INTA;
- intb = pDrv->base->DMACOMMON[0].INTB;
- all = err | inta | intb;
- while (pQueue) {
- dmaChMask = (1 << pQueue->dmaCh);
- if ((all & dmaChMask) != 0) {
- /* DMA interrupt fire for this channel */
- if ((err & dmaChMask) != 0) {
- /* Abort current descriptor */
- _dma_ch_int_disable(pDrv->base, pQueue->dmaCh);
- _dma_abort_ch(pDrv->base, pQueue->dmaCh);
- /* Error interrupt, clear */
- pDrv->base->DMACOMMON[0].ERRINT = dmaChMask;
- pDrv->base->DMACOMMON[0].INTA = dmaChMask;
- pDrv->base->DMACOMMON[0].INTB = dmaChMask;
- /* Update status to error */
- pQueue->pDescNext->status = ROM_DMA_DESC_STS_ERROR;
- pQueue->queueSt = (uint8_t) ROM_QUEUE_ST_ERROR;
- /* Call error callback for channel */
- if (pQueue->dmaErrorCB) {
- pQueue->dmaErrorCB(pHandle, (struct ROM_DMA_QUEUE *) pQueue, pQueue->pDescNext);
- }
- nextChain = 1;
- }
- /* Interrupt A is used for user defined interrupt tied to a descriptor */
- if ((inta & dmaChMask) != 0) {
- pDrv->base->DMACOMMON[0].INTA = dmaChMask;
- /* Call transfer descriptor completion for channel */
- if (pQueue->dmaDescCompCB) {
- pQueue->dmaDescCompCB(pHandle, (struct ROM_DMA_QUEUE *) pQueue, pQueue->pDescNext);
- }
- }
- /* Interrupt B is used for user transfer descriptor chain completion */
- if ((intb & dmaChMask) != 0) {
- pDrv->base->DMACOMMON[0].INTB = dmaChMask;
- /* Update status to spent/complete */
- pQueue->pDescNext->status = ROM_DMA_DESC_STS_SPENT;
- /* Start the next descriptor chain? */
- pDesc = (ROM_DMA_DESC_T *) pQueue->pDescNext->pNextChain;
- if ((pDesc) && (pDesc->status == ROM_DMA_DESC_STS_READY)) {
- /* A queued descriptor is available and ready, so start it */
- _dma_start_desc_chain(pDrv, pQueue->dmaCh, pDesc);
- }
- /* Call transfer descriptor completion for channel */
- if (pQueue->dmaCompCB) {
- pQueue->dmaCompCB(pHandle, (struct ROM_DMA_QUEUE *) pQueue, pQueue->pDescNext);
- }
- nextChain = 1;
- }
- if (nextChain) {
- /* Need to save in pop queue? */
- if (pQueue->pDescPop == NULL) {
- pQueue->pDescPop = pQueue->pDescNext;
- }
- /* Advance to next queued descriptor */
- pQueue->pDescNext = (ROM_DMA_DESC_T *) pQueue->pDescNext->pNextChain;
- if (pQueue->pDescNext == NULL) {
- /* No more descriptors */
- pQueue->pDescEnd = NULL;
- }
- }
- all &= ~dmaChMask;
- }
- /* Next queue */
- pQueue = (ROM_DMA_QUEUE_T *) pQueue->pQueueHead;
- }
- if (all) {
- /* Unexpected interrupts, clear and disable */
- pDrv->base->DMACOMMON[0].ENABLECLR = all;
- pDrv->base->DMACOMMON[0].INTENCLR = all;
- pDrv->base->DMACOMMON[0].ERRINT = all;
- pDrv->base->DMACOMMON[0].INTA = all;
- pDrv->base->DMACOMMON[0].INTB = all;
- }
- }
- uint32_t dmaalt_get_driver_version(void)
- {
- return DRVVERSION;
- }
- // *********************************************************
|