SAMV71 Xplained Ultra Software Package 1.4

dac_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 dacc_module Working with DACC
00031  *  \ingroup peripherals_module
00032  * The DACC driver provides the interface to configure and use the DACC
00033  * peripheral.\n
00034  *
00035  * The DACC(Digital-to-Analog Converter Controller) converts digital code to 
00036  * analog output.
00037  * The data to be converted are sent in a common register for all channels. 
00038  * It offers up to 2 analog outputs.The output voltage ranges from (1/6)ADVREF 
00039  * to (5/6)ADVREF.
00040  *
00041  * To Enable a DACC conversion,the user has to follow these few steps:
00042  * <ul>
00043  * <li> Select an appropriate reference voltage on ADVREF   </li>
00044  * <li> Configure the DACC according to its requirements and special needs,
00045  * which could be broken down into several parts:
00046  * -#   Enable DACC in free running mode by clearing TRGEN in DACC_MR;
00047  * -#   Configure Refresh Period through setting REFRESH fields
00048  *      in DACC_MR; The refresh mechanism is used to protect the output analog 
00049  * value from
00050  *      decreasing.
00051  * -#   Enable channels and write digital code to DACC_CDR,in free running mode,
00052  * the conversion is started right after at least one channel is enabled and 
00053  * data is written .
00054  </li>
00055  * </ul>
00056  *
00057  * For more accurate information, please look at the DACC section of the
00058  * Datasheet.
00059  *
00060  * Related files :\n
00061  * \ref dac_dma.c\n
00062  * \ref dac_dma.h\n
00063  */
00064 /*@{*/
00065 /*@}*/
00066 /**
00067  * \file
00068  *
00069  * Implementation of Digital-to-Analog Converter Controller (DACC).
00070  *
00071  */
00072 
00073 /*----------------------------------------------------------------------------
00074  *        Headers
00075  *----------------------------------------------------------------------------*/
00076 
00077 #include "chip.h"
00078 
00079 #include <stdint.h>
00080 #include <assert.h>
00081 
00082 /*  DMA driver instance */
00083 static uint32_t dacDmaTxChannel;
00084 static LinkedListDescriporView1 dmaWriteLinkList[256];
00085 /*----------------------------------------------------------------------------
00086  *        Local functions
00087  *----------------------------------------------------------------------------*/
00088 
00089 /**
00090  * \brief Configure the DMA Channels: 0 RX.
00091  * Channels are disabled after configure.
00092  * \returns 0 if the dma channel configuration successfully; otherwise returns
00093  * DAC_ERROR_XXX.
00094  */
00095 static uint8_t _DacConfigureDmaChannels( DacDma* pDacd )
00096 {
00097 
00098     /* Driver initialize */
00099     XDMAD_Initialize( pDacd->pXdmad, 0 );
00100 
00101     XDMAD_FreeChannel( pDacd->pXdmad, dacDmaTxChannel);
00102 
00103     /* Allocate a DMA channel for DAC0/1 TX. */
00104     dacDmaTxChannel = 
00105         XDMAD_AllocateChannel( pDacd->pXdmad, XDMAD_TRANSFER_MEMORY, ID_DACC);
00106     if ( dacDmaTxChannel == XDMAD_ALLOC_FAILED ) {
00107         return DAC_ERROR;
00108     }
00109 
00110     if ( XDMAD_PrepareChannel( pDacd->pXdmad, dacDmaTxChannel )) 
00111         return DAC_ERROR;
00112     return DAC_OK;
00113 }
00114 
00115 
00116 /**
00117  * \brief Configure the DMA source and destination with Linker List mode.
00118  *
00119  * \param pBuffer Pointer to dac buffer
00120  * \param size length of buffer
00121  */
00122 
00123 static uint8_t _Dac_configureLinkList(Dacc *pDacHw, void *pXdmad, DacCmd *pCommand)
00124 {
00125     uint32_t xdmaCndc;
00126     sXdmadCfg xdmadCfg;
00127     uint32_t * pBuffer;
00128     /* Setup TX Link List */
00129     uint8_t i;
00130     pBuffer = (uint32_t *)pCommand->pTxBuff;
00131     for(i = 0; i < pCommand->TxSize; i++){
00132         dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 
00133                                     | XDMA_UBC_NDE_FETCH_EN
00134                                     | XDMA_UBC_NSEN_UPDATED
00135                                     | XDMAC_CUBC_UBLEN(4);
00136         dmaWriteLinkList[i].mbr_sa = (uint32_t)pBuffer;
00137         dmaWriteLinkList[i].mbr_da = 
00138             (uint32_t)&(pDacHw->DACC_CDR[pCommand->dacChannel]);
00139         if ( i == (pCommand->TxSize - 1 )) {
00140             if (pCommand->loopback) {
00141                 dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0];
00142             } else {
00143                 dmaWriteLinkList[i].mbr_nda = 0;
00144             }
00145         } else {
00146             dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i+1];
00147         }
00148         pBuffer++;
00149     }
00150     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00151                      | XDMAC_CC_MBSIZE_SINGLE 
00152                      | XDMAC_CC_DSYNC_MEM2PER 
00153                      | XDMAC_CC_CSIZE_CHK_1 
00154                      | XDMAC_CC_DWIDTH_WORD
00155                      | XDMAC_CC_SIF_AHB_IF0 
00156                      | XDMAC_CC_DIF_AHB_IF1 
00157                      | XDMAC_CC_SAM_INCREMENTED_AM 
00158                      | XDMAC_CC_DAM_FIXED_AM 
00159                      | XDMAC_CC_PERID(
00160                         XDMAIF_Get_ChannelNumber(ID_DACC, XDMAD_TRANSFER_TX ));
00161     xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 
00162              | XDMAC_CNDC_NDE_DSCR_FETCH_EN 
00163              | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00164              | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00165     XDMAD_ConfigureTransfer( pXdmad, dacDmaTxChannel, &xdmadCfg, xdmaCndc, 
00166             (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE);
00167     return DAC_OK;
00168 }
00169 
00170 /*----------------------------------------------------------------------------
00171  *        Exported functions
00172  *----------------------------------------------------------------------------*/
00173 /**
00174  * \brief Initializes the DacDma structure and the corresponding DAC & DMA .
00175  * hardware select value.
00176  * The driver will uses DMA channel 0 for RX .
00177  * The DMA channels are freed automatically when no DMA command processing.
00178  *
00179  * \param pDacd  Pointer to a DacDma instance.
00180  * \param pDacHw Associated Dac peripheral.
00181  * \param DacId  Dac peripheral identifier.
00182  * \param pDmad  Pointer to a Dmad instance. 
00183  */
00184 uint32_t Dac_ConfigureDma( DacDma *pDacd ,
00185         Dacc *pDacHw ,
00186         uint8_t DacId,
00187         sXdmad *pXdmad )
00188 {
00189     /* Initialize the Dac structure */
00190     pDacd->pDacHw = pDacHw;
00191     pDacd->dacId  = DacId;
00192     pDacd->semaphore = 1;
00193     pDacd->pCurrentCommand = 0;
00194     pDacd->pXdmad = pXdmad;
00195     return 0;
00196 }
00197 
00198 /**
00199  * \brief Starts a DAC transfer. This is a non blocking function. It will
00200  *  return as soon as the transfer is started.
00201  *
00202  * \param pDacd  Pointer to a DacDma instance.
00203  * \param pCommand Pointer to the Dac command to execute.
00204  * \returns 0 if the transfer has been started successfully; otherwise returns
00205  * DAC_ERROR_LOCK is the driver is in use, or DAC_ERROR if the command is not
00206  * valid.
00207  */
00208 uint32_t Dac_SendData( DacDma *pDacd, DacCmd *pCommand)
00209 {
00210     Dacc *pDacHw = pDacd->pDacHw;
00211 
00212     /* Try to get the dataflash semaphore */
00213     if (pDacd->semaphore == 0) {
00214         return DAC_ERROR_LOCK;
00215     }
00216     pDacd->semaphore--;
00217 
00218     // Initialize the callback
00219     pDacd->pCurrentCommand = pCommand;
00220 
00221     /* Initialize DMA controller using channel 0 for RX. */
00222     if (_DacConfigureDmaChannels(pDacd) )
00223         return DAC_ERROR_LOCK;
00224 
00225     if (_Dac_configureLinkList(pDacHw, pDacd->pXdmad, pCommand))
00226         return DAC_ERROR_LOCK;
00227 
00228     SCB_CleanDCache();
00229 
00230     /* Start DMA TX */
00231     if (XDMAD_StartTransfer( pDacd->pXdmad, dacDmaTxChannel )) 
00232         return DAC_ERROR_LOCK;
00233     return DAC_OK;;
00234 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines