1 /***************************************************************************//**
2 * \file cy_dma.c
3 * \version 2.70
4 *
5 * \brief
6 * The source code file for the DMA driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27 #include <assert.h>
28
29 #if defined (CY_IP_M4CPUSS_DMA) || defined (CY_IP_MXDW) || defined (CY_IP_M7CPUSS_DMA)
30
31 #include "cy_dma.h"
32
33 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 5, \
34 'DW_Type will typecast to either DW_V1_Type or DW_V2_Type but not both on PDL initialization based on the target device at compile time.')
35 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 10.8', 2, \
36 'Value extracted from _VAL2FLD macro will not exceed enum range.')
37
38 /*******************************************************************************
39 * Function Name: Cy_DMA_Crc_Init
40 ****************************************************************************//**
41 *
42 * Initializes the DMA CRC functionality.
43 *
44 * \param base The pointer to the hardware DMA block.
45 *
46 * \param crcConfig The pointer to the CRC configuration structure
47 * \ref cy_stc_dma_crc_config_t.
48 *
49 * \return The status /ref cy_en_dma_status_t.
50 *
51 * \funcusage
52 * \snippet dma/snippet/main.c snippet_Cy_DMA_Crc_Init
53 *
54 *******************************************************************************/
Cy_DMA_Crc_Init(DW_Type * base,cy_stc_dma_crc_config_t const * crcConfig)55 cy_en_dma_status_t Cy_DMA_Crc_Init(DW_Type * base, cy_stc_dma_crc_config_t const * crcConfig)
56 {
57 cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
58 #ifdef CY_IP_MXDW
59 if((NULL != base) && (NULL != crcConfig) )
60 #else
61 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','Intentional check for the macro CY_DW_CRC.');
62 if((NULL != base) && (NULL != crcConfig) && (CY_DW_CRC == 1UL))
63 #endif /* CY_IP_MXDW */
64 {
65 DW_CRC_CTL(base) = _BOOL2FLD(DW_V2_CRC_CTL_DATA_REVERSE, crcConfig->dataReverse) |
66 _BOOL2FLD(DW_V2_CRC_CTL_REM_REVERSE, crcConfig->reminderReverse);
67
68 DW_CRC_DATA_CTL(base) = _VAL2FLD(DW_V2_CRC_DATA_CTL_DATA_XOR, crcConfig->dataXor);
69 DW_CRC_REM_CTL(base) = _VAL2FLD(DW_V2_CRC_REM_CTL_REM_XOR, crcConfig->reminderXor);
70 DW_CRC_POL_CTL(base) = _VAL2FLD(DW_V2_CRC_POL_CTL_POLYNOMIAL, crcConfig->polynomial);
71 DW_CRC_LFSR_CTL(base) = _VAL2FLD(DW_V2_CRC_LFSR_CTL_LFSR32, crcConfig->lfsrInitVal);
72
73 ret = CY_DMA_SUCCESS;
74 }
75
76 return ret;
77 }
78
79
80 /*******************************************************************************
81 * Function Name: Cy_DMA_Descriptor_Init
82 ****************************************************************************//**
83 *
84 * Initializes the descriptor structure in SRAM from a pre-initialized
85 * configuration structure.
86 * This function initializes only the descriptor and not the channel.
87 *
88 * \param descriptor
89 * The descriptor structure instance declared by the user/component.
90 *
91 * \param config
92 * This is a configuration structure that has all initialization information for
93 * the descriptor.
94 *
95 * \return
96 * The status /ref cy_en_dma_status_t.
97 *
98 * \funcusage
99 * \snippet dma/snippet/main.c snippet_Cy_DMA_Enable
100 *
101 *******************************************************************************/
Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor,const cy_stc_dma_descriptor_config_t * config)102 cy_en_dma_status_t Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor, const cy_stc_dma_descriptor_config_t * config)
103 {
104 cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
105
106 if ((NULL != descriptor) && (NULL != config))
107 {
108 CY_ASSERT_L3(CY_DMA_IS_RETRIG_VALID(config->retrigger));
109 CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->interruptType));
110 CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerOutType));
111 CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerInType));
112 CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->srcTransferSize));
113 CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->dstTransferSize));
114 CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(config->channelState));
115 CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(config->dataSize));
116 CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(config->descriptorType));
117
118 descriptor->ctl =
119 _VAL2FLD(CY_DMA_CTL_RETRIG, config->retrigger) |
120 _VAL2FLD(CY_DMA_CTL_INTR_TYPE, config->interruptType) |
121 _VAL2FLD(CY_DMA_CTL_TR_OUT_TYPE, config->triggerOutType) |
122 _VAL2FLD(CY_DMA_CTL_TR_IN_TYPE, config->triggerInType) |
123 _VAL2FLD(CY_DMA_CTL_SRC_SIZE, config->srcTransferSize) |
124 _VAL2FLD(CY_DMA_CTL_DST_SIZE, config->dstTransferSize) |
125 _VAL2FLD(CY_DMA_CTL_CH_DISABLE, config->channelState) |
126 _VAL2FLD(CY_DMA_CTL_DATA_SIZE, config->dataSize) |
127 _VAL2FLD(CY_DMA_CTL_TYPE, config->descriptorType);
128
129 descriptor->src = (uint32_t)config->srcAddress;
130
131 descriptor->dst = (uint32_t)config->dstAddress;
132
133 switch(config->descriptorType)
134 {
135 case CY_DMA_SINGLE_TRANSFER:
136 descriptor->xCtl = (uint32_t)config->nextDescriptor;
137 ret = CY_DMA_SUCCESS;
138 break;
139
140 case CY_DMA_1D_TRANSFER:
141 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
142 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
143 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
144
145 descriptor->xCtl =
146 _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
147 _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
148 /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
149 _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
150
151 descriptor->yCtl = (uint32_t)config->nextDescriptor;
152 ret = CY_DMA_SUCCESS;
153 break;
154
155 case CY_DMA_2D_TRANSFER:
156 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
157 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
158 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
159 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcYincrement));
160 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstYincrement));
161 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->yCount));
162
163 descriptor->xCtl =
164 _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
165 _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
166 /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
167 _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
168
169 descriptor->yCtl =
170 _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcYincrement) |
171 _VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstYincrement) |
172 /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
173 _VAL2FLD(CY_DMA_CTL_COUNT, config->yCount - 1UL);
174
175 descriptor->nextPtr = (uint32_t)config->nextDescriptor;
176 ret = CY_DMA_SUCCESS;
177 break;
178
179 case CY_DMA_CRC_TRANSFER:
180 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','CY_DW_CRC is available for all CAT1B devices.');
181 if (CY_DW_CRC != 0UL)
182 {
183 CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
184 CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
185
186 descriptor->xCtl =
187 _VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
188 /* Convert the data count from the user's range (1-256) into the machine range (0-255). */
189 _VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
190
191 descriptor->yCtl = (uint32_t)config->nextDescriptor;
192 ret = CY_DMA_SUCCESS;
193 }
194 break;
195
196 default: /* An unsupported type of a descriptor */
197 break;
198 }
199 }
200
201 return ret;
202 }
203
204
205 /*******************************************************************************
206 * Function Name: Cy_DMA_Descriptor_DeInit
207 ****************************************************************************//**
208 *
209 * Clears the content of the specified descriptor.
210 *
211 * \param descriptor
212 * The descriptor structure instance declared by the user/component.
213 *
214 * \funcusage
215 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_Deinit
216 *
217 *******************************************************************************/
Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)218 void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)
219 {
220 CY_ASSERT_L1(descriptor);
221
222 descriptor->ctl = 0UL;
223 descriptor->src = 0UL;
224 descriptor->dst = 0UL;
225 descriptor->xCtl = 0UL;
226 descriptor->yCtl = 0UL;
227 descriptor->nextPtr = 0UL;
228 }
229
230
231 /*******************************************************************************
232 * Function Name: Cy_DMA_Channel_Init
233 ****************************************************************************//**
234 *
235 * Initializes the DMA channel with a descriptor and other parameters.
236 *
237 * \param base
238 * The pointer to the hardware DMA block.
239 *
240 * \param channel
241 * A channel number.
242 *
243 * \param channelConfig
244 * The structure that has the initialization information for the
245 * channel.
246 *
247 * \return
248 * The status /ref cy_en_dma_status_t.
249 *
250 * \funcusage
251 * \snippet dma/snippet/main.c snippet_Cy_DMA_Enable
252 *
253 *******************************************************************************/
Cy_DMA_Channel_Init(DW_Type * base,uint32_t channel,cy_stc_dma_channel_config_t const * channelConfig)254 cy_en_dma_status_t Cy_DMA_Channel_Init(DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig)
255 {
256 cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
257
258 if ((NULL != base) &&
259 (NULL != channelConfig) &&
260 (NULL != channelConfig->descriptor) &&
261 (CY_DMA_IS_CH_NR_VALID(base, channel)))
262 {
263 CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(channelConfig->priority));
264
265 /* Set the current descriptor */
266 Cy_DMA_Channel_SetDescriptor(base, channel, channelConfig->descriptor);
267
268 /* Set the channel configuration */
269 DW_CH_CTL(base, channel) =
270 _BOOL2FLD(CY_DW_CH_CTL_PREEMPTABLE, channelConfig->preemptable) |
271 _VAL2FLD(CY_DW_CH_CTL_PRIO, channelConfig->priority) |
272 _BOOL2FLD(DW_CH_STRUCT_CH_CTL_ENABLED, channelConfig->enable) |
273 _BOOL2FLD(DW_CH_STRUCT_CH_CTL_B, channelConfig->bufferable);
274 ret = CY_DMA_SUCCESS;
275 }
276
277 return (ret);
278 }
279
280
281 /*******************************************************************************
282 * Function Name: Cy_DMA_Channel_DeInit
283 ****************************************************************************//**
284 *
285 * Clears the content of registers corresponding to the channel.
286 *
287 * \param base
288 * The pointer to the hardware DMA block.
289 *
290 * \param channel
291 * A channel number.
292 *
293 * \funcusage
294 * \snippet dma/snippet/main.c snippet_Cy_DMA_Disable
295 *
296 *******************************************************************************/
Cy_DMA_Channel_DeInit(DW_Type * base,uint32_t channel)297 void Cy_DMA_Channel_DeInit(DW_Type * base, uint32_t channel)
298 {
299 CY_ASSERT_L1(CY_DMA_IS_CH_NR_VALID(base, channel));
300
301 DW_CH_CTL(base, channel) = 0UL;
302 DW_CH_IDX(base, channel) = 0UL;
303 DW_CH_CURR_PTR(base, channel) = 0UL;
304 DW_CH_INTR_MASK(base, channel) = 0UL;
305 }
306
307
308 /*******************************************************************************
309 * Function Name: Cy_DMA_Descriptor_SetNextDescriptor
310 ****************************************************************************//**
311 *
312 * Sets a Next Descriptor for the specified descriptor.
313 *
314 * Based on the descriptor type, the offset of the address for the next descriptor may
315 * vary. For the single-transfer descriptor type, this register is at offset 0x0c.
316 * For the 1D-transfer descriptor type, this register is at offset 0x10.
317 * For the 2D-transfer descriptor type, this register is at offset 0x14.
318 *
319 * \param descriptor
320 * The descriptor structure instance declared by the user/component.
321 *
322 * \param nextDescriptor
323 * The pointer to the next descriptor.
324 * For CAT1C devices this pointer needs to point to 32 byte aligned structure.
325 *
326 * \funcusage
327 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_SetterFunctions
328 *
329 *******************************************************************************/
Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor,cy_stc_dma_descriptor_t const * nextDescriptor)330 void Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor)
331 {
332 CY_ASSERT_L1(descriptor);
333 cy_en_dma_descriptor_type_t transferType = (cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl);
334
335 if (transferType == CY_DMA_SINGLE_TRANSFER)
336 {
337 descriptor->xCtl = (uint32_t)nextDescriptor;
338 }
339 else if (transferType == CY_DMA_CRC_TRANSFER || transferType == CY_DMA_1D_TRANSFER)
340 {
341 descriptor->yCtl = (uint32_t)nextDescriptor;
342 }
343 else if ( transferType == CY_DMA_2D_TRANSFER)
344 {
345 descriptor->nextPtr = (uint32_t)nextDescriptor;
346 }
347 else
348 {
349 /* Unsupported type of descriptor */
350 }
351
352 }
353
354
355 /*******************************************************************************
356 * Function Name: Cy_DMA_Descriptor_GetNextDescriptor
357 ****************************************************************************//**
358 *
359 * Returns a next descriptor address of the specified descriptor.
360 *
361 * Based on the descriptor type, the offset of the address for the next descriptor may
362 * vary. For a single-transfer descriptor type, this register is at offset 0x0c.
363 * For the 1D-transfer descriptor type, this register is at offset 0x10.
364 * For the 2D-transfer descriptor type, this register is at offset 0x14.
365 *
366 * \param descriptor
367 * The descriptor structure instance declared by the user/component.
368 *
369 * \return
370 * The pointer to the next descriptor.
371 *
372 * \funcusage
373 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_GetterFunctions
374 *
375 *******************************************************************************/
Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)376 cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)
377 {
378 cy_stc_dma_descriptor_t * retVal = NULL;
379 CY_ASSERT_L1(descriptor);
380 cy_en_dma_descriptor_type_t transferType = (cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl);
381
382 if (transferType == CY_DMA_SINGLE_TRANSFER)
383 {
384 retVal = (cy_stc_dma_descriptor_t*) descriptor->xCtl;
385 }
386 else if (transferType == CY_DMA_CRC_TRANSFER || transferType == CY_DMA_1D_TRANSFER)
387 {
388 retVal = (cy_stc_dma_descriptor_t*) descriptor->yCtl;
389 }
390 else if (transferType == CY_DMA_2D_TRANSFER)
391 {
392 retVal = (cy_stc_dma_descriptor_t*) descriptor->nextPtr;
393 }
394 else
395 {
396 /* An unsupported type of the descriptor */
397 }
398
399 return (retVal);
400 }
401
402
403 /*******************************************************************************
404 * Function Name: Cy_DMA_Descriptor_SetDescriptorType
405 ****************************************************************************//**
406 *
407 * Sets the descriptor's type for the specified descriptor.
408 * Moves the next descriptor register value into the proper place in accordance
409 * to the actual descriptor type.
410 * During the descriptor's type changing, the Xloop and Yloop settings, such as
411 * data count and source/destination increment (i.e. the content of the
412 * xCtl and yCtl descriptor registers) might be lost (overridden by the
413 * next descriptor value) because of the different descriptor registers structures
414 * for different descriptor types. Carefully set up the Xloop
415 * (and Yloop, if used) data count and source/destination increment if the
416 * descriptor type is changed from a simpler to a more complicated type
417 * ("single transfer" -> "1D", "1D" -> "2D", etc.).
418 *
419 * \param descriptor
420 * The descriptor structure instance declared by the user/component.
421 *
422 * \param descriptorType
423 * The descriptor type \ref cy_en_dma_descriptor_type_t.
424 *
425 * \funcusage
426 * \snippet dma/snippet/main.c snippet_Cy_DMA_Descriptor_SetterFunctions
427 *
428 *******************************************************************************/
Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor,cy_en_dma_descriptor_type_t descriptorType)429 void Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_descriptor_type_t descriptorType)
430 {
431 CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(descriptorType));
432 CY_ASSERT_L1(descriptor);
433 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 14.3','CY_DW_CRC is available for all CAT1B devices.');
434 if ((CY_DMA_CRC_TRANSFER != descriptorType) || (CY_DW_CRC == 1UL))
435 {
436 if (descriptorType != Cy_DMA_Descriptor_GetDescriptorType(descriptor)) /* Do not perform if the type is not changed */
437 {
438 /* Store the current nextDescriptor pointer. */
439 cy_stc_dma_descriptor_t const * locNextDescriptor = Cy_DMA_Descriptor_GetNextDescriptor(descriptor);
440 /* Change the descriptor type. */
441 CY_REG32_CLR_SET(descriptor->ctl, CY_DMA_CTL_TYPE, descriptorType);
442 /* Restore the nextDescriptor pointer into the proper place. */
443 Cy_DMA_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor);
444 }
445 }
446 }
447
448 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
449 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 10.8')
450
451 #endif /* CY_IP_M4CPUSS_DMA, CY_IP_MXDW */
452
453 /* [] END OF FILE */
454