diff options
Diffstat (limited to 'bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c')
-rw-r--r-- | bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c new file mode 100644 index 0000000000..5675499f95 --- /dev/null +++ b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c @@ -0,0 +1,238 @@ +/* ---------------------------------------------------------------------------- */ +/* Atmel Microcontroller Software Support */ +/* SAM Software Package License */ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2015, Atmel Corporation */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following condition is met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the disclaimer below. */ +/* */ +/* Atmel's name may not be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ +/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ +/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ +/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* ---------------------------------------------------------------------------- */ + +/** \addtogroup dacc_module Working with DACC + * \ingroup peripherals_module + * The DACC driver provides the interface to configure and use the DACC + * peripheral.\n + * + * The DACC(Digital-to-Analog Converter Controller) converts digital code to + * analog output. + * The data to be converted are sent in a common register for all channels. + * It offers up to 2 analog outputs.The output voltage ranges from (1/6)ADVREF + * to (5/6)ADVREF. + * + * To Enable a DACC conversion,the user has to follow these few steps: + * <ul> + * <li> Select an appropriate reference voltage on ADVREF </li> + * <li> Configure the DACC according to its requirements and special needs, + * which could be broken down into several parts: + * -# Enable DACC in free running mode by clearing TRGEN in DACC_MR; + * -# Configure Refresh Period through setting REFRESH fields + * in DACC_MR; The refresh mechanism is used to protect the output analog + * value from + * decreasing. + * -# Enable channels and write digital code to DACC_CDR,in free running mode, + * the conversion is started right after at least one channel is enabled and + * data is written . + </li> + * </ul> + * + * For more accurate information, please look at the DACC section of the + * Datasheet. + * + * Related files :\n + * \ref dac_dma.c\n + * \ref dac_dma.h\n + */ +/*@{*/ +/*@}*/ +/** + * \file + * + * Implementation of Digital-to-Analog Converter Controller (DACC). + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include <stdint.h> +#include <assert.h> + +/* DMA driver instance */ +static uint32_t dacDmaTxChannel; +static LinkedListDescriporView1 dmaWriteLinkList[256]; +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configure the DMA Channels: 0 RX. + * Channels are disabled after configure. + * \returns 0 if the dma channel configuration successfully; otherwise returns + * DAC_ERROR_XXX. + */ +static uint8_t _DacConfigureDmaChannels(DacDma *pDacd) +{ + + /* Driver initialize */ + XDMAD_FreeChannel(pDacd->pXdmad, dacDmaTxChannel); + + /* Allocate a DMA channel for DAC0/1 TX. */ + dacDmaTxChannel = + XDMAD_AllocateChannel(pDacd->pXdmad, XDMAD_TRANSFER_MEMORY, ID_DACC); + + if (dacDmaTxChannel == XDMAD_ALLOC_FAILED) + return DAC_ERROR; + + if (XDMAD_PrepareChannel(pDacd->pXdmad, dacDmaTxChannel)) + return DAC_ERROR; + + return DAC_OK; +} + + +/** + * \brief Configure the DMA source and destination with Linker List mode. + * + * \param pBuffer Pointer to dac buffer + * \param size length of buffer + */ + +static uint8_t _Dac_configureLinkList(Dacc *pDacHw, void *pXdmad, + DacCmd *pCommand) +{ + uint32_t xdmaCndc; + sXdmadCfg xdmadCfg; + uint32_t *pBuffer; + /* Setup TX Link List */ + uint8_t i; + pBuffer = (uint32_t *)pCommand->pTxBuff; + + for (i = 0; i < pCommand->TxSize; i++) { + dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 + | XDMA_UBC_NDE_FETCH_EN + | XDMA_UBC_NSEN_UPDATED + | XDMAC_CUBC_UBLEN(4); + dmaWriteLinkList[i].mbr_sa = (uint32_t)pBuffer; + dmaWriteLinkList[i].mbr_da = + (uint32_t) & (pDacHw->DACC_CDR[pCommand->dacChannel]); + + if (i == (pCommand->TxSize - 1)) { + if (pCommand->loopback) + dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0]; + else + dmaWriteLinkList[i].mbr_nda = 0; + } else + dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i + 1]; + + pBuffer++; + } + + xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN + | XDMAC_CC_MBSIZE_SINGLE + | XDMAC_CC_DSYNC_MEM2PER + | XDMAC_CC_CSIZE_CHK_1 + | XDMAC_CC_DWIDTH_WORD + | XDMAC_CC_SIF_AHB_IF1 + | XDMAC_CC_DIF_AHB_IF1 + | XDMAC_CC_SAM_INCREMENTED_AM + | XDMAC_CC_DAM_FIXED_AM + | XDMAC_CC_PERID( + XDMAIF_Get_ChannelNumber(ID_DACC, XDMAD_TRANSFER_TX)); + xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 + | XDMAC_CNDC_NDE_DSCR_FETCH_EN + | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED + | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED; + XDMAD_ConfigureTransfer(pXdmad, dacDmaTxChannel, &xdmadCfg, xdmaCndc, + (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE); + return DAC_OK; +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ +/** + * \brief Initializes the DacDma structure and the corresponding DAC & DMA . + * hardware select value. + * The driver will uses DMA channel 0 for RX . + * The DMA channels are freed automatically when no DMA command processing. + * + * \param pDacd Pointer to a DacDma instance. + * \param pDacHw Associated Dac peripheral. + * \param DacId Dac peripheral identifier. + * \param pDmad Pointer to a Dmad instance. + */ +uint32_t Dac_ConfigureDma(DacDma *pDacd , + Dacc *pDacHw , + uint8_t DacId, + sXdmad *pXdmad) +{ + /* Initialize the Dac structure */ + pDacd->pDacHw = pDacHw; + pDacd->dacId = DacId; + pDacd->semaphore = 1; + pDacd->pCurrentCommand = 0; + assert(pXdmad == &XDMAD_Instance); + pDacd->pXdmad = pXdmad; + return 0; +} + +/** + * \brief Starts a DAC transfer. This is a non blocking function. It will + * return as soon as the transfer is started. + * + * \param pDacd Pointer to a DacDma instance. + * \param pCommand Pointer to the Dac command to execute. + * \returns 0 if the transfer has been started successfully; otherwise returns + * DAC_ERROR_LOCK is the driver is in use, or DAC_ERROR if the command is not + * valid. + */ +uint32_t Dac_SendData(DacDma *pDacd, DacCmd *pCommand) +{ + Dacc *pDacHw = pDacd->pDacHw; + + /* Try to get the dataflash semaphore */ + if (pDacd->semaphore == 0) + return DAC_ERROR_LOCK; + + pDacd->semaphore--; + + // Initialize the callback + pDacd->pCurrentCommand = pCommand; + + /* Initialize DMA controller using channel 0 for RX. */ + if (_DacConfigureDmaChannels(pDacd)) + return DAC_ERROR_LOCK; + + if (_Dac_configureLinkList(pDacHw, pDacd->pXdmad, pCommand)) + return DAC_ERROR_LOCK; + + SCB_CleanDCache(); + + /* Start DMA TX */ + if (XDMAD_StartTransfer(pDacd->pXdmad, dacDmaTxChannel)) + return DAC_ERROR_LOCK; + + return DAC_OK;; +} |