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