+++ /dev/null
-/* ----------------------------------------------------------------------------\r
- * SAM Software Package License \r
- * ----------------------------------------------------------------------------\r
- * Copyright (c) 2014, Atmel Corporation\r
- *\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the disclaimer below.\r
- *\r
- * Atmel's name may not be used to endorse or promote products derived from\r
- * this software without specific prior written permission.\r
- *\r
- * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
- * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * ----------------------------------------------------------------------------\r
- */\r
-\r
-/** \addtogroup xdmad_module \r
- *\r
- * \section Xdma xDma Configuration Usage\r
- *\r
- * To configure a XDMA channel, the user has to follow these few steps :\r
- * <ul>\r
- * <li> Initialize a XDMA driver instance by XDMAD_Initialize().</li>\r
- * <li> choose an available (disabled) channel using XDMAD_AllocateChannel().</li>\r
- * <li> After the XDMAC selected channel has been programmed, XDMAD_PrepareChannel() is to enable \r
- * clock and dma peripheral of the DMA, and set Configuration register to set up the transfer type \r
- * (memory or non-memory peripheral for source and destination) and flow control device.</li>\r
- * <li> Invoke XDMAD_StartTransfer() to start DMA transfer or XDMAD_StopTransfer() to force stop DMA transfer.</li>\r
- * <li> Once the buffer of data is transferred, XDMAD_IsTransferDone() checks if DMA transfer is finished.</li>\r
- * <li> XDMAD_Handler() handles XDMA interrupt, and invoking XDMAD_SetCallback() if provided.</li>\r
- * </ul>\r
- *\r
- * Related files:\n\r
- * \ref xdmad.h\n\r
- * \ref xdmad.c.\n\r
- */\r
-\r
-/** \file */\r
-\r
-/** \addtogroup dmad_functions\r
- @{*/\r
-\r
-/*----------------------------------------------------------------------------\r
- * Includes\r
- *----------------------------------------------------------------------------*/\r
-\r
-#include "board.h"\r
-#include <assert.h>\r
-static uint8_t xDmad_Initialized = 0;\r
-\r
-/*----------------------------------------------------------------------------\r
- * Local functions\r
- *----------------------------------------------------------------------------*/\r
-/**\r
- * \brief Try to allocate a DMA channel for on given controller.\r
- * \param pDmad Pointer to DMA driver instance. \r
- * \param bSrcID Source peripheral ID, 0xFF for memory.\r
- * \param bDstID Destination peripheral ID, 0xFF for memory.\r
- * \return Channel number if allocation sucessful, return\r
- * DMAD_ALLOC_FAILED if allocation failed.\r
- */\r
-static uint32_t XDMAD_AllocateXdmacChannel( sXdmad *pXdmad,\r
- uint8_t bSrcID,\r
- uint8_t bDstID)\r
-{\r
- uint32_t i;\r
- /* Can't support peripheral to peripheral */\r
- if ((( bSrcID != XDMAD_TRANSFER_MEMORY ) && ( bDstID != XDMAD_TRANSFER_MEMORY )))\r
- {\r
- return XDMAD_ALLOC_FAILED;\r
- }\r
- /* dma transfer from peripheral to memory */\r
- if ( bDstID == XDMAD_TRANSFER_MEMORY)\r
- {\r
- if( (!XDMAIF_IsValidatedPeripherOnDma(bSrcID)) )\r
- {\r
- return XDMAD_ALLOC_FAILED;\r
- }\r
- }\r
- /* dma transfer from memory to peripheral */\r
- if ( bSrcID == XDMAD_TRANSFER_MEMORY )\r
- {\r
- if( (!XDMAIF_IsValidatedPeripherOnDma(bDstID)) )\r
- {\r
- return XDMAD_ALLOC_FAILED;\r
- }\r
- }\r
-\r
- for (i = 0; i < pXdmad->numChannels; i ++)\r
- {\r
- if (( pXdmad->XdmaChannels[i].state == XDMAD_STATE_FREE ) || ( pXdmad->XdmaChannels[i].state == XDMAD_STATE_DONE ))\r
- {\r
- /* Allocate the channel */\r
- pXdmad->XdmaChannels[i].state = XDMAD_STATE_ALLOCATED;\r
- /* Get general informations */\r
- pXdmad->XdmaChannels[i].bSrcPeriphID = bSrcID;\r
- pXdmad->XdmaChannels[i].bDstPeriphID = bDstID;\r
- pXdmad->XdmaChannels[i].bSrcTxIfID =\r
- XDMAIF_Get_ChannelNumber(bSrcID, 0);\r
- pXdmad->XdmaChannels[i].bSrcRxIfID =\r
- XDMAIF_Get_ChannelNumber(bSrcID, 1);\r
- pXdmad->XdmaChannels[i].bDstTxIfID =\r
- XDMAIF_Get_ChannelNumber(bDstID, 0);\r
- pXdmad->XdmaChannels[i].bDstRxIfID =\r
- XDMAIF_Get_ChannelNumber(bDstID, 1);\r
- return ((i) & 0xFF);\r
- }\r
- }\r
- return XDMAD_ALLOC_FAILED;\r
-}\r
-\r
-/*----------------------------------------------------------------------------\r
- * Exported functions\r
- *----------------------------------------------------------------------------*/\r
-\r
-/**\r
- * \brief Initialize xDMA driver instance.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param bPollingMode Polling DMA transfer:\r
- * 1. Via XDMAD_IsTransferDone(); or\r
- * 2. Via XDMAD_Handler().\r
- */\r
-void XDMAD_Initialize( sXdmad *pXdmad, uint8_t bPollingMode )\r
-{\r
- uint32_t j;\r
-\r
- assert( pXdmad != NULL ) ;\r
- if (xDmad_Initialized) return;\r
- pXdmad->pXdmacs = XDMAC;\r
- pXdmad->pollingMode = bPollingMode;\r
- pXdmad->numControllers = XDMAC_CONTROLLER_NUM;\r
- pXdmad->numChannels = (XDMAC_GTYPE_NB_CH( XDMAC_GetType(XDMAC) ) + 1);\r
-\r
- for (j = 0; j < pXdmad->numChannels; j ++)\r
- {\r
- pXdmad->XdmaChannels[j].fCallback = 0;\r
- pXdmad->XdmaChannels[j].pArg = 0;\r
- pXdmad->XdmaChannels[j].bIrqOwner = 0;\r
- pXdmad->XdmaChannels[j].bSrcPeriphID = 0;\r
- pXdmad->XdmaChannels[j].bDstPeriphID = 0;\r
- pXdmad->XdmaChannels[j].bSrcTxIfID = 0;\r
- pXdmad->XdmaChannels[j].bSrcRxIfID = 0;\r
- pXdmad->XdmaChannels[j].bDstTxIfID = 0;\r
- pXdmad->XdmaChannels[j].bDstRxIfID = 0;\r
- pXdmad->XdmaChannels[j].state = XDMAD_STATE_FREE;\r
- }\r
- xDmad_Initialized = 1;\r
-}\r
-\r
-\r
-/**\r
- * \brief Allocate a XDMA channel for upper layer.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param bSrcID Source peripheral ID, 0xFF for memory.\r
- * \param bDstID Destination peripheral ID, 0xFF for memory.\r
- * \return Channel number if allocation sucessful, return\r
- * XDMAD_ALLOC_FAILED if allocation failed.\r
- */\r
-uint32_t XDMAD_AllocateChannel( sXdmad *pXdmad,\r
- uint8_t bSrcID,\r
- uint8_t bDstID)\r
-{ \r
- uint32_t dwChannel = XDMAD_ALLOC_FAILED;\r
-\r
- dwChannel = XDMAD_AllocateXdmacChannel( pXdmad, bSrcID, bDstID );\r
-\r
- return dwChannel;\r
-}\r
-\r
-/**\r
- * \brief Free the specified xDMA channel.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- */\r
-eXdmadRC XDMAD_FreeChannel( sXdmad *pXdmad, \r
- uint32_t dwChannel )\r
-{\r
-\r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
-\r
- assert( pXdmad != NULL ) ;\r
- switch ( pXdmad->XdmaChannels[iChannel].state )\r
- {\r
- case XDMAD_STATE_START: \r
- case XDMAD_STATE_ALLOCATED: \r
- return XDMAD_BUSY;\r
- case XDMAD_STATE_DONE:\r
- pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_FREE;\r
- break;\r
- }\r
- return XDMAD_OK;\r
-}\r
-\r
-\r
-/**\r
- * \brief Set the callback function for xDMA channel transfer.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- * \param fCallback Pointer to callback function.\r
- * \param pArg Pointer to optional argument for callback.\r
- */\r
-eXdmadRC XDMAD_SetCallback( sXdmad *pXdmad, \r
- uint32_t dwChannel,\r
- XdmadTransferCallback fCallback, \r
- void* pArg )\r
-{\r
-\r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
- assert( pXdmad != NULL ) ;\r
- if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE )\r
- return XDMAD_ERROR;\r
- else if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START )\r
- return XDMAD_BUSY;\r
-\r
- pXdmad->XdmaChannels[iChannel].fCallback = fCallback;\r
- pXdmad->XdmaChannels[iChannel].pArg = pArg;\r
-\r
- return XDMAD_OK;\r
-}\r
-\r
-\r
-/**\r
- * \brief Enable clock of the xDMA peripheral, Enable the dma peripheral,\r
- * configure configuration register for xDMA transfer.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- * \param dwCfg Configuration value.\r
- */\r
-eXdmadRC XDMAD_PrepareChannel( sXdmad *pXdmad, uint32_t dwChannel)\r
-{\r
-\r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
-\r
-\r
- assert( pXdmad != NULL ) ;\r
- Xdmac *pXdmac = pXdmad->pXdmacs;\r
-\r
- if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE )\r
- return XDMAD_ERROR;\r
- else if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START )\r
- return XDMAD_BUSY;\r
- /* Clear dummy status */\r
- XDMAC_GetGlobalChStatus( pXdmac );\r
- XDMAC_GetGIsr (pXdmac);\r
-\r
- /* Enable clock of the DMA peripheral */\r
- if (!PMC_IsPeriphEnabled( ID_XDMAC ))\r
- {\r
- PMC_EnablePeripheral( ID_XDMAC );\r
- }\r
-\r
- /* Clear dummy status */\r
- XDMAC_GetChannelIsr( pXdmac,iChannel );\r
- /* Disables XDMAC interrupt for the given channel. */\r
- XDMAC_DisableGIt (pXdmac, (uint32_t)-1);\r
- XDMAC_DisableChannelIt (pXdmac, iChannel, (uint32_t)-1);\r
- /* Disable the given dma channel. */\r
- XDMAC_DisableChannel( pXdmac, iChannel );\r
- XDMAC_SetSourceAddr(pXdmac, iChannel, 0);\r
- XDMAC_SetDestinationAddr(pXdmac, iChannel, 0);\r
- XDMAC_SetBlockControl(pXdmac, iChannel, 0);\r
- XDMAC_SetChannelConfig( pXdmac, iChannel, 0x20);\r
- XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);\r
- XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);\r
- return XDMAD_OK;\r
-}\r
-\r
-/**\r
- * \brief xDMA interrupt handler\r
- * \param pxDmad Pointer to DMA driver instance.\r
- */\r
-void XDMAD_Handler( sXdmad *pDmad)\r
-{\r
- Xdmac *pXdmac;\r
- sXdmadChannel *pCh;\r
- uint32_t xdmaChannelIntStatus, xdmaGlobaIntStatus,xdmaGlobalChStatus;\r
- uint8_t bExec = 0;\r
- uint8_t _iChannel;\r
- assert( pDmad != NULL ) ;\r
-\r
-\r
- pXdmac = pDmad->pXdmacs;\r
- xdmaGlobaIntStatus = XDMAC_GetGIsr(pXdmac);\r
- if ((xdmaGlobaIntStatus & 0xFFFFFF) != 0)\r
- {\r
- xdmaGlobalChStatus = XDMAC_GetGlobalChStatus(pXdmac);\r
- for (_iChannel = 0; _iChannel < pDmad->numChannels; _iChannel ++) \r
- {\r
- if (!(xdmaGlobaIntStatus & (1<<_iChannel))) continue;\r
- pCh = &pDmad->XdmaChannels[_iChannel];\r
- if ( pCh->state == XDMAD_STATE_FREE) return ;\r
- if ((xdmaGlobalChStatus & ( XDMAC_GS_ST0 << _iChannel)) == 0) \r
- {\r
- bExec = 0;\r
- xdmaChannelIntStatus = XDMAC_GetChannelIsr( pXdmac, _iChannel);\r
- if (xdmaChannelIntStatus & XDMAC_CIS_BIS) { \r
- if((XDMAC_GetChannelItMask(pXdmac, _iChannel) & XDMAC_CIM_LIM) == 0 ) {\r
- pCh->state = XDMAD_STATE_DONE ;\r
- bExec = 1;\r
- }\r
- //printf("XDMAC_CIS_BIS\n\r");\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_FIS) {\r
- // printf("XDMAC_CIS_FIS\n\r");\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_RBEIS) {\r
- //printf("XDMAC_CIS_RBEIS\n\r");\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_WBEIS) {\r
- // printf("XDMAC_CIS_WBEIS\n\r");\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_ROIS) {\r
- // printf("XDMAC_CIS_ROIS\n\r");\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_LIS) {\r
- //printf("XDMAC_CIS_LIS\n\r");\r
-\r
- pCh->state = XDMAD_STATE_DONE ;\r
- bExec = 1;\r
- }\r
- if (xdmaChannelIntStatus & XDMAC_CIS_DIS ) \r
- {\r
- pCh->state = XDMAD_STATE_DONE ;\r
- bExec = 1;\r
- }\r
- }\r
- /* Execute callback */\r
- if (bExec && pCh->fCallback) {\r
- //XDMAC_DisableGIt( pXdmac,1 << _iChannel);\r
- pCh->fCallback(_iChannel, pCh->pArg);\r
- }\r
- }\r
- } // if condtion\r
-}\r
-\r
-/**\r
- * \brief Check if DMA transfer is finished.\r
- * In polling mode XDMAD_Handler() is polled.\r
- * \param pDmad Pointer to DMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- */\r
-eXdmadRC XDMAD_IsTransferDone( sXdmad *pXdmad, uint32_t dwChannel )\r
-{ \r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
- uint8_t state;\r
- state = pXdmad->XdmaChannels[iChannel].state;\r
- assert( pXdmad != NULL ) ;\r
- if ( state == XDMAD_STATE_ALLOCATED ) return XDMAD_OK;\r
- if ( state == XDMAD_STATE_FREE )\r
- return XDMAD_ERROR;\r
- else if ( state != XDMAD_STATE_DONE )\r
- {\r
- if(pXdmad->pollingMode) XDMAD_Handler( pXdmad);\r
- return XDMAD_BUSY;\r
- }\r
- return XDMAD_OK;\r
-}\r
-\r
-\r
-/**\r
- * \brief Configure DMA for a single transfer.\r
- * \param pXdmad Pointer to xDMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- */\r
-eXdmadRC XDMAD_ConfigureTransfer( sXdmad *pXdmad,\r
- uint32_t dwChannel,\r
- sXdmadCfg *pXdmaParam,\r
- uint32_t dwXdmaDescCfg,\r
- uint32_t dwXdmaDescAddr)\r
-{\r
-\r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
- Xdmac *pXdmac = pXdmad->pXdmacs;\r
- XDMAC_GetGIsr(pXdmac);\r
- XDMAC_GetChannelIsr( pXdmac, iChannel);\r
- if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE )\r
- return XDMAD_ERROR;\r
- if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START )\r
- return XDMAD_BUSY;\r
- /* Linked List is enabled */\r
- if ((dwXdmaDescCfg & XDMAC_CNDC_NDE) == XDMAC_CNDC_NDE_DSCR_FETCH_EN)\r
- {\r
- if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV0) {\r
- XDMAC_SetChannelConfig( pXdmac, iChannel, pXdmaParam->mbr_cfg );\r
- XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);\r
- XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);\r
- }\r
- if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV1) {\r
- XDMAC_SetChannelConfig( pXdmac, iChannel, pXdmaParam->mbr_cfg );\r
- }\r
- XDMAC_SetDescriptorAddr(pXdmac, iChannel, dwXdmaDescAddr, 0);\r
- XDMAC_SetDescriptorControl(pXdmac, iChannel, dwXdmaDescCfg);\r
- XDMAC_DisableChannelIt (pXdmac, iChannel, (uint32_t)-1);\r
- XDMAC_EnableChannelIt (pXdmac,iChannel, XDMAC_CIE_LIE );\r
- }\r
- /* LLI is disabled. */\r
- else\r
- {\r
- XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);\r
- XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);\r
- XDMAC_SetMicroblockControl(pXdmac, iChannel, pXdmaParam->mbr_ubc);\r
- XDMAC_SetBlockControl(pXdmac, iChannel, pXdmaParam->mbr_bc);\r
- XDMAC_SetDataStride_MemPattern(pXdmac, iChannel, pXdmaParam->mbr_ds);\r
- XDMAC_SetSourceMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_sus);\r
- XDMAC_SetDestinationMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_dus);\r
- XDMAC_SetChannelConfig( pXdmac, iChannel, pXdmaParam->mbr_cfg );\r
- XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);\r
- XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);\r
- XDMAC_EnableChannelIt (pXdmac,\r
- iChannel,\r
- XDMAC_CIE_BIE |\r
- XDMAC_CIE_DIE |\r
- XDMAC_CIE_FIE |\r
- XDMAC_CIE_RBIE |\r
- XDMAC_CIE_WBIE |\r
- XDMAC_CIE_ROIE);\r
- }\r
- return XDMAD_OK;\r
-}\r
-\r
-/**\r
- * \brief Start xDMA transfer.\r
- * \param pXdmad Pointer to XDMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- */\r
-eXdmadRC XDMAD_StartTransfer( sXdmad *pXdmad, uint32_t dwChannel )\r
-{\r
-\r
- uint8_t iChannel = (dwChannel) & 0xFF;\r
- Xdmac *pXdmac = pXdmad->pXdmacs;\r
- if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE )\r
- {\r
- printf("-E- XDMAD_STATE_FREE \n\r");\r
- return XDMAD_ERROR;\r
- }\r
- else if ( pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START )\r
- {\r
- printf("-E- XDMAD_STATE_START \n\r");\r
- return XDMAD_BUSY;\r
- }\r
- /* Change state to transferring */\r
- pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_START; \r
- XDMAC_EnableChannel(pXdmac, iChannel);\r
- if ( pXdmad->pollingMode == 0 )\r
- {\r
- XDMAC_EnableGIt( pXdmac,1 << iChannel);\r
- }\r
- return XDMAD_OK;\r
-}\r
-\r
-\r
-/**\r
- * \brief Stop DMA transfer.\r
- * \param pDmad Pointer to DMA driver instance.\r
- * \param dwChannel ControllerNumber << 8 | ChannelNumber.\r
- */\r
-eXdmadRC XDMAD_StopTransfer( sXdmad *pXdmad, uint32_t dwChannel )\r
-{ \r
- uint8_t _iChannel = (dwChannel) & 0xFF;\r
- Xdmac *pXdmac = pXdmad->pXdmacs;\r
-\r
- pXdmad->XdmaChannels[_iChannel].state = XDMAD_STATE_ALLOCATED;\r
- /* Disable channel */\r
- XDMAC_DisableChannel(pXdmac, _iChannel);\r
- /* Disable interrupts */\r
- XDMAC_DisableChannelIt(pXdmac, _iChannel, (uint32_t)-1);\r
- /* Clear pending status */\r
- XDMAC_GetChannelIsr( pXdmac, _iChannel);\r
- XDMAC_GetGlobalChStatus(pXdmac);\r
-\r
- return XDMAD_OK;\r
-}\r
-\r
-/**@}*/\r
-\r