1 /***************************************************************************//**
2 * \file cy_usbfs_dev_drv_io_dma.c
3 * \version 2.20.2
4 *
5 * Provides data transfer API implementation of the USBFS driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if defined (CY_IP_MXUSBFS) && defined (CY_IP_MXPERI)
28 
29 #include <string.h>
30 #include "cy_usbfs_dev_drv_pvt.h"
31 
32 #if defined(__cplusplus)
33 extern "C" {
34 #endif
35 
36 /*******************************************************************************
37 *                        Internal Constants
38 *******************************************************************************/
39 
40 /* Invalid channel */
41 #define DMA_INVALID_CHANNEL     ((uint32_t) (-1))
42 
43 /* Arbiter interrupt sources for OUT and IN endpoints when mode is
44 * CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO.
45 */
46 #define IN_ENDPOINT_ARB_INTR_SOURCES    (USBFS_USBDEV_ARB_EP_IN_BUF_FULL_Msk | \
47                                          USBFS_USBDEV_ARB_EP_BUF_OVER_Msk    | \
48                                          USBFS_USBDEV_ARB_EP_BUF_UNDER_Msk   | \
49                                          USBFS_USBDEV_ARB_EP_ERR_Msk)
50 
51 #define OUT_ENDPOINT_ARB_INTR_SOURCES   (USBFS_USBDEV_ARB_EP_DMA_TERMIN_Msk | \
52                                          USBFS_USBDEV_ARB_EP_BUF_OVER_Msk   | \
53                                          USBFS_USBDEV_ARB_EP_BUF_UNDER_Msk  | \
54                                          USBFS_USBDEV_ARB_EP_ERR_Msk)
55 
56 /* DMA configuration defines */
57 #define DMA_XLOOP_INCREMENT    (1)
58 #define DMA_YLOOP_INCREMENT    (32)
59 #define DMA_NO_INCREMENT       (0)
60 
61 /* Timeout for dynamic reconfiguration */
62 #define DYN_RECONFIG_ONE_TICK   (1U)        /* 1 tick = 1 us */
63 #define DYN_RECONFIG_TIMEOUT    (25000UL)   /* (25000 * tick)us = 25 ms ( TDRQCMPLTND / 2 ) */
64 
65 /* Timeout for DMA read operation */
66 #define DMA_READ_REQUEST_ONE_TICK   (1U)      /* 1 tick = 1 us */
67 #define DMA_READ_REQUEST_TIMEOUT    (25000UL) /* (25000 * tick)us = 25 ms ( TDRQCMPLTND / 2 ) */
68 
69 #define DMA_WRITE_REQUEST_ONE_TICK   (1U)      /* 1 tick = 1 us */
70 #define DMA_WRITE_REQUEST_TIMEOUT    (25000UL) /* (25000 * tick)us = 25 ms ( TDRQCMPLTND / 2 ) */
71 
72 
73 /*******************************************************************************
74 *                        Internal Functions Prototypes
75 *******************************************************************************/
76 
77 static void DmaEndpointInit1D(cy_stc_dma_descriptor_t *descr,
78                               bool inDirection,
79                               cy_en_dma_data_size_t dataSize,
80                               volatile uint32_t const *dataReg);
81 
82 static void DmaEndpointInit2D(cy_stc_dma_descriptor_t *descr,
83                               bool inDirection,
84                               int32_t numElements);
85 
86 static void DmaEndpointSetLength(bool inDirection,
87                                  uint32_t size,
88                                  cy_stc_usbfs_dev_drv_endpoint_data_t *endpoint);
89 
90 
91 /*******************************************************************************
92 *                            Internal Constants
93 *******************************************************************************/
94 
95 /* Used for getting data in X loops */
96 #define DMA_DESCR_1D_CFG \
97 {                        \
98     /* .retrigger      = */ CY_DMA_RETRIG_IM,        \
99     /* .interruptType  = */ CY_DMA_DESCR,            \
100     /* .triggerOutType = */ CY_DMA_DESCR,            \
101     /* .channelState   = */ CY_DMA_CHANNEL_DISABLED, \
102     /* .triggerInType  = */ CY_DMA_DESCR,            \
103     /* .dataSize        = */ CY_DMA_BYTE,               \
104     /* .srcTransferSize = */ CY_DMA_TRANSFER_SIZE_WORD, \
105     /* .dstTransferSize = */ CY_DMA_TRANSFER_SIZE_WORD, \
106     /* .descriptorType  = */ CY_DMA_1D_TRANSFER,        \
107     /* .srcAddress     = */ NULL, \
108     /* .dstAddress     = */ NULL, \
109     /* .srcXincrement  = */ 0,    \
110     /* .dstXincrement  = */ 0,    \
111     /* .xCount         = */ 1UL,  \
112     /* .srcYincrement  = */ 0,    \
113     /* .dstYincrement  = */ 0,    \
114     /* .yCount         = */ 1UL,  \
115     /* .nextDescriptor = */ NULL, \
116 }
117 
118 /* Used for getting data in Y loops */
119 #define DMA_DESCR_2D_CFG \
120 {                        \
121     /* .retrigger      = */ CY_DMA_RETRIG_IM,       \
122     /* .interruptType  = */ CY_DMA_X_LOOP,          \
123     /* .triggerOutType = */ CY_DMA_X_LOOP,          \
124     /* .channelState   = */ CY_DMA_CHANNEL_ENABLED, \
125     /* .triggerInType  = */ CY_DMA_X_LOOP,          \
126     /* .dataSize        = */ CY_DMA_BYTE,               \
127     /* .srcTransferSize = */ CY_DMA_TRANSFER_SIZE_WORD, \
128     /* .dstTransferSize = */ CY_DMA_TRANSFER_SIZE_WORD, \
129     /* .descriptorType  = */ CY_DMA_2D_TRANSFER,        \
130     /* .srcAddress     = */ NULL, \
131     /* .dstAddress     = */ NULL, \
132     /* .srcXincrement  = */ 0,    \
133     /* .dstXincrement  = */ 0,    \
134     /* .xCount         = */ 1UL,  \
135     /* .srcYincrement  = */ 0,    \
136     /* .dstYincrement  = */ 0,    \
137     /* .yCount         = */ 1UL,  \
138     /* .nextDescriptor = */ NULL, \
139 }
140 
141 
142 /*******************************************************************************
143 * Function Name: DmaInit
144 ****************************************************************************//**
145 *
146 * Initializes all DMA channels used by the USBFS Device.
147 *
148 * \param config
149 * The pointer to the driver configuration structure \ref cy_stc_usbfs_dev_drv_config_t.
150 *
151 * \param context
152 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
153 * allocated by the user. The structure is used during the USBFS Device
154 * operation for internal configuration and data retention. The user must not
155 * modify anything in this structure.
156 *
157 * \return
158 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
159 *
160 *******************************************************************************/
DmaInit(cy_stc_usbfs_dev_drv_config_t const * config,cy_stc_usbfs_dev_drv_context_t * context)161 cy_en_usbfs_dev_drv_status_t DmaInit(cy_stc_usbfs_dev_drv_config_t const *config, cy_stc_usbfs_dev_drv_context_t *context)
162 {
163     cy_en_usbfs_dev_drv_status_t retStatus = CY_USBFS_DEV_DRV_DMA_CFG_FAILED;
164 
165     uint32_t endpoint;
166 
167     /* Configure DMA descriptors and channels for data endpoints */
168     for (endpoint = 0UL; endpoint < CY_USBFS_DEV_DRV_NUM_EPS_MAX; ++endpoint)
169     {
170         /* DMA configuration status for endpoint */
171         retStatus = CY_USBFS_DEV_DRV_DMA_CFG_FAILED;
172 
173         /* Get pointer to endpoint data */
174         cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
175 
176         if (config->dmaConfig[endpoint] != NULL)
177         {
178             cy_en_usbfs_dev_drv_status_t locStatus = CY_USBFS_DEV_DRV_DMA_CFG_FAILED;
179 
180             cy_stc_dma_channel_config_t chConfig;
181 
182             /* Descriptors configurations */
183             const cy_stc_dma_descriptor_config_t DmaDescr1DCfg = DMA_DESCR_1D_CFG;
184             const cy_stc_dma_descriptor_config_t DmaDescr2DCfg = DMA_DESCR_2D_CFG;
185 
186             /* Store DMA configuration required for operation */
187             endpointData->base   = config->dmaConfig[endpoint]->base;
188             endpointData->chNum  = config->dmaConfig[endpoint]->chNum;
189             endpointData->descr0 = config->dmaConfig[endpoint]->descr0;
190             endpointData->descr1 = config->dmaConfig[endpoint]->descr1;
191             endpointData->outTrigMux = config->dmaConfig[endpoint]->outTrigMux;
192             endpointData->copyData   = NULL;
193 
194             if (CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA == context->mode)
195             {
196                 if (NULL != endpointData->descr0)
197                 {
198                     /* Initialize DMA descriptor 0 for 1D operation.
199                     * Discard return because descriptor configuration (defined in driver) is valid.
200                     */
201                     (void) Cy_DMA_Descriptor_Init(endpointData->descr0, &DmaDescr1DCfg);
202 
203                     locStatus = CY_USBFS_DEV_DRV_SUCCESS;
204                 }
205             }
206             else
207             {
208                 if ((NULL != endpointData->descr0) && (NULL != endpointData->descr1))
209                 {
210                     /* Initialize DMA descriptor 0 for 2D operation.
211                     * Discard return because descriptor configuration (defined in driver) is valid.
212                     */
213                     (void) Cy_DMA_Descriptor_Init(endpointData->descr0, &DmaDescr2DCfg);
214 
215 
216                     /* Initialize DMA descriptor 0 for 1D operation.
217                     * Discard return because descriptor configuration (defined in driver) is valid.
218                     */
219                     (void)Cy_DMA_Descriptor_Init(endpointData->descr1, &DmaDescr1DCfg);
220 
221                     locStatus = CY_USBFS_DEV_DRV_SUCCESS;
222                 }
223             }
224 
225             /* Set DMA channel configuration */
226             chConfig.enable      = false;
227             chConfig.bufferable  = false;
228             chConfig.descriptor  = config->dmaConfig[endpoint]->descr0;
229             chConfig.preemptable = config->dmaConfig[endpoint]->preemptable;
230             chConfig.priority    = config->dmaConfig[endpoint]->priority;
231 
232             /* Initialize DMA channel */
233             if ((CY_DMA_SUCCESS != Cy_DMA_Channel_Init(endpointData->base, endpointData->chNum, &chConfig)) ||
234                 (CY_USBFS_DEV_DRV_SUCCESS != locStatus))
235             {
236                 break;
237             }
238 
239             /* Enable DMA block */
240             Cy_DMA_Enable(endpointData->base);
241         }
242         else
243         {
244             endpointData->chNum = DMA_INVALID_CHANNEL;
245         }
246 
247         /* Configuration complete successfully */
248         retStatus = CY_USBFS_DEV_DRV_SUCCESS;
249     }
250 
251     /* Disable all DMAs if any configuration failed */
252     if (CY_USBFS_DEV_DRV_SUCCESS != retStatus)
253     {
254         DmaDisable(context);
255     }
256 
257     return retStatus;
258 }
259 
260 
261 /*******************************************************************************
262 * Function Name: DmaDisable
263 ****************************************************************************//**
264 *
265 * Disables all DMA channels used by the USBFS Device.
266 * The channel state is not verified before being disabled.
267 *
268 * \param context
269 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
270 * allocated by the user. The structure is used during the USBFS Device
271 * operation for internal configuration and data retention. The user must not
272 * modify anything in this structure.
273 *
274 *******************************************************************************/
DmaDisable(cy_stc_usbfs_dev_drv_context_t * context)275 void DmaDisable(cy_stc_usbfs_dev_drv_context_t *context)
276 {
277     uint32_t endpoint;
278 
279     /* Disable DMA channels for data endpoints */
280     for (endpoint = 0UL; endpoint < CY_USBFS_DEV_DRV_NUM_EPS_MAX; ++endpoint)
281     {
282         /* Get pointer to endpoint data */
283         cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
284 
285         if (endpointData->chNum != DMA_INVALID_CHANNEL)
286         {
287             Cy_DMA_Channel_Disable(endpointData->base, endpointData->chNum);
288         }
289     }
290 }
291 
292 
293 /*******************************************************************************
294 * Function Name: DmaEndpointInit1D
295 ****************************************************************************//**
296 *
297 * Configures DMA 1D descriptor used in DMA modes.
298 *
299 * \param descr
300 * The pointer to the DMA descriptor.
301 *
302 * \param inDirection
303 * Endpoint direction associated with DMA descriptor.
304 *
305 * \param dataSize
306 * The DMA transfer data size \ref cy_en_dma_data_size_t.
307 *
308 * \param dataReg
309 * The pointer to the data endpoint data register.
310 *
311 *******************************************************************************/
DmaEndpointInit1D(cy_stc_dma_descriptor_t * descr,bool inDirection,cy_en_dma_data_size_t dataSize,volatile uint32_t const * dataReg)312 static void DmaEndpointInit1D(cy_stc_dma_descriptor_t *descr, bool inDirection,
313                               cy_en_dma_data_size_t dataSize, volatile uint32_t const *dataReg)
314 {
315     Cy_DMA_Descriptor_SetDataSize(descr, dataSize);
316 
317     if (inDirection)
318     {
319         Cy_DMA_Descriptor_SetSrcTransferSize(descr, CY_DMA_TRANSFER_SIZE_DATA);
320         Cy_DMA_Descriptor_SetDstTransferSize(descr, CY_DMA_TRANSFER_SIZE_WORD);
321 
322         Cy_DMA_Descriptor_SetXloopSrcIncrement(descr, DMA_XLOOP_INCREMENT);
323         Cy_DMA_Descriptor_SetXloopDstIncrement(descr, DMA_NO_INCREMENT);
324 
325         Cy_DMA_Descriptor_SetDstAddress(descr, (void const *) dataReg);
326     }
327     else
328     {
329         Cy_DMA_Descriptor_SetSrcTransferSize(descr, CY_DMA_TRANSFER_SIZE_WORD);
330         Cy_DMA_Descriptor_SetDstTransferSize(descr, CY_DMA_TRANSFER_SIZE_DATA);
331 
332         Cy_DMA_Descriptor_SetXloopSrcIncrement(descr, DMA_NO_INCREMENT);
333         Cy_DMA_Descriptor_SetXloopDstIncrement(descr, DMA_XLOOP_INCREMENT);
334 
335         Cy_DMA_Descriptor_SetSrcAddress(descr, (void const *) dataReg);
336     }
337 
338     /* Link descriptor to itself */
339     Cy_DMA_Descriptor_SetNextDescriptor(descr, descr);
340 }
341 
342 
343 /*******************************************************************************
344 * Function Name: DmaEndpointInit2D
345 ****************************************************************************//**
346 *
347 * Configures DMA 2D descriptor used in the DMA Automatic mode.
348 *
349 * \param descr
350 * The pointer to the DMA descriptor.
351 *
352 * \param inDirection
353 * Endpoint direction associated with DMA descriptor.
354 *
355 * \param numElements
356 * Number of elements to transfer.
357 *
358 *******************************************************************************/
DmaEndpointInit2D(cy_stc_dma_descriptor_t * descr,bool inDirection,int32_t numElements)359 static void DmaEndpointInit2D(cy_stc_dma_descriptor_t *descr, bool inDirection,
360                               int32_t numElements)
361 {
362     /* Descriptor 0 (2D): it transfers number of data elements (X loop count)
363     * and increments source/destination (depends on direction) by this amount
364     * (Y loop increment).
365     */
366     Cy_DMA_Descriptor_SetXloopDataCount(descr, (uint32_t) numElements);
367 
368     if (inDirection)
369     {
370         Cy_DMA_Descriptor_SetYloopSrcIncrement(descr, numElements);
371         Cy_DMA_Descriptor_SetYloopDstIncrement(descr, DMA_NO_INCREMENT);
372     }
373     else
374     {
375         Cy_DMA_Descriptor_SetYloopSrcIncrement(descr, DMA_NO_INCREMENT);
376         Cy_DMA_Descriptor_SetYloopDstIncrement(descr, numElements);
377     }
378 }
379 
380 
381 /*******************************************************************************
382 * Function Name: DmaEndpointSetLength
383 ****************************************************************************//**
384 *
385 * Completes DMA initialization for the OUT data endpoint.
386 * Applicable only when mode is \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO.
387 *
388 * \param inDirection
389 * Endpoint direction associated with DMA descriptor.
390 *
391 * \param size
392 * The number of bytes to load into endpoint.
393 * This value must be less than or equal to the endpoint maximum packet size.
394 *
395 * \param endpoint
396 * The pointer to the structure that stores endpoint information.
397 *
398 *******************************************************************************/
DmaEndpointSetLength(bool inDirection,uint32_t size,cy_stc_usbfs_dev_drv_endpoint_data_t * endpoint)399 static void DmaEndpointSetLength(bool inDirection, uint32_t size,
400                                  cy_stc_usbfs_dev_drv_endpoint_data_t *endpoint)
401 {
402     uint8_t *buf = endpoint->buffer;
403 
404     /*
405     * Descriptor 0: get number of Y loops. It transfers data in multiples of 32 bytes.
406     * Descriptor 1: get number of X loops. It transfers data what was left 1-31 bytes.
407     */
408     uint32_t numYloops = size / (uint32_t) DMA_YLOOP_INCREMENT;
409     uint32_t numXloops = size % (uint32_t) DMA_YLOOP_INCREMENT;
410 
411     /* Configure */
412     if (inDirection)
413     {
414         endpoint->startBuf = (uint16_t) size;  /* Store DMA transfer size */
415         Cy_DMA_Descriptor_SetSrcAddress(endpoint->descr0, buf);
416         Cy_DMA_Descriptor_SetSrcAddress(endpoint->descr1, &buf[size - numXloops]);
417     }
418     else
419     {
420         endpoint->startBuf = (numYloops > 0U) ? 1U : 0U; /* Store 1st DMA descriptor to execute */
421         Cy_DMA_Descriptor_SetDstAddress(endpoint->descr0, buf);
422         Cy_DMA_Descriptor_SetDstAddress(endpoint->descr1, &buf[size - numXloops]);
423     }
424 
425     /* Configure loop length */
426     if (numYloops > 0UL)
427     {
428         Cy_DMA_Descriptor_SetYloopDataCount(endpoint->descr0, numYloops);
429     }
430 
431     if (numXloops > 0UL)
432     {
433         Cy_DMA_Descriptor_SetXloopDataCount(endpoint->descr1, numXloops);
434     }
435 
436     /* Chain descriptors to operate */
437     if (numYloops == 0UL)
438     {
439         /* (Size < 32): only Descriptor 1 transfers data */
440         Cy_DMA_Descriptor_SetNextDescriptor(endpoint->descr1, endpoint->descr1);
441     }
442     else if (numXloops == 0UL)
443     {
444         /* Size multiple of 32: only Descriptor 0 transfers data */
445         Cy_DMA_Descriptor_SetNextDescriptor(endpoint->descr0, endpoint->descr0);
446     }
447     else
448     {
449         /* (Size > 32): both Descriptor 0 and 1 transfer data */
450         Cy_DMA_Descriptor_SetNextDescriptor(endpoint->descr0, endpoint->descr1);
451         Cy_DMA_Descriptor_SetNextDescriptor(endpoint->descr1, endpoint->descr0);
452     }
453 
454     /* Keep channel enabled after execution of Descriptor 0 to execute Descriptor 1 */
455     Cy_DMA_Descriptor_SetChannelState(endpoint->descr0,
456                                         ((numYloops > 0UL) && (numXloops > 0UL)) ?
457                                             CY_DMA_CHANNEL_ENABLED : CY_DMA_CHANNEL_DISABLED);
458 
459     /* Start execution from Descriptor 0 (length >= 32) or Descriptor 1 (length < 32) */
460     Cy_DMA_Channel_SetDescriptor(endpoint->base, endpoint->chNum,
461                                     ((numYloops > 0UL) ? endpoint->descr0 : endpoint->descr1));
462 
463     /* Configuration complete: enable channel */
464     Cy_DMA_Channel_Enable(endpoint->base, endpoint->chNum);
465 }
466 
467 
468 /*******************************************************************************
469 * Function Name: DmaOutEndpointRestore
470 ****************************************************************************//**
471 *
472 * Restores the DMA channel after transfer is completed for the the OUT data endpoint.
473 * Applicable only when mode is \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO.
474 *
475 * \param endpoint
476 * The pointer to the structure that stores endpoint information.
477 *
478 *******************************************************************************/
DmaOutEndpointRestore(cy_stc_usbfs_dev_drv_endpoint_data_t * endpoint)479 void DmaOutEndpointRestore(cy_stc_usbfs_dev_drv_endpoint_data_t *endpoint)
480 {
481     /* Number of clocks for DMA completion pulse */
482     const uint32_t CY_USBFS_DEV_DRV_TRIG_CYCLES = 2UL;
483 
484     /* Define which descriptor is 1st in the chain */
485     bool setDescr0 = (0U != endpoint->startBuf);
486 
487     /* Channel disable aborts on-going transfer */
488     Cy_DMA_Channel_Disable(endpoint->base, endpoint->chNum);
489 
490     /* Send pulse to UBSFS IP to indicate end of DMA transfer */
491     (void) Cy_TrigMux_SwTrigger(endpoint->outTrigMux, CY_USBFS_DEV_DRV_TRIG_CYCLES);
492 
493     /* Set 1st DMA descriptor for the following transfer */
494     Cy_DMA_Channel_SetDescriptor(endpoint->base, endpoint->chNum,
495                                                 (setDescr0 ? endpoint->descr0 : endpoint->descr1));
496 
497     Cy_DMA_Channel_Enable(endpoint->base, endpoint->chNum);
498 }
499 
500 
501 /*******************************************************************************
502 * Function Name: DmaEndpointInit
503 ****************************************************************************//**
504 *
505 * Initializes DMA descriptor for a certain data endpoint.
506 *
507 * \param base
508 * The pointer to the USBFS instance.
509 *
510 * \param mode
511 *
512 * \param useReg16
513 * Defines which endpoint registers to use: 8-bits or 16-bits.
514 *
515 * \param endpointData
516 * The pointer to the endpoint data structure.
517 *
518 * \return
519 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
520 *
521 *******************************************************************************/
DmaEndpointInit(USBFS_Type * base,cy_en_usbfs_dev_drv_ep_management_mode_t mode,bool useReg16,cy_stc_usbfs_dev_drv_endpoint_data_t * endpointData)522 cy_en_usbfs_dev_drv_status_t DmaEndpointInit(USBFS_Type *base,
523                                              cy_en_usbfs_dev_drv_ep_management_mode_t mode,
524                                              bool useReg16,
525                                              cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData)
526 {
527     cy_en_dma_data_size_t regSize;
528     int32_t numElements;
529     uint32_t volatile *dataReg;
530 
531     /* Get direction and endpoint number */
532     bool inDirection  = IS_EP_DIR_IN(endpointData->address);
533     uint32_t endpoint = EPADDR2PHY(endpointData->address);
534 
535     if (DMA_INVALID_CHANNEL == endpointData->chNum)
536     {
537         return CY_USBFS_DEV_DRV_DMA_CFG_FAILED;
538     }
539 
540     /* Set configuration variables depending on access type */
541     if (useReg16)
542     {
543         dataReg     = Cy_USBFS_Dev_Drv_GetDataReg16Addr(base, endpoint);
544         regSize     = CY_DMA_HALFWORD;
545         numElements = (DMA_YLOOP_INCREMENT / 2);
546     }
547     else
548     {
549         dataReg     = Cy_USBFS_Dev_Drv_GetDataRegAddr(base, endpoint);
550         regSize     = CY_DMA_BYTE;
551         numElements = DMA_YLOOP_INCREMENT;
552     }
553 
554     /* Disable channel before configuration */
555     Cy_DMA_Channel_Disable(endpointData->base, endpointData->chNum);
556 
557     /* Configure Descriptor 0 for 1D operation */
558     DmaEndpointInit1D(endpointData->descr0, inDirection, regSize, dataReg);
559 
560     if (CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO == mode)
561     {
562         /* Configure Descriptor 0 for 2D operation */
563         DmaEndpointInit2D(endpointData->descr0, inDirection, numElements);
564 
565         /* Configure Descriptor 1 for 1D operation */
566         DmaEndpointInit1D(endpointData->descr1, inDirection, regSize, dataReg);
567 
568         /* Configure descriptors to access buffer */
569         DmaEndpointSetLength(inDirection, (uint32_t) endpointData->bufferSize, endpointData);
570     }
571 
572     return CY_USBFS_DEV_DRV_SUCCESS;
573 }
574 
575 
576 /*******************************************************************************
577 * Function Name: DynamicEndpointReConfiguration
578 ****************************************************************************//**
579 *
580 * Changes endpoint direction (IN -> OUT or OUT -> IN).
581 * This function is also used to flush IN or OUT endpoint buffer.
582 * Applicable only when mode is \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO.
583 *
584 * \param base
585 * The pointer to the USBFS instance.
586 *
587 * \param inDirection
588 * True - endpoint direction is IN; False - endpoint direction is OUT.
589 *
590 * \param endpoint
591 * The data endpoint number.
592 *
593 * \return
594 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
595 *
596 *******************************************************************************/
DynamicEndpointReConfiguration(USBFS_Type * base,bool inDirection,uint32_t endpoint)597 cy_en_usbfs_dev_drv_status_t DynamicEndpointReConfiguration(USBFS_Type *base,
598                                                             bool        inDirection,
599                                                             uint32_t    endpoint)
600 {
601     cy_en_usbfs_dev_drv_status_t retStatus = CY_USBFS_DEV_DRV_EP_DYN_RECONFIG_TIMEOUT;
602 
603     uint32_t timeout = DYN_RECONFIG_TIMEOUT;
604 
605     /* Only enabled endpoint can be re-configured */
606     if (0U == (USBFS_DEV_EP_ACTIVE(base) & EP2MASK(endpont)))
607     {
608         return CY_USBFS_DEV_DRV_BUF_ALLOC_FAILED;
609     }
610 
611     /* Request reconfiguration for endpoint */
612     USBFS_DEV_DYN_RECONFIG(base) = (USBFS_USBDEV_DYN_RECONFIG_EN_Msk |
613                                     _VAL2FLD(USBFS_USBDEV_DYN_RECONFIG_EPNO, endpoint));
614 
615     /* Cypress ID#295549: execute dummy read */
616     (void) USBFS_DEV_DYN_RECONFIG(base);
617 
618     /* Wait for dynamic re-configuration completion */
619     while ((0U == (USBFS_DEV_DYN_RECONFIG(base) & USBFS_USBDEV_DYN_RECONFIG_RDY_STS_Msk)) &&
620            (timeout > 0U))
621     {
622         Cy_SysLib_DelayUs(DYN_RECONFIG_ONE_TICK);
623         --timeout;
624     }
625 
626     /* Verify operation result */
627     if (timeout > 0U)
628     {
629         Cy_USBFS_Dev_Drv_SetEpType(base, inDirection, endpoint);
630         retStatus = CY_USBFS_DEV_DRV_SUCCESS;
631     }
632 
633     /* Complete endpoint reconfiguration: clear request */
634     USBFS_DEV_DYN_RECONFIG(base) &= ~USBFS_USBDEV_DYN_RECONFIG_EN_Msk;
635     (void) USBFS_DEV_DYN_RECONFIG(base);
636 
637     /* Clear register for next re-configuration */
638     USBFS_DEV_DYN_RECONFIG(base) = 0U;
639 
640     return retStatus;
641 }
642 
643 
644 /*******************************************************************************
645 * Function Name: AddEndpointRamBuffer
646 ****************************************************************************//**
647 *
648 * Implements \ref Cy_USBFS_Dev_Drv_AddEndpoint for
649 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO mode.
650 *
651 * \param base
652 * The pointer to the USBFS instance.
653 *
654 * \param config
655 * The pointer to data endpoint configuration \ref cy_stc_usb_dev_ep_config_t.
656 *
657 * \param context
658 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
659 * allocated by the user. The structure is used during the USBFS Device
660 * operation for internal configuration and data retention. The user must not
661 * modify anything in this structure.
662 *
663 * \return
664 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
665 *
666 *******************************************************************************/
AddEndpointRamBuffer(USBFS_Type * base,cy_stc_usb_dev_ep_config_t const * config,cy_stc_usbfs_dev_drv_context_t * context)667 cy_en_usbfs_dev_drv_status_t AddEndpointRamBuffer(USBFS_Type *base,
668                                                   cy_stc_usb_dev_ep_config_t const *config,
669                                                   cy_stc_usbfs_dev_drv_context_t   *context)
670 {
671     cy_en_usbfs_dev_drv_status_t retStatus = CY_USBFS_DEV_DRV_BAD_PARAM;
672 
673     uint32_t endpoint = EPADDR2PHY(config->endpointAddr);
674 
675     /* Get pointer to endpoint data */
676     cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
677 
678     /* Get buffer for endpoint using buffer allocated by the user */
679     if (config->allocBuffer)
680     {
681         uint32_t startBufIdx;
682 
683         /* Configure active endpoint */
684         context->activeEpMask    |= (uint8_t) EP2MASK(endpont);
685         USBFS_DEV_EP_ACTIVE(base) = context->activeEpMask;
686 
687         /* Allocate buffer for endpoint */
688         retStatus = GetEndpointBuffer((uint32_t) config->bufferSize, &startBufIdx, context);
689         if (CY_USBFS_DEV_DRV_SUCCESS != retStatus)
690         {
691             return retStatus;
692         }
693 
694         /* Store pointer to buffer for this endpoint */
695         endpointData->buffer = &context->epSharedBuf[startBufIdx];
696     }
697 
698     /* Enable endpoint for operation */
699     if (config->enableEndpoint)
700     {
701         bool inDirection = IS_EP_DIR_IN(config->endpointAddr);
702 
703         /* Clear variables related to endpoint */
704         endpointData->state   = CY_USB_DEV_EP_IDLE;
705         endpointData->address = config->endpointAddr;
706         endpointData->toggle  = 0U;
707         endpointData->bufferSize = config->maxPacketSize;
708         endpointData->sieMode    = GetEndpointActiveMode(inDirection, config->attributes);
709         endpointData->isPending  = false;
710 
711         /* Set arbiter configuration (clears DMA requests) */
712         Cy_USBFS_Dev_Drv_SetArbEpConfig(base, endpoint, (USBFS_USBDEV_ARB_EP1_CFG_CRC_BYPASS_Msk |
713                                                          USBFS_USBDEV_ARB_EP1_CFG_RESET_PTR_Msk));
714 
715         /* Performs dynamic reconfiguration to make sure that the DMA has completed the data transfer.
716         * Also it flushes endpoint pre-fetch buffer (useful for IN endpoints).
717         */
718         retStatus = DynamicEndpointReConfiguration(base, inDirection, endpoint);
719         if (CY_USBFS_DEV_DRV_SUCCESS != retStatus)
720         {
721             return retStatus;
722         }
723 
724         /* Configure DMA for endpoint */
725         retStatus = DmaEndpointInit(base, context->mode, context->useReg16, endpointData);
726         if (CY_USBFS_DEV_DRV_SUCCESS != retStatus)
727         {
728             return retStatus;
729         }
730 
731         /* Enable Arbiter interrupt sources for endpoint */
732         Cy_USBFS_Dev_Drv_SetArbEpInterruptMask(base, endpoint,(inDirection ?
733                                                              IN_ENDPOINT_ARB_INTR_SOURCES :
734                                                              OUT_ENDPOINT_ARB_INTR_SOURCES));
735 
736         /* Enable SIE and arbiter interrupt for endpoint */
737         Cy_USBFS_Dev_Drv_EnableSieEpInterrupt(base, endpoint);
738         Cy_USBFS_Dev_Drv_EnableArbEpInterrupt(base, endpoint);
739 
740         /* Set SIE mode to respond to host */
741         Cy_USBFS_Dev_Drv_SetSieEpMode(base, endpoint, GetEndpointInactiveMode((uint32_t) endpointData->sieMode));
742     }
743 
744     return retStatus;
745 }
746 
747 
748 /*******************************************************************************
749 * Function Name: RestoreEndpointRamBuffer
750 ****************************************************************************//**
751 *
752 * Restores endpoint active configuration for
753 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO mode.
754 *
755 * \param base
756 * The pointer to the USBFS instance.
757 *
758 * \param endpointData
759 * The pointer to the endpoint data structure.
760 *
761 *******************************************************************************/
RestoreEndpointRamBuffer(USBFS_Type * base,cy_stc_usbfs_dev_drv_endpoint_data_t * endpointData)762 void RestoreEndpointRamBuffer(USBFS_Type *base,
763                               cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData)
764 {
765     bool inDirection  = IS_EP_DIR_IN(endpointData->address);
766     uint32_t endpoint = EPADDR2PHY(endpointData->address);
767 
768     /* Clear state */
769     endpointData->state = CY_USB_DEV_EP_IDLE;
770 
771     /* Configure active endpoint */
772     USBFS_DEV_EP_ACTIVE(base) |= EP2MASK(endpont);
773 
774     /* Configure endpoint type: OUT - 1, IN - 0 */
775     Cy_USBFS_Dev_Drv_SetEpType(base, inDirection, endpoint);
776 
777     /* Enable Arbiter interrupt sources for endpoint */
778     Cy_USBFS_Dev_Drv_SetArbEpInterruptMask(base, endpoint, (inDirection ?
779                                                             IN_ENDPOINT_ARB_INTR_SOURCES :
780                                                             OUT_ENDPOINT_ARB_INTR_SOURCES));
781 
782     /* Enable SIE and arbiter interrupt for endpoint */
783     Cy_USBFS_Dev_Drv_EnableSieEpInterrupt(base, endpoint);
784     Cy_USBFS_Dev_Drv_EnableArbEpInterrupt(base, endpoint);
785 
786     if (false == inDirection)
787     {
788         /* OUT Endpoint: enable DMA channel endpoint ready for operation.
789         * IN Endpoint: keep disabled, it is enabled in LoadInEndpointDmaAuto.
790         */
791         Cy_DMA_Channel_Enable(endpointData->base, endpointData->chNum);
792     }
793 
794     /* Sets an arbiter configuration */
795     Cy_USBFS_Dev_Drv_SetArbEpConfig(base, endpoint, (USBFS_USBDEV_ARB_EP1_CFG_CRC_BYPASS_Msk |
796                                                      USBFS_USBDEV_ARB_EP1_CFG_RESET_PTR_Msk));
797 
798     /* Set SIE mode to respond to host */
799     Cy_USBFS_Dev_Drv_SetSieEpMode(base, endpoint, GetEndpointInactiveMode((uint32_t) endpointData->sieMode));
800 }
801 
802 
803 /*******************************************************************************
804 * Function Name: LoadInEndpointDma
805 ****************************************************************************//**
806 *
807 * Implements \ref Cy_USBFS_Dev_Drv_LoadInEndpoint for
808 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA mode.
809 *
810 * \param base
811 * The pointer to the USBFS instance.
812 *
813 * \param endpoint
814 * The IN data endpoint number.
815 *
816 * \param buffer
817 * The pointer to the buffer containing data bytes to load.
818 *
819 * \param size
820 * The number of bytes to load into the endpoint.
821 * This value must be less than or equal to the endpoint maximum packet size.
822 *
823 * \param context
824 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
825 * allocated by the user. The structure is used during the USBFS Device
826 * operation for internal configuration and data retention. The user must not
827 * modify anything in this structure.
828 *
829 * \return
830 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
831 *
832 *******************************************************************************/
LoadInEndpointDma(USBFS_Type * base,uint32_t endpoint,uint8_t const * buffer,uint32_t size,cy_stc_usbfs_dev_drv_context_t * context)833 cy_en_usbfs_dev_drv_status_t LoadInEndpointDma(USBFS_Type    *base,
834                                                uint32_t      endpoint,
835                                                uint8_t const *buffer,
836                                                uint32_t      size,
837                                                cy_stc_usbfs_dev_drv_context_t *context)
838 {
839     cy_en_usbfs_dev_drv_status_t retStatus = CY_USBFS_DEV_DRV_EP_DMA_WRITE_TIMEOUT;
840 
841     /* Get pointer to endpoint data */
842     cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
843 
844     /* Request to load more bytes than endpoint buffer */
845     if (size > endpointData->bufferSize)
846     {
847         return CY_USBFS_DEV_DRV_BAD_PARAM;
848     }
849 
850     /* Clears the abort mask for the endpoint (there is no transfer during abort) */
851     context->epAbortMask &= (uint8_t) ~EP2MASK(endpoint);
852 
853     /* Set count and data toggle */
854     Cy_USBFS_Dev_Drv_SetSieEpCount(base, endpoint, size, (uint32_t) endpointData->toggle);
855 
856     if (0U == size)
857     {
858         /* Endpoint pending: Waits for the host read data after exiting this function */
859         endpointData->state = CY_USB_DEV_EP_PENDING;
860 
861         /* Arm endpoint: Host is allowed to read data */
862         Cy_USBFS_Dev_Drv_SetSieEpMode(base, endpoint, (uint32_t) endpointData->sieMode);
863 
864         retStatus = CY_USBFS_DEV_DRV_SUCCESS;
865     }
866     else
867     {
868         /* Channel is disabled after initialization or descriptor completion  */
869 
870         uint32_t timeout = DMA_WRITE_REQUEST_TIMEOUT;
871 
872         /* Get number of data elements to transfer */
873         size = context->useReg16 ? GET_SIZE16(size) : size;
874 
875         /* 1D descriptor: configure source address and length */
876         Cy_DMA_Descriptor_SetSrcAddress    (endpointData->descr0, (const void*) buffer);
877         Cy_DMA_Descriptor_SetXloopDataCount(endpointData->descr0, size);
878 
879         /* Enable DMA channel: configuration complete */
880         Cy_DMA_Channel_Enable(endpointData->base, endpointData->chNum);
881 
882         /* Generate DMA request: the endpoint will be armed when the DMA is
883         * finished in the Arbiter interrupt
884         */
885         Cy_USBFS_Dev_Drv_TriggerArbCfgEpDmaReq(base, endpoint);
886 
887         /* Waits until DMA completes the write operation. The current endpoint state is
888         * idle or completed and DMA completion interrupt changes state to pending
889         * (endpoint waits for the host read data).
890         */
891         while ((CY_USB_DEV_EP_PENDING != endpointData->state) &&
892                (timeout > 0U))
893         {
894             Cy_SysLib_DelayUs(DMA_WRITE_REQUEST_ONE_TICK);
895             --timeout;
896         }
897 
898         /* Check timeout */
899         if (timeout > 0U)
900         {
901             retStatus = CY_USBFS_DEV_DRV_SUCCESS;
902         }
903     }
904 
905     return retStatus;
906 }
907 
908 
909 /*******************************************************************************
910 * Function Name: ReadOutEndpointDma
911 ****************************************************************************//**
912 *
913 * Implements \ref Cy_USBFS_Dev_Drv_ReadOutEndpoint for
914 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA mode.
915 *
916 * \param base
917 * The pointer to the USBFS instance.
918 *
919 * \param endpoint
920 * The OUT data endpoint number.
921 *
922 * \param buffer
923 * Pointer to buffer that stores data that was read.
924 *
925 * \param size
926 * The number of bytes to read from endpoint.
927 * This value must be less than or equal to the endpoint maximum packet size.
928 *
929 * \param actSize
930 * The number of bytes that were actually read.
931 *
932 * \param context
933 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
934 * allocated by the user. The structure is used during the USBFS Device
935 * operation for internal configuration and data retention. The user must not
936 * modify anything in this structure.
937 *
938 * \return
939 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
940 *
941 *******************************************************************************/
ReadOutEndpointDma(USBFS_Type * base,uint32_t endpoint,uint8_t * buffer,uint32_t size,uint32_t * actSize,cy_stc_usbfs_dev_drv_context_t * context)942 cy_en_usbfs_dev_drv_status_t ReadOutEndpointDma(USBFS_Type *base,
943                                                 uint32_t   endpoint,
944                                                 uint8_t    *buffer,
945                                                 uint32_t   size,
946                                                 uint32_t   *actSize,
947                                                 cy_stc_usbfs_dev_drv_context_t *context)
948 {
949     cy_en_usbfs_dev_drv_status_t retStatus = CY_USBFS_DEV_DRV_EP_DMA_READ_TIMEOUT;
950 
951     /* Get pointer to endpoint data */
952     cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
953 
954     uint32_t timeout = DMA_READ_REQUEST_TIMEOUT;
955 
956     /* Get number of received bytes */
957     uint32_t numToCopy = Cy_USBFS_Dev_Drv_GetSieEpCount(base, endpoint);
958     uint32_t actCopied = numToCopy;
959 
960     /* Initialize actual number of copied bytes */
961     *actSize = 0U;
962 
963     /* Endpoint received more bytes than provided buffer */
964     if (numToCopy > size)
965     {
966         return CY_USBFS_DEV_DRV_BAD_PARAM;
967     }
968 
969     /* Nothing to copy; return success */
970     if (0U == numToCopy)
971     {
972         return CY_USBFS_DEV_DRV_SUCCESS;
973     }
974 
975     /* Channel is disabled after initialization or descriptor completion  */
976 
977     /* Get number of data elements to transfer */
978     numToCopy = context->useReg16 ? GET_SIZE16(numToCopy) : numToCopy;
979 
980     /* 1D descriptor: configure destination address and length */
981     Cy_DMA_Descriptor_SetDstAddress    (endpointData->descr0, buffer);
982     Cy_DMA_Descriptor_SetXloopDataCount(endpointData->descr0, numToCopy);
983 
984     /* Enable DMA channel: configuration complete */
985     Cy_DMA_Channel_Enable(endpointData->base, endpointData->chNum);
986 
987     /* The current endpoint state is completed, changes the state to pending to
988     * track DMA read completion.
989     */
990     endpointData->state = CY_USB_DEV_EP_PENDING;
991 
992     /* Generate DMA request to read data from hardware buffer */
993     Cy_USBFS_Dev_Drv_TriggerArbCfgEpDmaReq(base, endpoint);
994 
995     /* Waits until DMA completes the read operation */
996     while ((CY_USB_DEV_EP_COMPLETED != endpointData->state) &&
997            (timeout > 0U))
998     {
999         Cy_SysLib_DelayUs(DMA_READ_REQUEST_ONE_TICK);
1000         --timeout;
1001     }
1002 
1003     /* Check timeout */
1004     if (timeout > 0U)
1005     {
1006         /* Update number of copied bytes */
1007         *actSize = actCopied;
1008         retStatus = CY_USBFS_DEV_DRV_SUCCESS;
1009     }
1010 
1011     return retStatus;
1012 }
1013 
1014 
1015 /*******************************************************************************
1016 * Function Name: LoadInEndpointDmaAuto
1017 ****************************************************************************//**
1018 *
1019 * Implements \ref Cy_USBFS_Dev_Drv_LoadInEndpoint for
1020 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO mode.
1021 *
1022 * \param base
1023 * The pointer to the USBFS instance.
1024 *
1025 * \param endpoint
1026 * The IN data endpoint number.
1027 *
1028 * \param buffer
1029 * The pointer to the buffer containing data bytes to load.
1030 *
1031 * \param size
1032 * The number of bytes to load into endpoint.
1033 * This value must be less than or equal to the endpoint maximum packet size.
1034 *
1035 * \param context
1036 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
1037 * allocated by the user. The structure is used during the USBFS Device
1038 * operation for internal configuration and data retention. The user must not
1039 * modify anything in this structure.
1040 *
1041 * \return
1042 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
1043 *
1044 *******************************************************************************/
LoadInEndpointDmaAuto(USBFS_Type * base,uint32_t endpoint,uint8_t const * buffer,uint32_t size,cy_stc_usbfs_dev_drv_context_t * context)1045 cy_en_usbfs_dev_drv_status_t LoadInEndpointDmaAuto(USBFS_Type    *base,
1046                                                    uint32_t      endpoint,
1047                                                    uint8_t const *buffer,
1048                                                    uint32_t      size,
1049                                                    cy_stc_usbfs_dev_drv_context_t *context)
1050 {
1051     /* Get pointer to endpoint data */
1052     cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
1053 
1054     /* Request to load more bytes than endpoint buffer */
1055     if (size > endpointData->bufferSize)
1056     {
1057         return CY_USBFS_DEV_DRV_BAD_PARAM;
1058     }
1059 
1060     /* Clears the abort mask for the endpoint (there is no transfer during abort) */
1061     context->epAbortMask &= (uint8_t) ~EP2MASK(endpoint);
1062 
1063     /* Endpoint pending: Waits for the host read data after exiting this function */
1064     endpointData->state = CY_USB_DEV_EP_PENDING;
1065 
1066     /* Set count and data toggle */
1067     Cy_USBFS_Dev_Drv_SetSieEpCount(base, endpoint, size, (uint32_t) endpointData->toggle);
1068 
1069     if (0U == size)
1070     {
1071         /* Arm endpoint: Host is allowed to read data */
1072         Cy_USBFS_Dev_Drv_SetSieEpMode(base, endpoint, (uint32_t) endpointData->sieMode);
1073     }
1074     else
1075     {
1076         /* Copy data from user buffer to internal endpoint buffer */
1077         if (NULL != endpointData->copyData)
1078         {
1079             (void) endpointData->copyData(endpointData->buffer, buffer, size);
1080         }
1081         else
1082         {
1083             (void) memcpy(endpointData->buffer, buffer, size);
1084         }
1085 
1086         /* Configure transfer length */
1087         if (size != endpointData->startBuf)
1088         {
1089             /* Update transfer length, endpoint startBuf and enables DMA */
1090             DmaEndpointSetLength(true, size, &context->epPool[endpoint]);
1091         }
1092         else
1093         {
1094             /* Reset DMA channel indexes, they keep value after Resume or Abort */
1095             Cy_DMA_Channel_SetDescriptor(endpointData->base, endpointData->chNum,
1096                                             (endpointData->startBuf >= (uint32_t) DMA_YLOOP_INCREMENT) ?
1097                                                 endpointData->descr0 : endpointData->descr1);
1098 
1099             /* Enable channel: configuration complete */
1100             Cy_DMA_Channel_Enable(endpointData->base, endpointData->chNum);
1101         }
1102 
1103         /* Generate DMA request to pre-load data into endpoint buffer */
1104         Cy_USBFS_Dev_Drv_SetArbCfgEpInReady(base, endpoint);
1105 
1106         /* IN endpoint will be armed in the Arbiter interrupt (source: IN_BUF_FULL)
1107         * after DMA pre-load data buffer.
1108         */
1109     }
1110 
1111     return CY_USBFS_DEV_DRV_SUCCESS;
1112 }
1113 
1114 
1115 /*******************************************************************************
1116 * Function Name: ReadOutEndpointDmaAuto
1117 ****************************************************************************//**
1118 *
1119 * Implements \ref Cy_USBFS_Dev_Drv_ReadOutEndpoint for
1120 * \ref CY_USBFS_DEV_DRV_EP_MANAGEMENT_DMA_AUTO mode.
1121 *
1122 * \param base
1123 * The pointer to the USBFS instance.
1124 *
1125 * \param endpoint
1126 * The OUT data endpoint number.
1127 *
1128 * \param buffer
1129 * Pointer to buffer that stores data that was read.
1130 *
1131 * \param size
1132 * The number of bytes to read from the endpoint.
1133 * This value must be less than or equal to the endpoint maximum packet size.
1134 *
1135 * \param actSize
1136 * The number of bytes which were actually read.
1137 *
1138 * \param context
1139 * The pointer to the context structure \ref cy_stc_usbfs_dev_drv_context_t
1140 * allocated by the user. The structure is used during the USBFS Device
1141 * operation for internal configuration and data retention. The user must not
1142 * modify anything in this structure.
1143 *
1144 * \return
1145 * Status code of the function execution \ref cy_en_usbfs_dev_drv_status_t.
1146 *
1147 *******************************************************************************/
ReadOutEndpointDmaAuto(USBFS_Type * base,uint32_t endpoint,uint8_t * buffer,uint32_t size,uint32_t * actSize,cy_stc_usbfs_dev_drv_context_t * context)1148 cy_en_usbfs_dev_drv_status_t ReadOutEndpointDmaAuto(USBFS_Type *base,
1149                                                     uint32_t   endpoint,
1150                                                     uint8_t    *buffer,
1151                                                     uint32_t   size,
1152                                                     uint32_t   *actSize,
1153                                                     cy_stc_usbfs_dev_drv_context_t *context)
1154 {
1155     /* Get pointer to endpoint data */
1156     cy_stc_usbfs_dev_drv_endpoint_data_t *endpointData = &context->epPool[endpoint];
1157 
1158     /* Get number of received bytes */
1159     uint32_t numToCopy = Cy_USBFS_Dev_Drv_GetSieEpCount(base, endpoint);
1160 
1161     /* Initialize actual number of copied bytes */
1162     *actSize = 0U;
1163 
1164     /* Endpoint received more bytes than provided buffer */
1165     if (numToCopy > size)
1166     {
1167         return CY_USBFS_DEV_DRV_BAD_PARAM;
1168     }
1169 
1170     /* Nothing to copy (zero length packet) return success */
1171     if (0U == numToCopy)
1172     {
1173         return CY_USBFS_DEV_DRV_SUCCESS;
1174     }
1175 
1176     /* Copy data from user buffer to internal endpoint buffer */
1177     if (NULL != endpointData->copyData)
1178     {
1179         (void) endpointData->copyData(buffer, endpointData->buffer, numToCopy);
1180     }
1181     else
1182     {
1183         (void) memcpy(buffer, endpointData->buffer, numToCopy);
1184     }
1185 
1186     /* Update number of copied bytes */
1187     *actSize = numToCopy;
1188 
1189     return CY_USBFS_DEV_DRV_SUCCESS;
1190 }
1191 
1192 
1193 #if defined(__cplusplus)
1194 }
1195 #endif
1196 
1197 #endif /* CY_IP_MXUSBFS */
1198 
1199 
1200 /* [] END OF FILE */
1201