1 /***************************************************************************//**
2 * \file cy_dmac.c
3 * \version 1.30.1
4 *
5 * \brief
6 * The source code file for the DMAC driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 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
28 #if defined (CY_IP_M4CPUSS_DMAC) || defined (CY_IP_MXAHBDMAC) || defined (CY_IP_M7CPUSS_DMAC)
29
30
31 #include "cy_dmac.h"
32
33 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 8, \
34 'The cast to another type is made intentionally. \
35 These structures are subset of the main structure cy_stc_dmac_descriptor_t. \
36 This will provide better code readability with the type of data transfer used')
37
38 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 10.8', 2, \
39 'Value extracted from _VAL2FLD macro will not exceed enum range.')
40
41 /*******************************************************************************
42 * Function Name: Cy_DMAC_Descriptor_Init
43 ****************************************************************************//**
44 *
45 * Initializes the descriptor structure in SRAM from a pre-initialized
46 * configuration structure.
47 * This function initializes only the descriptor and not the channel.
48 *
49 * \param descriptor
50 * The descriptor structure instance.
51 *
52 * \param config
53 * This is a configuration structure that has all initialization information for
54 * the descriptor.
55 *
56 * \return
57 * The status /ref cy_en_dmac_status_t.
58 *
59 * \funcusage
60 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Enable
61 *
62 *******************************************************************************/
Cy_DMAC_Descriptor_Init(cy_stc_dmac_descriptor_t * descriptor,const cy_stc_dmac_descriptor_config_t * config)63 cy_en_dmac_status_t Cy_DMAC_Descriptor_Init(cy_stc_dmac_descriptor_t * descriptor, const cy_stc_dmac_descriptor_config_t * config)
64 {
65 cy_en_dmac_status_t ret = CY_DMAC_BAD_PARAM;
66
67 if ((NULL != descriptor) && (NULL != config))
68 {
69 CY_ASSERT_L3(CY_DMAC_IS_RETRIGGER_VALID(config->retrigger));
70 CY_ASSERT_L3(CY_DMAC_IS_TRIG_TYPE_VALID(config->interruptType));
71 CY_ASSERT_L3(CY_DMAC_IS_TRIG_TYPE_VALID(config->triggerOutType));
72 CY_ASSERT_L3(CY_DMAC_IS_TRIG_TYPE_VALID(config->triggerInType));
73 CY_ASSERT_L3(CY_DMAC_IS_XFER_SIZE_VALID(config->srcTransferSize));
74 CY_ASSERT_L3(CY_DMAC_IS_XFER_SIZE_VALID(config->dstTransferSize));
75 CY_ASSERT_L3(CY_DMAC_IS_CHANNEL_STATE_VALID(config->channelState));
76 CY_ASSERT_L3(CY_DMAC_IS_DATA_SIZE_VALID(config->dataSize));
77 CY_ASSERT_L3(CY_DMAC_IS_TYPE_VALID(config->descriptorType));
78
79 descriptor->ctl =
80 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_WAIT_FOR_DEACT, config->retrigger) |
81 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_INTR_TYPE, config->interruptType) |
82 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_OUT_TYPE, config->triggerOutType) |
83 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_TR_IN_TYPE, config->triggerInType) |
84 _BOOL2FLD(DMAC_CH_V2_DESCR_CTL_DATA_PREFETCH, config->dataPrefetch) |
85 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_SRC_TRANSFER_SIZE, config->srcTransferSize) |
86 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_DST_TRANSFER_SIZE, config->dstTransferSize) |
87 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_CH_DISABLE, config->channelState) |
88 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_DATA_SIZE, config->dataSize) |
89 _VAL2FLD(DMAC_CH_V2_DESCR_CTL_DESCR_TYPE, config->descriptorType);
90
91 descriptor->src = (uint32_t)config->srcAddress;
92
93 if(CY_DMAC_SCATTER_TRANSFER != config->descriptorType)
94 {
95 Cy_DMAC_Descriptor_SetDstAddress(descriptor, config->dstAddress);
96 }
97
98 if(CY_DMAC_SINGLE_TRANSFER != config->descriptorType)
99 {
100 Cy_DMAC_Descriptor_SetXloopDataCount(descriptor, config->xCount);
101 }
102
103 Cy_DMAC_Descriptor_SetNextDescriptor(descriptor, config->nextDescriptor);
104
105 if((CY_DMAC_1D_TRANSFER == config->descriptorType) ||
106 (CY_DMAC_2D_TRANSFER == config->descriptorType))
107 {
108 CY_ASSERT_L2(CY_DMAC_IS_LOOP_INCR_VALID(config->srcXincrement));
109 CY_ASSERT_L2(CY_DMAC_IS_LOOP_INCR_VALID(config->dstXincrement));
110
111 descriptor->xIncr = _VAL2FLD(DMAC_CH_V2_DESCR_X_INCR_SRC_X, config->srcXincrement) |
112 _VAL2FLD(DMAC_CH_V2_DESCR_X_INCR_DST_X, config->dstXincrement);
113 }
114
115 if(CY_DMAC_2D_TRANSFER == config->descriptorType)
116 {
117 Cy_DMAC_Descriptor_SetYloopDataCount(descriptor, config->yCount);
118
119 CY_ASSERT_L2(CY_DMAC_IS_LOOP_INCR_VALID(config->srcYincrement));
120 CY_ASSERT_L2(CY_DMAC_IS_LOOP_INCR_VALID(config->dstYincrement));
121
122 descriptor->yIncr = _VAL2FLD(DMAC_CH_V2_DESCR_Y_INCR_SRC_Y, config->srcYincrement) |
123 _VAL2FLD(DMAC_CH_V2_DESCR_Y_INCR_DST_Y, config->dstYincrement);
124 }
125
126 ret = CY_DMAC_SUCCESS;
127 }
128
129 return ret;
130 }
131
132
133 /*******************************************************************************
134 * Function Name: Cy_DMAC_Descriptor_DeInit
135 ****************************************************************************//**
136 *
137 * Clears the content of the specified descriptor.
138 *
139 * \param descriptor
140 * The descriptor structure instance.
141 *
142 * \funcusage
143 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_Deinit
144 *
145 *******************************************************************************/
Cy_DMAC_Descriptor_DeInit(cy_stc_dmac_descriptor_t * descriptor)146 void Cy_DMAC_Descriptor_DeInit(cy_stc_dmac_descriptor_t * descriptor)
147 {
148 descriptor->ctl = 0UL;
149 descriptor->src = 0UL;
150 descriptor->dst = 0UL;
151 descriptor->xSize = 0UL;
152 descriptor->xIncr = 0UL;
153 descriptor->ySize = 0UL;
154 descriptor->yIncr = 0UL;
155 descriptor->nextPtr = 0UL;
156 }
157
158
159 /*******************************************************************************
160 * Function Name: Cy_DMAC_Channel_Init
161 ****************************************************************************//**
162 *
163 * Initializes the DMAC channel with a descriptor and other parameters.
164 *
165 * \param base
166 * The pointer to the hardware DMAC block.
167 *
168 * \param channel
169 * A channel number.
170 *
171 * \param config
172 * The structure that has the initialization information for the
173 * channel.
174 *
175 * \return
176 * The status /ref cy_en_dmac_status_t.
177 *
178 * \funcusage
179 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Enable
180 *
181 *******************************************************************************/
Cy_DMAC_Channel_Init(DMAC_Type * base,uint32_t channel,cy_stc_dmac_channel_config_t const * config)182 cy_en_dmac_status_t Cy_DMAC_Channel_Init(DMAC_Type * base, uint32_t channel, cy_stc_dmac_channel_config_t const * config)
183 {
184 cy_en_dmac_status_t ret = CY_DMAC_BAD_PARAM;
185
186 if ((NULL != base) && (CY_DMAC_IS_CH_NR_VALID(channel)) && (NULL != config) && (NULL != config->descriptor))
187 {
188 CY_ASSERT_L2(CY_DMAC_IS_PRIORITY_VALID(config->priority));
189
190 /* Set the current descriptor */
191 DMAC_CH_CURR(base, channel) = (uint32_t)config->descriptor;
192
193 /* Set the channel configuration */
194 DMAC_CH_CTL(base, channel) = _VAL2FLD(DMAC_CH_V2_CTL_PRIO, config->priority) |
195 _BOOL2FLD(DMAC_CH_V2_CTL_ENABLED, config->enable) |
196 _BOOL2FLD(DMAC_CH_V2_CTL_B, config->bufferable);
197 ret = CY_DMAC_SUCCESS;
198 }
199
200 return (ret);
201 }
202
203
204 /*******************************************************************************
205 * Function Name: Cy_DMAC_Channel_DeInit
206 ****************************************************************************//**
207 *
208 * Clears the content of registers corresponding to the channel.
209 *
210 * \param base
211 * The pointer to the hardware DMAC block.
212 *
213 * \param channel
214 * A channel number.
215 *
216 * \funcusage
217 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Disable
218 *
219 *******************************************************************************/
Cy_DMAC_Channel_DeInit(DMAC_Type * base,uint32_t channel)220 void Cy_DMAC_Channel_DeInit(DMAC_Type * base, uint32_t channel)
221 {
222 CY_ASSERT_L1(CY_DMAC_IS_CH_NR_VALID(channel));
223
224 DMAC_CH_CTL(base, channel) = 0UL;
225 DMAC_CH_CURR(base, channel) = 0UL;
226 DMAC_CH_INTR_MASK(base, channel) = 0UL;
227 }
228
229
230 /*******************************************************************************
231 * Function Name: Cy_DMAC_Descriptor_GetXloopDataCount
232 ****************************************************************************//**
233 *
234 * Returns the number of data elements for the X loop of the specified
235 * descriptor (for all descriptor types except single transfer).
236 *
237 * Based on the descriptor type, the offset of the address for the xCount
238 * register may vary:
239 * For the scatter transfer descriptors type, this register is at offset 0x8.
240 * For all the rest supported descriptor types, this register is at offset 0xc.
241 *
242 * \param descriptor
243 * The descriptor structure instance.
244 *
245 * \return
246 * The number of data elements to transfer in the X loop.
247 * For scatter transfer descriptors the X loop count unit is
248 * an [address, data] pair (two words, or 8 bytes).
249 * For memory copy descriptors X loop count unit is one byte.
250 * For all the rest descriptors (except single transfer) the X loop count unit
251 * is specified by the data transfer size /ref cy_en_dmac_data_size_t.
252 *
253 * \funcusage
254 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_GetterFunctions
255 *
256 *******************************************************************************/
Cy_DMAC_Descriptor_GetXloopDataCount(cy_stc_dmac_descriptor_t const * descriptor)257 uint32_t Cy_DMAC_Descriptor_GetXloopDataCount(cy_stc_dmac_descriptor_t const * descriptor)
258 {
259 uint32_t retVal = 0UL;
260 cy_en_dmac_descriptor_type_t locDescriptorType = Cy_DMAC_Descriptor_GetDescriptorType(descriptor);
261
262 CY_ASSERT_L1(CY_DMAC_SINGLE_TRANSFER != locDescriptorType);
263
264 if (CY_DMAC_SCATTER_TRANSFER == locDescriptorType)
265 {
266 /* Convert the data count from the machine range (0-65535) into the user's range (1-32768). */
267 retVal = (_FLD2VAL(DMAC_CH_V2_DESCR_X_SIZE_X_COUNT, ((cy_stc_dmac_dscr_scatter_t const*)descriptor)->xSize) + 1UL) / 2UL;
268 }
269 else
270 {
271 /* Convert the data count from the machine range (0-65535) into the user's range (1-65536). */
272 retVal = _FLD2VAL(DMAC_CH_V2_DESCR_X_SIZE_X_COUNT, descriptor->xSize) + 1UL;
273 }
274
275 return (retVal);
276 }
277
278
279 /*******************************************************************************
280 * Function Name: Cy_DMAC_Descriptor_SetXloopDataCount
281 ****************************************************************************//**
282 *
283 * Sets the number of data elements to transfer in the X loop
284 * for the specified descriptor (for all descriptor types except single transfer).
285 *
286 * Based on the descriptor type, the offset of the address for the xCount
287 * register may vary:
288 * For the scatter transfer descriptors type, this register is at offset 0x8.
289 * For all the rest of the supported descriptor types, this register is at offset 0xc.
290 *
291 * \param descriptor
292 * The descriptor structure instance.
293 *
294 * \param xCount
295 * The number of data elements to transfer in the X loop.
296 * For scatter transfer descriptors the valid range is 1...32768.
297 * For all the rest of the descriptors (except single transfer), the valid range is 1...65536.
298 *
299 * \funcusage
300 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_SetterFunctions
301 *
302 *******************************************************************************/
Cy_DMAC_Descriptor_SetXloopDataCount(cy_stc_dmac_descriptor_t * descriptor,uint32_t xCount)303 void Cy_DMAC_Descriptor_SetXloopDataCount(cy_stc_dmac_descriptor_t * descriptor, uint32_t xCount)
304 {
305 cy_en_dmac_descriptor_type_t locDescriptorType = Cy_DMAC_Descriptor_GetDescriptorType(descriptor);
306
307 CY_ASSERT_L1(CY_DMAC_SINGLE_TRANSFER != locDescriptorType);
308
309 if (CY_DMAC_SCATTER_TRANSFER == locDescriptorType)
310 {
311 CY_ASSERT_L2(CY_DMAC_IS_SCATTER_COUNT_VALID(xCount));
312 /* Convert the data count from the user's range (1-32768) into the machine range (0-65535). */
313 ((cy_stc_dmac_dscr_scatter_t*)descriptor)->xSize = _VAL2FLD(DMAC_CH_V2_DESCR_X_SIZE_X_COUNT, (xCount * 2UL) - 1UL);
314 }
315 else
316 {
317 CY_ASSERT_L2(CY_DMAC_IS_LOOP_COUNT_VALID(xCount));
318 /* Convert the data count from the user's range (1-65536) into the machine range (0-65535). */
319 descriptor->xSize = _VAL2FLD(DMAC_CH_V2_DESCR_X_SIZE_X_COUNT, xCount - 1UL);
320 }
321 }
322
323
324 /*******************************************************************************
325 * Function Name: Cy_DMAC_Descriptor_SetNextDescriptor
326 ****************************************************************************//**
327 *
328 * Sets a Next Descriptor parameter for the specified descriptor.
329 *
330 * Based on the descriptor type, the offset of the address for the next descriptor
331 * register may vary:
332 * For the single and scatter transfer descriptors, this register is at offset 0x0c.
333 * For the memory copy descriptor type, this register is at offset 0x10.
334 * For the 1D-transfer descriptor type, this register is at offset 0x14.
335 * For the 2D-transfer descriptor type, this register is at offset 0x1c.
336 *
337 * \param descriptor
338 * The descriptor structure instance.
339 *
340 * \param nextDescriptor
341 * The pointer to the next descriptor.
342 * For CAT1C devices this pointer needs to point to 32 byte aligned structure.
343 *
344 * \funcusage
345 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_SetterFunctions
346 *
347 *******************************************************************************/
Cy_DMAC_Descriptor_SetNextDescriptor(cy_stc_dmac_descriptor_t * descriptor,cy_stc_dmac_descriptor_t const * nextDescriptor)348 void Cy_DMAC_Descriptor_SetNextDescriptor(cy_stc_dmac_descriptor_t * descriptor, cy_stc_dmac_descriptor_t const * nextDescriptor)
349 {
350 CY_ASSERT_L1(NULL != descriptor);
351
352 switch((cy_en_dmac_descriptor_type_t)_FLD2VAL(DMAC_CH_V2_DESCR_CTL_DESCR_TYPE, descriptor->ctl))
353 {
354 case CY_DMAC_SINGLE_TRANSFER:
355 case CY_DMAC_SCATTER_TRANSFER:
356 /* The next pointer is on the same offset for single and scatter descriptors */
357 ((cy_stc_dmac_dscr_single_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
358 break;
359
360 case CY_DMAC_MEMORY_COPY:
361 ((cy_stc_dmac_dscr_memcpy_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
362 break;
363
364 case CY_DMAC_1D_TRANSFER:
365 ((cy_stc_dmac_dscr_1d_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
366 break;
367
368 case CY_DMAC_2D_TRANSFER:
369 ((cy_stc_dmac_dscr_2d_t*)descriptor)->nextPtr = (uint32_t)nextDescriptor;
370 break;
371
372 default:
373 /* Unsupported type of descriptor */
374 break;
375 }
376 }
377
378
379 /*******************************************************************************
380 * Function Name: Cy_DMAC_Descriptor_GetNextDescriptor
381 ****************************************************************************//**
382 *
383 * Returns a next descriptor address of the specified descriptor.
384 *
385 * Based on the descriptor type, the offset of the address for the next descriptor
386 * register may vary:
387 * For the single and scatter transfer descriptors, this register is at offset 0x0c.
388 * For the memory copy descriptor type, this register is at offset 0x10.
389 * For the 1D-transfer descriptor type, this register is at offset 0x14.
390 * For the 2D-transfer descriptor type, this register is at offset 0x1c.
391 *
392 * \param descriptor
393 * The descriptor structure instance.
394 *
395 * \return
396 * The pointer to the next descriptor.
397 *
398 * \funcusage
399 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_GetterFunctions
400 *
401 *******************************************************************************/
Cy_DMAC_Descriptor_GetNextDescriptor(cy_stc_dmac_descriptor_t const * descriptor)402 cy_stc_dmac_descriptor_t * Cy_DMAC_Descriptor_GetNextDescriptor(cy_stc_dmac_descriptor_t const * descriptor)
403 {
404 uint32_t retVal = 0UL;
405
406 switch((cy_en_dmac_descriptor_type_t)_FLD2VAL(DMAC_CH_V2_DESCR_CTL_DESCR_TYPE, descriptor->ctl))
407 {
408 case CY_DMAC_SINGLE_TRANSFER:
409 case CY_DMAC_SCATTER_TRANSFER:
410 /* The next pointer is on the same offset for single and scatter descriptors */
411 retVal = ((cy_stc_dmac_dscr_single_t const*)descriptor)->nextPtr;
412 break;
413
414 case CY_DMAC_MEMORY_COPY:
415 retVal = ((cy_stc_dmac_dscr_memcpy_t const*)descriptor)->nextPtr;
416 break;
417
418 case CY_DMAC_1D_TRANSFER:
419 retVal = ((cy_stc_dmac_dscr_1d_t const*)descriptor)->nextPtr;
420 break;
421
422 case CY_DMAC_2D_TRANSFER:
423 retVal = ((cy_stc_dmac_dscr_2d_t const*)descriptor)->nextPtr;
424 break;
425
426 default:
427 /* An unsupported type of the descriptor */
428 break;
429 }
430
431 return ((cy_stc_dmac_descriptor_t*)retVal);
432 }
433
434
435 /*******************************************************************************
436 * Function Name: Cy_DMAC_Descriptor_SetDescriptorType
437 ****************************************************************************//**
438 *
439 * Sets the descriptor's type for the specified descriptor.
440 * Moves the next descriptor pointer and X data count values into the proper
441 * offset in accordance to the actual descriptor type.
442 *
443 * During the descriptor's type change, carefully set up the settings starting
444 * from dstAddress and all the rest below in the \ref cy_stc_dmac_descriptor_config_t
445 * structure. This is because the content of the descriptor registers might be
446 * lost/overridden by other descriptor settings due to the
447 * different registers structure for different descriptor types.
448 *
449 * \param descriptor
450 * The descriptor structure instance.
451 *
452 * \param descriptorType
453 * The descriptor type \ref cy_en_dmac_descriptor_type_t.
454 *
455 * \funcusage
456 * \snippet dmac/snippet/main.c snippet_Cy_DMAC_Descriptor_SetterFunctions
457 *
458 *******************************************************************************/
Cy_DMAC_Descriptor_SetDescriptorType(cy_stc_dmac_descriptor_t * descriptor,cy_en_dmac_descriptor_type_t descriptorType)459 void Cy_DMAC_Descriptor_SetDescriptorType(cy_stc_dmac_descriptor_t * descriptor, cy_en_dmac_descriptor_type_t descriptorType)
460 {
461 CY_ASSERT_L3(CY_DMAC_IS_TYPE_VALID(descriptorType));
462
463 if (descriptorType != Cy_DMAC_Descriptor_GetDescriptorType(descriptor)) /* Do not perform if the type is not changed */
464 {
465 /* Store the current nextDescriptor pointer. */
466 cy_stc_dmac_descriptor_t const *locNextDescriptor = Cy_DMAC_Descriptor_GetNextDescriptor(descriptor);
467 /* Store the current X data counter. */
468 uint32_t locXcount = Cy_DMAC_Descriptor_GetXloopDataCount(descriptor);
469 /* Change the descriptor type. */
470 CY_REG32_CLR_SET(descriptor->ctl, DMAC_CH_V2_DESCR_CTL_DESCR_TYPE, descriptorType);
471 /* Restore the current X data counter. */
472 Cy_DMAC_Descriptor_SetXloopDataCount(descriptor, locXcount);
473 /* Restore the nextDescriptor pointer into the proper place. */
474 Cy_DMAC_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor);
475 }
476 }
477
478 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
479 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 10.8')
480
481 #endif /* CY_IP_M4CPUSS_DMAC, CY_IP_MXAHBDMAC */
482
483 /* [] END OF FILE */
484