]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/afe_dma.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / afe_dma.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2014, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /** \addtogroup afecc_module Working with afecC\r
31  *  \ingroup peripherals_module\r
32  * The afecC driver provides the interface to configure and use the afecC peripheral.\n\r
33  *\r
34  * The afecC(Digital-to-Analog Converter Controller) converts digital code to analog output.\r
35  * The data to be converted are sent in a common register for all channels. It offers up to 2\r
36  * analog outputs.The output voltage ranges from (1/6)ADVREF to (5/6)ADVREF.\r
37  *\r
38  * To Enable a afecC conversion,the user has to follow these few steps:\r
39  * <ul>\r
40  * <li> Select an appropriate reference voltage on ADVREF   </li>\r
41  * <li> Configure the afecC according to its requirements and special needs,which could be\r
42  broken down into several parts:\r
43  * -#   Enable afecC in free running mode by clearing TRGEN in afecC_MR;\r
44  * -#   Configure Refresh Period through setting REFRESH fields\r
45  *      in afecC_MR; The refresh mechanism is used to protect the output analog value from\r
46  *      decreasing.\r
47  * -#   Enable channels and write digital code to afecC_CDR,in free running mode, the conversion\r
48  *      is started right after at least one channel is enabled and data is written .\r
49  </li>\r
50  * </ul>\r
51  *\r
52  * For more accurate information, please look at the afecC section of the\r
53  * Datasheet.\r
54  *\r
55  * Related files :\n\r
56  * \ref afecC.c\n\r
57  * \ref afecC.h\n\r
58  */\r
59 /*@{*/\r
60 /*@}*/\r
61 /**\r
62  * \file\r
63  *\r
64  * Implementation of Digital-to-Analog Converter Controller (afecC).\r
65  *\r
66  */\r
67 /*----------------------------------------------------------------------------\r
68  *        Headers\r
69  *----------------------------------------------------------------------------*/\r
70 \r
71 #include "chip.h"\r
72 \r
73 #include <stdint.h>\r
74 #include <assert.h>\r
75 \r
76 /*  DMA driver instance */\r
77 static uint32_t afeDmaRxChannel;\r
78 \r
79 /*----------------------------------------------------------------------------\r
80  *        Local functions\r
81  *----------------------------------------------------------------------------*/\r
82 \r
83 /**\r
84  * \brief AFE xDMA Rx callback\r
85  * Invoked on AFE DMA reception done.\r
86  * \param channel DMA channel.\r
87  * \param pArg Pointer to callback argument - Pointer to AfeDma instance.\r
88  */ \r
89 static void Afe_Rx_Cb(uint32_t channel, AfeDma* pArg)\r
90 {\r
91     AfeCmd *pAfedCmd = pArg->pCurrentCommand;\r
92     if (channel != afeDmaRxChannel)\r
93         return;\r
94 \r
95     /* Configure and enable interrupt on RC compare */\r
96     NVIC_ClearPendingIRQ(XDMAC_IRQn);\r
97     NVIC_DisableIRQ(XDMAC_IRQn);\r
98 \r
99     /* Release the DMA channels */\r
100     XDMAD_FreeChannel(pArg->pXdmad, afeDmaRxChannel);\r
101 \r
102     /* Release the dataflash semaphore */\r
103     pArg->semaphore++;\r
104 \r
105     /* Invoke the callback associated with the current command */\r
106     if (pAfedCmd && pAfedCmd->callback) {\r
107         pAfedCmd->callback(0, pAfedCmd->pArgument);\r
108     }\r
109 }\r
110 \r
111 /**\r
112  * \brief Configure the DMA Channels: 0 RX.\r
113  * Channels are disabled after configure.\r
114  * \returns 0 if the dma channel configuration successfully; otherwise returns\r
115  * AFE_ERROR_XXX.\r
116  */\r
117 static uint8_t _AfeConfigureDmaChannels( AfeDma* pAfed )\r
118 {\r
119 \r
120     /* Driver initialize */\r
121     XDMAD_Initialize( pAfed->pXdmad, 0 );\r
122 \r
123     XDMAD_FreeChannel( pAfed->pXdmad, afeDmaRxChannel);\r
124 \r
125     /* Allocate a DMA channel for AFE0/1 RX. */\r
126     afeDmaRxChannel = XDMAD_AllocateChannel( pAfed->pXdmad, pAfed->afeId, XDMAD_TRANSFER_MEMORY);\r
127     {\r
128         if ( afeDmaRxChannel == XDMAD_ALLOC_FAILED ) \r
129         {\r
130             return AFE_ERROR;\r
131         }\r
132     }\r
133 \r
134     /* Setup callbacks for AFE0/1 RX */\r
135     XDMAD_SetCallback(pAfed->pXdmad, afeDmaRxChannel, (XdmadTransferCallback)Afe_Rx_Cb, pAfed);\r
136     if (XDMAD_PrepareChannel( pAfed->pXdmad, afeDmaRxChannel ))\r
137         return AFE_ERROR;\r
138     return AFE_OK;\r
139 }\r
140 \r
141 \r
142 /**\r
143  * \brief Configure the DMA source and destination with Linker List mode.\r
144  *\r
145  * \param pBuffer Pointer to afec buffer\r
146  * \param size length of buffer\r
147  */\r
148 \r
149 static uint8_t _Afe_configureLinkList(Afec *pAfeHw, void *pXdmad, AfeCmd *pCommand)\r
150 {\r
151     uint32_t xdmaCndc;\r
152     sXdmadCfg xdmadRxCfg;\r
153     uint32_t afeId;\r
154     if ((unsigned int)pAfeHw == (unsigned int)AFEC0 ) afeId = ID_AFEC0;\r
155     if ((unsigned int)pAfeHw == (unsigned int)AFEC1 ) afeId = ID_AFEC1;\r
156     /* Setup RX Link List */\r
157     xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |\r
158         XDMA_UBC_NDE_FETCH_EN|\r
159         XDMA_UBC_NDEN_UPDATED |\r
160         pCommand->RxSize;;\r
161     xdmadRxCfg.mbr_da = (uint32_t)pCommand->pRxBuff;\r
162     xdmadRxCfg.mbr_sa = (uint32_t)&(pAfeHw->AFEC_LCDR);\r
163     xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |\r
164         XDMAC_CC_MBSIZE_SINGLE |\r
165         XDMAC_CC_DSYNC_PER2MEM |\r
166         XDMAC_CC_CSIZE_CHK_1 |\r
167         XDMAC_CC_DWIDTH_WORD|\r
168         XDMAC_CC_SIF_AHB_IF1 |\r
169         XDMAC_CC_DIF_AHB_IF0 |\r
170         XDMAC_CC_SAM_FIXED_AM |\r
171         XDMAC_CC_DAM_INCREMENTED_AM |\r
172         XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(  afeId, XDMAD_TRANSFER_RX ));\r
173 \r
174     xdmadRxCfg.mbr_bc = 0;\r
175     xdmadRxCfg.mbr_sus = 0;\r
176     xdmadRxCfg.mbr_dus =0;\r
177 \r
178     xdmaCndc = 0;\r
179     if (XDMAD_ConfigureTransfer( pXdmad, afeDmaRxChannel, &xdmadRxCfg, xdmaCndc, 0))\r
180         return AFE_ERROR;\r
181 \r
182     return AFE_OK;\r
183 }\r
184 \r
185 /*----------------------------------------------------------------------------\r
186  *        Exported functions\r
187  *----------------------------------------------------------------------------*/\r
188 \r
189 \r
190 /**\r
191  * \brief Initializes the AfeDma structure and the corresponding AFE & DMA hardware.\r
192  * select value.\r
193  * The driver will uses DMA channel 0 for RX .\r
194  * The DMA channels are freed automatically when no DMA command processing.\r
195  *\r
196  * \param pAfed  Pointer to a AfeDma instance.\r
197  * \param pAfeHw Associated Afe peripheral.\r
198  * \param AfeId  Afe peripheral identifier.\r
199  * \param pDmad  Pointer to a Dmad instance. \r
200  */\r
201 uint32_t Afe_ConfigureDma( AfeDma *pAfed ,\r
202         Afec *pAfeHw ,\r
203         uint8_t AfeId,\r
204         sXdmad *pXdmad )\r
205 {\r
206     /* Initialize the Afe structure */\r
207     pAfed->pAfeHw = pAfeHw;\r
208     pAfed->afeId  = AfeId;\r
209     pAfed->semaphore = 1;\r
210     pAfed->pCurrentCommand = 0;\r
211     pAfed->pXdmad = pXdmad;\r
212     return 0;\r
213 }\r
214 \r
215 /**\r
216  * \brief Starts a AFE transfer. This is a non blocking function. It will\r
217  *  return as soon as the transfer is started.\r
218  *\r
219  * \param pAfed  Pointer to a AfeDma instance.\r
220  * \param pCommand Pointer to the Afe command to execute.\r
221  * \returns 0 if the transfer has been started successfully; otherwise returns\r
222  * AFE_ERROR_LOCK is the driver is in use, or AFE_ERROR if the command is not\r
223  * valid.\r
224  */\r
225 uint32_t Afe_SendData( AfeDma *pAfed, AfeCmd *pCommand)\r
226 {\r
227     Afec *pAfeHw = pAfed->pAfeHw;\r
228 \r
229     /* Try to get the dataflash semaphore */\r
230     if (pAfed->semaphore == 0) {\r
231 \r
232         return AFE_ERROR_LOCK;\r
233     }\r
234     pAfed->semaphore--;\r
235 \r
236     // Initialize the callback\r
237     pAfed->pCurrentCommand = pCommand;\r
238 \r
239     /* Initialize DMA controller using channel 0 for RX. */\r
240     if (_AfeConfigureDmaChannels(pAfed) )\r
241         return AFE_ERROR_LOCK;\r
242 \r
243     /* Configure and enable interrupt on RC compare */\r
244     NVIC_ClearPendingIRQ(XDMAC_IRQn);\r
245     NVIC_SetPriority( XDMAC_IRQn ,1);\r
246     NVIC_EnableIRQ(XDMAC_IRQn);\r
247 \r
248     if (_Afe_configureLinkList(pAfeHw, pAfed->pXdmad, pCommand))\r
249         return AFE_ERROR_LOCK;\r
250 \r
251     AFEC_StartConversion(pAfeHw);\r
252     /* Start DMA 0(RX) */\r
253     if (XDMAD_StartTransfer( pAfed->pXdmad, afeDmaRxChannel )) \r
254         return AFE_ERROR_LOCK;\r
255 \r
256     return AFE_OK;;\r
257 }\r