SAMV71 Xplained Ultra Software Package 1.3

afe_dma.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /** \addtogroup afe_dma_module Working with AFE (DMA support)
00031  *  \ingroup peripherals_module
00032  * The afec driver provides the interface to configure and use the afecC 
00033  * peripheral with DMA support.\n
00034  *
00035  * For more accurate information, please look at the AFEC section of the
00036  * Datasheet.
00037  *
00038  * Related files :\n
00039  * \ref afe_dma.c\n
00040  * \ref afe_dma.h\n
00041  */
00042 /*@{*/
00043 /*@}*/
00044 /**
00045  * \file
00046  *
00047  *
00048  */
00049 /*----------------------------------------------------------------------------
00050  *        Headers
00051  *----------------------------------------------------------------------------*/
00052 
00053 #include "chip.h"
00054 
00055 #include <stdint.h>
00056 #include <assert.h>
00057 
00058 /*  DMA driver instance */
00059 static uint32_t afeDmaRxChannel;
00060 
00061 /*----------------------------------------------------------------------------
00062  *        Local functions
00063  *----------------------------------------------------------------------------*/
00064 
00065 /**
00066  * \brief AFE xDMA Rx callback
00067  * Invoked on AFE DMA reception done.
00068  * \param channel DMA channel.
00069  * \param pArg Pointer to callback argument - Pointer to AfeDma instance.
00070  */ 
00071 static void Afe_Rx_Cb(uint32_t channel, AfeDma* pArg)
00072 {
00073     AfeCmd *pAfedCmd = pArg->pCurrentCommand;
00074     if (channel != afeDmaRxChannel)
00075         return;
00076 
00077     /* Configure and enable interrupt on RC compare */
00078     NVIC_ClearPendingIRQ(XDMAC_IRQn);
00079     NVIC_DisableIRQ(XDMAC_IRQn);
00080 
00081     /* Release the DMA channels */
00082     XDMAD_FreeChannel(pArg->pXdmad, afeDmaRxChannel);
00083     SCB_CleanInvalidateDCache();
00084     /* Release the dataflash semaphore */
00085     pArg->semaphore++;
00086 
00087     /* Invoke the callback associated with the current command */
00088     if (pAfedCmd && pAfedCmd->callback) {
00089         pAfedCmd->callback(0, pAfedCmd->pArgument);
00090     }
00091 }
00092 
00093 /**
00094  * \brief Configure the DMA Channels: 0 RX.
00095  * Channels are disabled after configure.
00096  * \param pXdmad Pointer to a AfeDma instance
00097  * \returns 0 if the dma channel configuration successfully; otherwise returns
00098  * AFE_ERROR_XXX.
00099  */
00100 static uint8_t _AfeConfigureDmaChannels( AfeDma* pAfed )
00101 {
00102 
00103     /* Driver initialize */
00104     XDMAD_Initialize( pAfed->pXdmad, 0 );
00105 
00106     XDMAD_FreeChannel( pAfed->pXdmad, afeDmaRxChannel);
00107 
00108     /* Allocate a DMA channel for AFE0/1 RX. */
00109     afeDmaRxChannel = 
00110         XDMAD_AllocateChannel( pAfed->pXdmad, pAfed->afeId, XDMAD_TRANSFER_MEMORY);
00111     if ( afeDmaRxChannel == XDMAD_ALLOC_FAILED ) {
00112         return AFE_ERROR;
00113     }
00114 
00115     /* Setup callbacks for AFE0/1 RX */
00116     XDMAD_SetCallback(pAfed->pXdmad, afeDmaRxChannel, 
00117             (XdmadTransferCallback)Afe_Rx_Cb, pAfed);
00118     if (XDMAD_PrepareChannel( pAfed->pXdmad, afeDmaRxChannel ))
00119         return AFE_ERROR;
00120     return AFE_OK;
00121 }
00122 
00123 /**
00124  * \brief Configure the DMA source and destination with Linker List mode.
00125  * \param pXdmad Pointer to a AfeDma instance
00126  * \param pCommand Pointer to AfeCmd instance
00127  * \param AfeCmd Pointer to command
00128  */
00129 
00130 static uint8_t _Afe_configureLinkList(Afec *pAfeHw, void *pXdmad, AfeCmd *pCommand)
00131 {
00132     uint32_t xdmaCndc, xdmaInt;
00133     sXdmadCfg xdmadRxCfg;
00134     uint32_t afeId;
00135     if ((unsigned int)pAfeHw == (unsigned int)AFEC0 ) afeId = ID_AFEC0;
00136     if ((unsigned int)pAfeHw == (unsigned int)AFEC1 ) afeId = ID_AFEC1;
00137     /* Setup RX Link List */
00138     xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
00139                          XDMA_UBC_NDE_FETCH_DIS|
00140                          XDMA_UBC_NDEN_UPDATED |
00141                          pCommand->RxSize;
00142 
00143     xdmadRxCfg.mbr_da = (uint32_t)pCommand->pRxBuff;
00144     xdmadRxCfg.mbr_sa = (uint32_t)&(pAfeHw->AFEC_LCDR);
00145     xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00146                          XDMAC_CC_MBSIZE_SINGLE |
00147                          XDMAC_CC_DSYNC_PER2MEM |
00148                          XDMAC_CC_CSIZE_CHK_1 |
00149                          XDMAC_CC_DWIDTH_WORD|
00150                          XDMAC_CC_SIF_AHB_IF1 |
00151                          XDMAC_CC_DIF_AHB_IF0 |
00152                          XDMAC_CC_SAM_FIXED_AM |
00153                          XDMAC_CC_DAM_INCREMENTED_AM |
00154                          XDMAC_CC_PERID(
00155                             XDMAIF_Get_ChannelNumber(  afeId, XDMAD_TRANSFER_RX ));
00156 
00157     xdmadRxCfg.mbr_bc = 0;
00158     xdmadRxCfg.mbr_sus = 0;
00159     xdmadRxCfg.mbr_dus =0;
00160 
00161     xdmaInt =  (XDMAC_CIE_BIE   |
00162                 XDMAC_CIE_DIE   |
00163                 XDMAC_CIE_FIE   |
00164                 XDMAC_CIE_RBIE  |
00165                 XDMAC_CIE_WBIE  |
00166                 XDMAC_CIE_ROIE);
00167     xdmaCndc = 0;
00168     if (XDMAD_ConfigureTransfer( pXdmad, afeDmaRxChannel, 
00169             &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
00170         return AFE_ERROR;
00171     SCB_CleanInvalidateDCache();
00172     return AFE_OK;
00173 }
00174 
00175 /*----------------------------------------------------------------------------
00176  *        Exported functions
00177  *----------------------------------------------------------------------------*/
00178 
00179 
00180 /**
00181  * \brief Initializes the AfeDma structure and the corresponding AFE & DMA .
00182  * hardware select value.
00183  * The driver will uses DMA channel 0 for RX .
00184  * The DMA channels are freed automatically when no DMA command processing.
00185  *
00186  * \param pAfed  Pointer to a AfeDma instance.
00187  * \param pAfeHw Associated Afe peripheral.
00188  * \param AfeId  Afe peripheral identifier.
00189  * \param pDmad  Pointer to a Dmad instance. 
00190  */
00191 uint32_t Afe_ConfigureDma( AfeDma *pAfed ,
00192         Afec *pAfeHw ,
00193         uint8_t AfeId,
00194         sXdmad *pXdmad )
00195 {
00196     /* Initialize the Afe structure */
00197     pAfed->pAfeHw = pAfeHw;
00198     pAfed->afeId  = AfeId;
00199     pAfed->semaphore = 1;
00200     pAfed->pCurrentCommand = 0;
00201     pAfed->pXdmad = pXdmad;
00202     return 0;
00203 }
00204 
00205 /**
00206  * \brief Starts a AFE transfer. This is a non blocking function. It will
00207  *  return as soon as the transfer is started.
00208  *
00209  * \param pAfed  Pointer to a AfeDma instance.
00210  * \param pCommand Pointer to the Afe command to execute.
00211  * \returns 0 if the transfer has been started successfully; otherwise returns
00212  * AFE_ERROR_LOCK is the driver is in use, or AFE_ERROR if the command is not
00213  * valid.
00214  */
00215 uint32_t Afe_SendData( AfeDma *pAfed, AfeCmd *pCommand)
00216 {
00217     Afec *pAfeHw = pAfed->pAfeHw;
00218 
00219     /* Try to get the dataflash semaphore */
00220     if (pAfed->semaphore == 0) {
00221 
00222         return AFE_ERROR_LOCK;
00223     }
00224     pAfed->semaphore--;
00225 
00226     // Initialize the callback
00227     pAfed->pCurrentCommand = pCommand;
00228 
00229     /* Initialize DMA controller using channel 0 for RX. */
00230     if (_AfeConfigureDmaChannels(pAfed) )
00231         return AFE_ERROR_LOCK;
00232 
00233     /* Configure and enable interrupt on RC compare */
00234     NVIC_ClearPendingIRQ(XDMAC_IRQn);
00235     NVIC_SetPriority( XDMAC_IRQn ,1);
00236     NVIC_EnableIRQ(XDMAC_IRQn);
00237 
00238     if (_Afe_configureLinkList(pAfeHw, pAfed->pXdmad, pCommand))
00239         return AFE_ERROR_LOCK;
00240 
00241     AFEC_StartConversion(pAfeHw);
00242     /* Start DMA 0(RX) */
00243     SCB_CleanInvalidateDCache();
00244     if (XDMAD_StartTransfer( pAfed->pXdmad, afeDmaRxChannel )) 
00245         return AFE_ERROR_LOCK;
00246 
00247     return AFE_OK;;
00248 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines