1 /*
2 * Copyright (c) 2016 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_USBD_ENABLED)
37
38 #include <nrfx_usbd.h>
39 #include "nrfx_usbd_errata.h"
40 #include <string.h>
41
42 #define NRFX_LOG_MODULE USBD
43 #include <nrfx_log.h>
44
45 #ifndef NRFX_USBD_EARLY_DMA_PROCESS
46 /* Try to process DMA request when endpoint transmission has been detected
47 * and just after last EasyDMA has been processed.
48 * It speeds up the transmission a little (about 10% measured)
49 * with a cost of more CPU power used.
50 */
51 #define NRFX_USBD_EARLY_DMA_PROCESS 1
52 #endif
53
54 #ifndef NRFX_USBD_STARTED_EV_ENABLE
55 #define NRFX_USBD_STARTED_EV_ENABLE 0
56 #endif
57
58 #ifndef NRFX_USBD_CONFIG_ISO_IN_ZLP
59 /*
60 * Respond to an IN token on ISO IN endpoint with ZLP when no data is ready.
61 */
62 #define NRFX_USBD_CONFIG_ISO_IN_ZLP 0
63 #endif
64
65 #ifndef NRFX_USBD_ISO_DEBUG
66 /* Also generate information about ISOCHRONOUS events and transfers.
67 * Turn this off if no ISOCHRONOUS transfers are going to be debugged and this
68 * option generates a lot of useless messages. */
69 #define NRFX_USBD_ISO_DEBUG 1
70 #endif
71
72 #ifndef NRFX_USBD_FAILED_TRANSFERS_DEBUG
73 /* Also generate debug information for failed transfers.
74 * It might be useful but may generate a lot of useless debug messages
75 * in some library usages (for example when transfer is generated and the
76 * result is used to check whatever endpoint was busy. */
77 #define NRFX_USBD_FAILED_TRANSFERS_DEBUG 1
78 #endif
79
80 #ifndef NRFX_USBD_DMAREQ_PROCESS_DEBUG
81 /* Generate additional messages that mark the status inside
82 * @ref usbd_dmareq_process.
83 * It is useful to debug library internals but may generate a lot of
84 * useless debug messages. */
85 #define NRFX_USBD_DMAREQ_PROCESS_DEBUG 1
86 #endif
87
88 #ifndef NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211
89 /* Anomaly 211 - Device remains in SUSPEND too long when host resumes
90 a bus activity (sending SOF packets) without a RESUME condition. */
91 #define NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211 0
92 #endif
93
94 /**
95 * @defgroup nrfx_usbd_int USB Device driver internal part
96 * @internal
97 * @ingroup nrfx_usbd
98 *
99 * This part contains auxiliary internal macros, variables and functions.
100 * @{
101 */
102
103 /**
104 * @brief Assert endpoint number validity.
105 *
106 * Internal macro to be used during program creation in debug mode.
107 * Generates assertion if endpoint number is not valid.
108 *
109 * @param ep Endpoint number to validity check.
110 */
111 #define NRFX_USBD_ASSERT_EP_VALID(ep) NRFX_ASSERT( \
112 ((NRF_USBD_EPIN_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPIN_CNT )) \
113 || \
114 (NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPOUT_CNT))) \
115 );
116
117 /**
118 * @brief Lowest position of bit for IN endpoint.
119 *
120 * The first bit position corresponding to IN endpoint.
121 * @sa ep2bit bit2ep
122 */
123 #define NRFX_USBD_EPIN_BITPOS_0 0
124
125 /**
126 * @brief Lowest position of bit for OUT endpoint.
127 *
128 * The first bit position corresponding to OUT endpoint
129 * @sa ep2bit bit2ep
130 */
131 #define NRFX_USBD_EPOUT_BITPOS_0 16
132
133 /**
134 * @brief Input endpoint bits mask.
135 */
136 #define NRFX_USBD_EPIN_BIT_MASK (0xFFFFU << NRFX_USBD_EPIN_BITPOS_0)
137
138 /**
139 * @brief Output endpoint bits mask.
140 */
141 #define NRFX_USBD_EPOUT_BIT_MASK (0xFFFFU << NRFX_USBD_EPOUT_BITPOS_0)
142
143 /**
144 * @brief Isochronous endpoint bit mask
145 */
146 #define USBD_EPISO_BIT_MASK \
147 ((1U << NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT8)) | \
148 (1U << NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN8)))
149
150 /**
151 * @brief Auxiliary macro to change EP number into bit position.
152 *
153 * This macro is used by @ref ep2bit function but also for statically check
154 * the bitpos values integrity during compilation.
155 *
156 * @param[in] ep Endpoint number.
157 * @return Endpoint bit position.
158 */
159 #define NRFX_USBD_EP_BITPOS(ep) \
160 ((NRF_USBD_EPIN_CHECK(ep) ? NRFX_USBD_EPIN_BITPOS_0 : NRFX_USBD_EPOUT_BITPOS_0) \
161 + NRF_USBD_EP_NR_GET(ep))
162
163 /**
164 * @brief Helper macro for creating an endpoint transfer event.
165 *
166 * @param[in] name Name of the created transfer event variable.
167 * @param[in] endpoint Endpoint number.
168 * @param[in] ep_stat Endpoint state to report.
169 *
170 * @return Initialized event constant variable.
171 */
172 #define NRFX_USBD_EP_TRANSFER_EVENT(name, endpont, ep_stat) \
173 const nrfx_usbd_evt_t name = { \
174 NRFX_USBD_EVT_EPTRANSFER, \
175 .data = { \
176 .eptransfer = { \
177 .ep = endpont, \
178 .status = ep_stat \
179 } \
180 } \
181 }
182
183 /* Check it the bit positions values match defined DATAEPSTATUS bit positions */
184 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN1) == USBD_EPDATASTATUS_EPIN1_Pos );
185 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN2) == USBD_EPDATASTATUS_EPIN2_Pos );
186 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN3) == USBD_EPDATASTATUS_EPIN3_Pos );
187 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN4) == USBD_EPDATASTATUS_EPIN4_Pos );
188 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN5) == USBD_EPDATASTATUS_EPIN5_Pos );
189 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN6) == USBD_EPDATASTATUS_EPIN6_Pos );
190 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPIN7) == USBD_EPDATASTATUS_EPIN7_Pos );
191 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT1) == USBD_EPDATASTATUS_EPOUT1_Pos);
192 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT2) == USBD_EPDATASTATUS_EPOUT2_Pos);
193 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT3) == USBD_EPDATASTATUS_EPOUT3_Pos);
194 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT4) == USBD_EPDATASTATUS_EPOUT4_Pos);
195 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT5) == USBD_EPDATASTATUS_EPOUT5_Pos);
196 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT6) == USBD_EPDATASTATUS_EPOUT6_Pos);
197 NRFX_STATIC_ASSERT(NRFX_USBD_EP_BITPOS(NRFX_USBD_EPOUT7) == USBD_EPDATASTATUS_EPOUT7_Pos);
198
199
200 /**
201 * @brief Current driver state.
202 */
203 static nrfx_drv_state_t m_drv_state = NRFX_DRV_STATE_UNINITIALIZED;
204
205 /**
206 * @brief Event handler for the driver.
207 *
208 * Event handler that would be called on events.
209 *
210 * @note Currently it cannot be null if any interrupt is activated.
211 */
212 static nrfx_usbd_event_handler_t m_event_handler;
213
214 /**
215 * @brief Detected state of the bus.
216 *
217 * Internal state changed in interrupts handling when
218 * RESUME or SUSPEND event is processed.
219 *
220 * Values:
221 * - true - bus suspended
222 * - false - ongoing normal communication on the bus
223 *
224 * @note This is only the bus state and does not mean that the peripheral is in suspend state.
225 */
226 static volatile bool m_bus_suspend;
227
228 /**
229 * @brief Internal constant that contains interrupts disabled in suspend state.
230 *
231 * Internal constant used in @ref nrfx_usbd_suspend_irq_config and @ref nrfx_usbd_active_irq_config
232 * functions.
233 */
234 static const uint32_t m_irq_disabled_in_suspend =
235 NRF_USBD_INT_ENDEPIN0_MASK |
236 NRF_USBD_INT_EP0DATADONE_MASK |
237 NRF_USBD_INT_ENDEPOUT0_MASK |
238 NRF_USBD_INT_EP0SETUP_MASK |
239 NRF_USBD_INT_DATAEP_MASK;
240
241 /**
242 * @brief Direction of last received Setup transfer.
243 *
244 * This variable is used to redirect internal setup data event
245 * into selected endpoint (IN or OUT).
246 */
247 static nrfx_usbd_ep_t m_last_setup_dir;
248
249 /**
250 * @brief Mark endpoint readiness for DMA transfer.
251 *
252 * Bits in this variable are cleared and set in interrupts.
253 * 1 means that endpoint is ready for DMA transfer.
254 * 0 means that DMA transfer cannot be performed on selected endpoint.
255 */
256 static uint32_t m_ep_ready;
257
258 /**
259 * @brief Mark endpoint with prepared data to transfer by DMA.
260 *
261 * This variable can be from any place in the code (interrupt or main thread).
262 * It would be cleared only from USBD interrupt.
263 *
264 * Mask prepared USBD data for transmission.
265 * It is cleared when no more data to transmit left.
266 */
267 static nrfx_atomic_t m_ep_dma_waiting;
268
269 /**
270 * @brief Current EasyDMA state.
271 *
272 * Single flag, updated only inside interrupts, that marks current EasyDMA state.
273 * In USBD there is only one DMA channel working in background, and new transfer
274 * cannot be started when there is ongoing transfer on any other channel.
275 */
276 static bool m_dma_pending;
277
278 /**
279 * @brief Tracks whether total bytes transferred by DMA is even or odd.
280 */
281 static uint8_t m_dma_odd;
282
283 /**
284 * @brief First time enabling after reset. Used in nRF52 errata 223.
285 */
286 static bool m_first_enable = true;
287
288 /**
289 * @brief The structure that would hold transfer configuration to every endpoint
290 *
291 * The structure that holds all the data required by the endpoint to proceed
292 * with LIST functionality and generate quick callback directly when data
293 * buffer is ready.
294 */
295 typedef struct
296 {
297 nrfx_usbd_handler_t handler; //!< Handler for current transfer, function pointer.
298 void * p_context; //!< Context for transfer handler.
299 size_t transfer_cnt; //!< Number of transferred bytes in the current transfer.
300 uint16_t max_packet_size; //!< Configured endpoint size.
301 nrfx_usbd_ep_status_t status; //!< NRFX_SUCCESS or error code, never NRFX_ERROR_BUSY - this one is calculated.
302 } usbd_ep_state_t;
303
304 /**
305 * @brief The array of transfer configurations for the endpoints.
306 *
307 * The status of the transfer on each endpoint.
308 */
309 static struct
310 {
311 usbd_ep_state_t ep_out[NRF_USBD_EPOUT_CNT]; //!< Status for OUT endpoints.
312 usbd_ep_state_t ep_in [NRF_USBD_EPIN_CNT ]; //!< Status for IN endpoints.
313 } m_ep_state;
314
315 /**
316 * @brief Status variables for integrated feeders.
317 *
318 * Current status for integrated feeders (IN transfers).
319 * Integrated feeders are used for default transfers:
320 * 1. Simple RAM transfer.
321 * 2. Simple flash transfer.
322 * 3. RAM transfer with automatic ZLP.
323 * 4. Flash transfer with automatic ZLP.
324 */
325 nrfx_usbd_transfer_t m_ep_feeder_state[NRF_USBD_EPIN_CNT];
326
327 /**
328 * @brief Status variables for integrated consumers.
329 *
330 * Current status for integrated consumers.
331 * Currently one type of transfer is supported:
332 * 1. Transfer to RAM.
333 *
334 * Transfer is finished automatically when received data block is smaller
335 * than the endpoint buffer or all the required data is received.
336 */
337 nrfx_usbd_transfer_t m_ep_consumer_state[NRF_USBD_EPOUT_CNT];
338
339
340 /**
341 * @brief Buffer used to send data directly from FLASH.
342 *
343 * This is internal buffer that would be used to emulate the possibility
344 * to transfer data directly from FLASH.
345 * We do not have to care about the source of data when calling transfer functions.
346 *
347 * We do not need more buffers that one, because only one transfer can be pending
348 * at once.
349 */
350 static uint32_t m_tx_buffer[NRFX_CEIL_DIV(
351 NRFX_USBD_FEEDER_BUFFER_SIZE, sizeof(uint32_t))];
352
353 /* Early declaration. Documentation above definition. */
354 static void usbd_dmareq_process(void);
355
356
357 /**
358 * @brief Change endpoint number to endpoint event code.
359 *
360 * @param ep Endpoint number.
361 *
362 * @return Connected endpoint event code.
363 *
364 * Marker to delete when not required anymore: >> NRFX_USBD_ERRATA_ENABLE <<.
365 */
nrfx_usbd_ep_to_endevent(nrfx_usbd_ep_t ep)366 static inline nrf_usbd_event_t nrfx_usbd_ep_to_endevent(nrfx_usbd_ep_t ep)
367 {
368 NRFX_USBD_ASSERT_EP_VALID(ep);
369
370 static const nrf_usbd_event_t epin_endev[] =
371 {
372 NRF_USBD_EVENT_ENDEPIN0,
373 NRF_USBD_EVENT_ENDEPIN1,
374 NRF_USBD_EVENT_ENDEPIN2,
375 NRF_USBD_EVENT_ENDEPIN3,
376 NRF_USBD_EVENT_ENDEPIN4,
377 NRF_USBD_EVENT_ENDEPIN5,
378 NRF_USBD_EVENT_ENDEPIN6,
379 NRF_USBD_EVENT_ENDEPIN7,
380 NRF_USBD_EVENT_ENDISOIN0
381 };
382 static const nrf_usbd_event_t epout_endev[] =
383 {
384 NRF_USBD_EVENT_ENDEPOUT0,
385 NRF_USBD_EVENT_ENDEPOUT1,
386 NRF_USBD_EVENT_ENDEPOUT2,
387 NRF_USBD_EVENT_ENDEPOUT3,
388 NRF_USBD_EVENT_ENDEPOUT4,
389 NRF_USBD_EVENT_ENDEPOUT5,
390 NRF_USBD_EVENT_ENDEPOUT6,
391 NRF_USBD_EVENT_ENDEPOUT7,
392 NRF_USBD_EVENT_ENDISOOUT0
393 };
394
395 return (NRF_USBD_EPIN_CHECK(ep) ? epin_endev : epout_endev)[NRF_USBD_EP_NR_GET(ep)];
396 }
397
398
399 /**
400 * @brief Get interrupt mask for selected endpoint.
401 *
402 * @param[in] ep Endpoint number.
403 *
404 * @return Interrupt mask related to the EasyDMA transfer end for the
405 * chosen endpoint.
406 */
nrfx_usbd_ep_to_int(nrfx_usbd_ep_t ep)407 static inline uint32_t nrfx_usbd_ep_to_int(nrfx_usbd_ep_t ep)
408 {
409 NRFX_USBD_ASSERT_EP_VALID(ep);
410
411 static const uint8_t epin_bitpos[] =
412 {
413 USBD_INTEN_ENDEPIN0_Pos,
414 USBD_INTEN_ENDEPIN1_Pos,
415 USBD_INTEN_ENDEPIN2_Pos,
416 USBD_INTEN_ENDEPIN3_Pos,
417 USBD_INTEN_ENDEPIN4_Pos,
418 USBD_INTEN_ENDEPIN5_Pos,
419 USBD_INTEN_ENDEPIN6_Pos,
420 USBD_INTEN_ENDEPIN7_Pos,
421 USBD_INTEN_ENDISOIN_Pos
422 };
423 static const uint8_t epout_bitpos[] =
424 {
425 USBD_INTEN_ENDEPOUT0_Pos,
426 USBD_INTEN_ENDEPOUT1_Pos,
427 USBD_INTEN_ENDEPOUT2_Pos,
428 USBD_INTEN_ENDEPOUT3_Pos,
429 USBD_INTEN_ENDEPOUT4_Pos,
430 USBD_INTEN_ENDEPOUT5_Pos,
431 USBD_INTEN_ENDEPOUT6_Pos,
432 USBD_INTEN_ENDEPOUT7_Pos,
433 USBD_INTEN_ENDISOOUT_Pos
434 };
435
436 return 1UL << (NRF_USBD_EPIN_CHECK(ep) ? epin_bitpos : epout_bitpos)[NRF_USBD_EP_NR_GET(ep)];
437 }
438
439 /**
440 * @name Integrated feeders and consumers
441 *
442 * Internal, default functions for transfer processing.
443 * @{
444 */
445
446 /**
447 * @brief Integrated consumer to RAM buffer.
448 *
449 * @param p_next See @ref nrfx_usbd_consumer_t documentation.
450 * @param p_context See @ref nrfx_usbd_consumer_t documentation.
451 * @param ep_size See @ref nrfx_usbd_consumer_t documentation.
452 * @param data_size See @ref nrfx_usbd_consumer_t documentation.
453 *
454 * @retval true Continue transfer.
455 * @retval false This was the last transfer.
456 */
nrfx_usbd_consumer(nrfx_usbd_ep_transfer_t * p_next,void * p_context,size_t ep_size,size_t data_size)457 bool nrfx_usbd_consumer(
458 nrfx_usbd_ep_transfer_t * p_next,
459 void * p_context,
460 size_t ep_size,
461 size_t data_size)
462 {
463 nrfx_usbd_transfer_t * p_transfer = (nrfx_usbd_transfer_t *)p_context;
464 NRFX_ASSERT(ep_size >= data_size);
465 NRFX_ASSERT((p_transfer->p_data.rx == NULL) ||
466 nrfx_is_in_ram(p_transfer->p_data.rx));
467
468 size_t size = p_transfer->size;
469 if (size < data_size)
470 {
471 NRFX_LOG_DEBUG("consumer: buffer too small: r: %u, l: %u", data_size, size);
472 /* Buffer size to small */
473 p_next->size = 0;
474 p_next->p_data = p_transfer->p_data;
475 }
476 else
477 {
478 p_next->size = data_size;
479 p_next->p_data = p_transfer->p_data;
480 size -= data_size;
481 p_transfer->size = size;
482 p_transfer->p_data.addr += data_size;
483 }
484 return (ep_size == data_size) && (size != 0);
485 }
486
487 /**
488 * @brief Integrated feeder from RAM source.
489 *
490 * @param[out] p_next See @ref nrfx_usbd_feeder_t documentation.
491 * @param[in,out] p_context See @ref nrfx_usbd_feeder_t documentation.
492 * @param[in] ep_size See @ref nrfx_usbd_feeder_t documentation.
493 *
494 * @retval true Continue transfer.
495 * @retval false This was the last transfer.
496 */
nrfx_usbd_feeder_ram(nrfx_usbd_ep_transfer_t * p_next,void * p_context,size_t ep_size)497 bool nrfx_usbd_feeder_ram(
498 nrfx_usbd_ep_transfer_t * p_next,
499 void * p_context,
500 size_t ep_size)
501 {
502 nrfx_usbd_transfer_t * p_transfer = (nrfx_usbd_transfer_t *)p_context;
503 NRFX_ASSERT(nrfx_is_in_ram(p_transfer->p_data.tx));
504
505 size_t tx_size = p_transfer->size;
506 if (tx_size > ep_size)
507 {
508 tx_size = ep_size;
509 }
510
511 p_next->p_data = p_transfer->p_data;
512 p_next->size = tx_size;
513
514 p_transfer->size -= tx_size;
515 p_transfer->p_data.addr += tx_size;
516
517 return (p_transfer->size != 0);
518 }
519
520 /**
521 * @brief Integrated feeder from RAM source with ZLP.
522 *
523 * @param[out] p_next See @ref nrfx_usbd_feeder_t documentation.
524 * @param[in,out] p_context See @ref nrfx_usbd_feeder_t documentation.
525 * @param[in] ep_size See @ref nrfx_usbd_feeder_t documentation.
526 *
527 * @retval true Continue transfer.
528 * @retval false This was the last transfer.
529 */
nrfx_usbd_feeder_ram_zlp(nrfx_usbd_ep_transfer_t * p_next,void * p_context,size_t ep_size)530 bool nrfx_usbd_feeder_ram_zlp(
531 nrfx_usbd_ep_transfer_t * p_next,
532 void * p_context,
533 size_t ep_size)
534 {
535 nrfx_usbd_transfer_t * p_transfer = (nrfx_usbd_transfer_t *)p_context;
536 NRFX_ASSERT(nrfx_is_in_ram(p_transfer->p_data.tx));
537
538 size_t tx_size = p_transfer->size;
539 if (tx_size > ep_size)
540 {
541 tx_size = ep_size;
542 }
543
544 p_next->p_data.tx = (tx_size == 0) ? NULL : p_transfer->p_data.tx;
545 p_next->size = tx_size;
546
547 p_transfer->size -= tx_size;
548 p_transfer->p_data.addr += tx_size;
549
550 return (tx_size != 0);
551 }
552
553 /**
554 * @brief Integrated feeder from a flash source.
555 *
556 * @param[out] p_next See @ref nrfx_usbd_feeder_t documentation.
557 * @param[in,out] p_context See @ref nrfx_usbd_feeder_t documentation.
558 * @param[in] ep_size See @ref nrfx_usbd_feeder_t documentation.
559 *
560 * @retval true Continue transfer.
561 * @retval false This was the last transfer.
562 */
nrfx_usbd_feeder_flash(nrfx_usbd_ep_transfer_t * p_next,void * p_context,size_t ep_size)563 bool nrfx_usbd_feeder_flash(nrfx_usbd_ep_transfer_t * p_next, void * p_context, size_t ep_size)
564 {
565 nrfx_usbd_transfer_t * p_transfer = (nrfx_usbd_transfer_t *)p_context;
566 NRFX_ASSERT(!nrfx_is_in_ram(p_transfer->p_data.tx));
567
568 size_t tx_size = p_transfer->size;
569 void * p_buffer = nrfx_usbd_feeder_buffer_get();
570
571 if (tx_size > ep_size)
572 {
573 tx_size = ep_size;
574 }
575
576 NRFX_ASSERT(tx_size <= NRFX_USBD_FEEDER_BUFFER_SIZE);
577 memcpy(p_buffer, (p_transfer->p_data.tx), tx_size);
578
579 p_next->p_data.tx = p_buffer;
580 p_next->size = tx_size;
581
582 p_transfer->size -= tx_size;
583 p_transfer->p_data.addr += tx_size;
584
585 return (p_transfer->size != 0);
586 }
587
588 /**
589 * @brief Integrated feeder from a flash source with ZLP.
590 *
591 * @param[out] p_next See @ref nrfx_usbd_feeder_t documentation.
592 * @param[in,out] p_context See @ref nrfx_usbd_feeder_t documentation.
593 * @param[in] ep_size See @ref nrfx_usbd_feeder_t documentation.
594 *
595 * @retval true Continue transfer.
596 * @retval false This was the last transfer.
597 */
nrfx_usbd_feeder_flash_zlp(nrfx_usbd_ep_transfer_t * p_next,void * p_context,size_t ep_size)598 bool nrfx_usbd_feeder_flash_zlp(nrfx_usbd_ep_transfer_t * p_next, void * p_context, size_t ep_size)
599 {
600 nrfx_usbd_transfer_t * p_transfer = (nrfx_usbd_transfer_t *)p_context;
601 NRFX_ASSERT(!nrfx_is_in_ram(p_transfer->p_data.tx));
602
603 size_t tx_size = p_transfer->size;
604 void * p_buffer = nrfx_usbd_feeder_buffer_get();
605
606 if (tx_size > ep_size)
607 {
608 tx_size = ep_size;
609 }
610
611 NRFX_ASSERT(tx_size <= NRFX_USBD_FEEDER_BUFFER_SIZE);
612
613 if (tx_size != 0)
614 {
615 memcpy(p_buffer, (p_transfer->p_data.tx), tx_size);
616 p_next->p_data.tx = p_buffer;
617 }
618 else
619 {
620 p_next->p_data.tx = NULL;
621 }
622 p_next->size = tx_size;
623
624 p_transfer->size -= tx_size;
625 p_transfer->p_data.addr += tx_size;
626
627 return (tx_size != 0);
628 }
629
630 /** @} */
631
632 /**
633 * @brief Change Driver endpoint number to HAL endpoint number.
634 *
635 * @param ep Driver endpoint identifier.
636 *
637 * @return Endpoint identifier in HAL.
638 *
639 * @sa nrfx_usbd_ep_from_hal
640 */
ep_to_hal(nrfx_usbd_ep_t ep)641 static inline uint8_t ep_to_hal(nrfx_usbd_ep_t ep)
642 {
643 NRFX_USBD_ASSERT_EP_VALID(ep);
644 return (uint8_t)ep;
645 }
646
647 /**
648 * @brief Generate start task number for selected endpoint index.
649 *
650 * @param ep Endpoint number.
651 *
652 * @return Task for starting EasyDMA transfer on selected endpoint.
653 */
task_start_ep(nrfx_usbd_ep_t ep)654 static inline nrf_usbd_task_t task_start_ep(nrfx_usbd_ep_t ep)
655 {
656 NRFX_USBD_ASSERT_EP_VALID(ep);
657 return (nrf_usbd_task_t)(
658 (NRF_USBD_EPIN_CHECK(ep) ? NRF_USBD_TASK_STARTEPIN0 : NRF_USBD_TASK_STARTEPOUT0) +
659 (NRF_USBD_EP_NR_GET(ep) * sizeof(uint32_t)));
660 }
661
662 /**
663 * @brief Access selected endpoint state structure.
664 *
665 * Function used to change or just read the state of selected endpoint.
666 * It is used for internal transmission state.
667 *
668 * @param ep Endpoint number.
669 */
ep_state_access(nrfx_usbd_ep_t ep)670 static inline usbd_ep_state_t* ep_state_access(nrfx_usbd_ep_t ep)
671 {
672 NRFX_USBD_ASSERT_EP_VALID(ep);
673 return ((NRF_USBD_EPIN_CHECK(ep) ? m_ep_state.ep_in : m_ep_state.ep_out) +
674 NRF_USBD_EP_NR_GET(ep));
675 }
676
677 /**
678 * @brief Change endpoint number to bit position.
679 *
680 * Bit positions are defined the same way as they are placed in DATAEPSTATUS register,
681 * but bits for endpoint 0 are included.
682 *
683 * @param ep Endpoint number.
684 *
685 * @return Bit position related to the given endpoint number.
686 *
687 * @sa bit2ep
688 */
ep2bit(nrfx_usbd_ep_t ep)689 static inline uint8_t ep2bit(nrfx_usbd_ep_t ep)
690 {
691 NRFX_USBD_ASSERT_EP_VALID(ep);
692 return (uint8_t)NRFX_USBD_EP_BITPOS(ep);
693 }
694
695 /**
696 * @brief Change bit position to endpoint number.
697 *
698 * @param bitpos Bit position.
699 *
700 * @return Endpoint number corresponding to given bit position.
701 *
702 * @sa ep2bit
703 */
bit2ep(uint8_t bitpos)704 static inline nrfx_usbd_ep_t bit2ep(uint8_t bitpos)
705 {
706 NRFX_STATIC_ASSERT(NRFX_USBD_EPOUT_BITPOS_0 > NRFX_USBD_EPIN_BITPOS_0);
707 return (nrfx_usbd_ep_t)((bitpos >= NRFX_USBD_EPOUT_BITPOS_0) ?
708 NRF_USBD_EPOUT(bitpos - NRFX_USBD_EPOUT_BITPOS_0) : NRF_USBD_EPIN(bitpos));
709 }
710
711 /**
712 * @brief Mark that EasyDMA is working.
713 *
714 * Internal function to set the flag informing about EasyDMA transfer pending.
715 * This function is called always just after the EasyDMA transfer is started.
716 */
usbd_dma_pending_set(void)717 static inline void usbd_dma_pending_set(void)
718 {
719 if (nrfx_usbd_errata_199())
720 {
721 *((volatile uint32_t *)0x40027C1C) = 0x00000082;
722 }
723 m_dma_pending = true;
724 }
725
726 /**
727 * @brief Mark that EasyDMA is free.
728 *
729 * Internal function to clear the flag informing about EasyDMA transfer pending.
730 * This function is called always just after the finished EasyDMA transfer is detected.
731 */
usbd_dma_pending_clear(void)732 static inline void usbd_dma_pending_clear(void)
733 {
734 if (nrfx_usbd_errata_199())
735 {
736 *((volatile uint32_t *)0x40027C1C) = 0x00000000;
737 }
738 m_dma_pending = false;
739 }
740
741 /**
742 * @brief Start selected EasyDMA transmission.
743 *
744 * This is internal auxiliary function.
745 * No checking is made if EasyDMA is ready for new transmission.
746 *
747 * @param[in] ep Number of endpoint for transmission.
748 * If it is OUT endpoint transmission would be directed from endpoint to RAM.
749 * If it is in endpoint transmission would be directed from RAM to endpoint.
750 */
usbd_dma_start(nrfx_usbd_ep_t ep)751 static inline void usbd_dma_start(nrfx_usbd_ep_t ep)
752 {
753 nrf_usbd_task_trigger(NRF_USBD, task_start_ep(ep));
754 }
755
nrfx_usbd_isoinconfig_set(nrf_usbd_isoinconfig_t config)756 void nrfx_usbd_isoinconfig_set(nrf_usbd_isoinconfig_t config)
757 {
758 nrf_usbd_isoinconfig_set(NRF_USBD, config);
759 }
760
nrfx_usbd_isoinconfig_get(void)761 nrf_usbd_isoinconfig_t nrfx_usbd_isoinconfig_get(void)
762 {
763 return nrf_usbd_isoinconfig_get(NRF_USBD);
764 }
765
766 /**
767 * @brief Abort pending transfer on selected endpoint.
768 *
769 * @param ep Endpoint number.
770 *
771 * @note
772 * This function locks interrupts that may be costly.
773 * It is good idea to test if the endpoint is still busy before calling this function:
774 * @code
775 (m_ep_dma_waiting & (1U << ep2bit(ep)))
776 * @endcode
777 * This function would check it again, but it makes it inside critical section.
778 */
usbd_ep_abort(nrfx_usbd_ep_t ep)779 static inline void usbd_ep_abort(nrfx_usbd_ep_t ep)
780 {
781 NRFX_CRITICAL_SECTION_ENTER();
782
783 usbd_ep_state_t * p_state = ep_state_access(ep);
784
785 if (NRF_USBD_EPOUT_CHECK(ep))
786 {
787 /* Host -> Device */
788 if ((~m_ep_dma_waiting) & (1U << ep2bit(ep)))
789 {
790 /* If the bit in m_ep_dma_waiting in cleared - nothing would be
791 * processed inside transfer processing */
792 nrfx_usbd_transfer_out_drop(ep);
793 }
794 else
795 {
796 p_state->handler.consumer = NULL;
797 m_ep_dma_waiting &= ~(1U << ep2bit(ep));
798 m_ep_ready &= ~(1U << ep2bit(ep));
799 }
800 /* Aborted */
801 p_state->status = NRFX_USBD_EP_ABORTED;
802 }
803 else
804 {
805 if(!NRF_USBD_EPISO_CHECK(ep))
806 {
807 /* Workaround: Disarm the endpoint if there is any data buffered. */
808 if(ep != NRFX_USBD_EPIN0)
809 {
810 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = 0x7B6 + (2u * (NRF_USBD_EP_NR_GET(ep) - 1));
811 uint8_t temp = (uint8_t)*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804));
812 temp |= (1U << 1);
813 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) |= temp;
814 (void)(*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)));
815 }
816 else
817 {
818 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = 0x7B4;
819 uint8_t temp = (uint8_t)*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804));
820 temp |= (1U << 2);
821 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) |= temp;
822 (void)(*((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)));
823 }
824 }
825 if ((m_ep_dma_waiting | (~m_ep_ready)) & (1U << ep2bit(ep)))
826 {
827 /* Device -> Host */
828 m_ep_dma_waiting &= ~(1U << ep2bit(ep));
829 m_ep_ready |= 1U << ep2bit(ep) ;
830
831 p_state->handler.feeder = NULL;
832 p_state->status = NRFX_USBD_EP_ABORTED;
833 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_ABORTED);
834 m_event_handler(&evt);
835 }
836 }
837 NRFX_CRITICAL_SECTION_EXIT();
838 }
839
nrfx_usbd_ep_abort(nrfx_usbd_ep_t ep)840 void nrfx_usbd_ep_abort(nrfx_usbd_ep_t ep)
841 {
842 usbd_ep_abort(ep);
843 }
844
845
846 /**
847 * @brief Abort all pending endpoints.
848 *
849 * Function aborts all pending endpoint transfers.
850 */
usbd_ep_abort_all(void)851 static void usbd_ep_abort_all(void)
852 {
853 uint32_t ep_waiting = m_ep_dma_waiting | (m_ep_ready & NRFX_USBD_EPOUT_BIT_MASK);
854 while (0 != ep_waiting)
855 {
856 uint8_t bitpos = (uint8_t)NRF_CTZ(ep_waiting);
857 if (!NRF_USBD_EPISO_CHECK(bit2ep(bitpos)))
858 {
859 usbd_ep_abort(bit2ep(bitpos));
860 }
861 ep_waiting &= ~(1U << bitpos);
862 }
863
864 m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << NRFX_USBD_EPIN_BITPOS_0);
865 }
866
867 /**
868 * @brief Force the USBD interrupt into pending state.
869 *
870 * This function is used to force USBD interrupt to be processed right now.
871 * It makes it possible to process all EasyDMA access on one thread priority level.
872 */
usbd_int_rise(void)873 static inline void usbd_int_rise(void)
874 {
875 NRFX_IRQ_PENDING_SET(USBD_IRQn);
876 }
877
878 /**
879 * @name USBD interrupt runtimes.
880 *
881 * Interrupt runtimes that would be vectorized using @ref m_isr.
882 * @{
883 */
884
ev_usbreset_handler(void)885 static void ev_usbreset_handler(void)
886 {
887 m_bus_suspend = false;
888 m_last_setup_dir = NRFX_USBD_EPOUT0;
889
890 const nrfx_usbd_evt_t evt = {
891 .type = NRFX_USBD_EVT_RESET
892 };
893
894 m_event_handler(&evt);
895 }
896
ev_started_handler(void)897 static void ev_started_handler(void)
898 {
899 #if NRFX_USBD_STARTED_EV_ENABLE
900 // Handler not used by the stack.
901 // May be used for debugging.
902 #endif
903 }
904
905 /**
906 * @brief Handler for EasyDMA event without endpoint clearing.
907 *
908 * This handler would be called when EasyDMA transfer for endpoints that does not require clearing.
909 * All in endpoints are cleared automatically when new EasyDMA transfer is initialized.
910 * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler.
911 *
912 * @param[in] ep Endpoint number.
913 */
nrf_usbd_ep0in_dma_handler(void)914 static inline void nrf_usbd_ep0in_dma_handler(void)
915 {
916 const nrfx_usbd_ep_t ep = NRFX_USBD_EPIN0;
917 NRFX_LOG_DEBUG("USB event: DMA ready IN0");
918 usbd_dma_pending_clear();
919
920 usbd_ep_state_t * p_state = ep_state_access(ep);
921 if (NRFX_USBD_EP_ABORTED == p_state->status)
922 {
923 /* Clear transfer information just in case */
924 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
925 }
926 else if (p_state->handler.feeder == NULL)
927 {
928 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
929 }
930 else
931 {
932 /* Nothing to do */
933 }
934 }
935
936 /**
937 * @brief Handler for EasyDMA event without endpoint clearing.
938 *
939 * This handler would be called when EasyDMA transfer for endpoints that does not require clearing.
940 * All in endpoints are cleared automatically when new EasyDMA transfer is initialized.
941 * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler.
942 *
943 * @param[in] ep Endpoint number.
944 */
nrf_usbd_epin_dma_handler(nrfx_usbd_ep_t ep)945 static inline void nrf_usbd_epin_dma_handler(nrfx_usbd_ep_t ep)
946 {
947 NRFX_LOG_DEBUG("USB event: DMA ready IN: %x", ep);
948 NRFX_ASSERT(NRF_USBD_EPIN_CHECK(ep));
949 NRFX_ASSERT(!NRF_USBD_EPISO_CHECK(ep));
950 NRFX_ASSERT(NRF_USBD_EP_NR_GET(ep) > 0);
951 usbd_dma_pending_clear();
952
953 usbd_ep_state_t * p_state = ep_state_access(ep);
954 if (NRFX_USBD_EP_ABORTED == p_state->status)
955 {
956 /* Clear transfer information just in case */
957 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
958 }
959 else if (p_state->handler.feeder == NULL)
960 {
961 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
962 }
963 else
964 {
965 /* Nothing to do */
966 }
967 }
968
969 /**
970 * @brief Handler for EasyDMA event from in isochronous endpoint.
971 */
nrf_usbd_epiniso_dma_handler(nrfx_usbd_ep_t ep)972 static inline void nrf_usbd_epiniso_dma_handler(nrfx_usbd_ep_t ep)
973 {
974 if (NRFX_USBD_ISO_DEBUG)
975 {
976 NRFX_LOG_DEBUG("USB event: DMA ready ISOIN: %x", ep);
977 }
978 NRFX_ASSERT(NRF_USBD_EPIN_CHECK(ep));
979 NRFX_ASSERT(NRF_USBD_EPISO_CHECK(ep));
980 usbd_dma_pending_clear();
981
982 usbd_ep_state_t * p_state = ep_state_access(ep);
983 if (NRFX_USBD_EP_ABORTED == p_state->status)
984 {
985 /* Clear transfer information just in case */
986 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
987 }
988 else if (p_state->handler.feeder == NULL)
989 {
990 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
991 /* Send event to the user - for an ISO IN endpoint, the whole transfer is finished in this moment */
992 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OK);
993 m_event_handler(&evt);
994 }
995 else
996 {
997 /* Nothing to do */
998 }
999 }
1000
1001 /**
1002 * @brief Handler for EasyDMA event for OUT endpoint 0.
1003 *
1004 * EP0 OUT have to be cleared automatically in special way - only in the middle of the transfer.
1005 * It cannot be cleared when required transfer is finished because it means the same that accepting the comment.
1006 */
nrf_usbd_ep0out_dma_handler(void)1007 static inline void nrf_usbd_ep0out_dma_handler(void)
1008 {
1009 const nrfx_usbd_ep_t ep = NRFX_USBD_EPOUT0;
1010 NRFX_LOG_DEBUG("USB event: DMA ready OUT0");
1011 usbd_dma_pending_clear();
1012
1013 usbd_ep_state_t * p_state = ep_state_access(ep);
1014 if (NRFX_USBD_EP_ABORTED == p_state->status)
1015 {
1016 /* Clear transfer information just in case */
1017 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
1018 }
1019 else if (p_state->handler.consumer == NULL)
1020 {
1021 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
1022 /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
1023 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OK);
1024 m_event_handler(&evt);
1025 }
1026 else
1027 {
1028 nrfx_usbd_setup_data_clear();
1029 }
1030 }
1031
1032 /**
1033 * @brief Handler for EasyDMA event from endpoinpoint that requires clearing.
1034 *
1035 * This handler would be called when EasyDMA transfer for OUT endpoint has been finished.
1036 *
1037 * @param[in] ep Endpoint number.
1038 */
nrf_usbd_epout_dma_handler(nrfx_usbd_ep_t ep)1039 static inline void nrf_usbd_epout_dma_handler(nrfx_usbd_ep_t ep)
1040 {
1041 NRFX_LOG_DEBUG("DMA ready OUT: %x", ep);
1042 NRFX_ASSERT(NRF_USBD_EPOUT_CHECK(ep));
1043 NRFX_ASSERT(!NRF_USBD_EPISO_CHECK(ep));
1044 NRFX_ASSERT(NRF_USBD_EP_NR_GET(ep) > 0);
1045 usbd_dma_pending_clear();
1046
1047 usbd_ep_state_t * p_state = ep_state_access(ep);
1048 if (NRFX_USBD_EP_ABORTED == p_state->status)
1049 {
1050 /* Clear transfer information just in case */
1051 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
1052 }
1053 else if (p_state->handler.consumer == NULL)
1054 {
1055 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
1056 /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
1057 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OK);
1058 m_event_handler(&evt);
1059 }
1060 else
1061 {
1062 /* Nothing to do */
1063 }
1064
1065 #if NRFX_USBD_EARLY_DMA_PROCESS
1066 /* Speed up */
1067 usbd_dmareq_process();
1068 #endif
1069 }
1070
1071 /**
1072 * @brief Handler for EasyDMA event from out isochronous endpoint.
1073 */
nrf_usbd_epoutiso_dma_handler(nrfx_usbd_ep_t ep)1074 static inline void nrf_usbd_epoutiso_dma_handler(nrfx_usbd_ep_t ep)
1075 {
1076 if (NRFX_USBD_ISO_DEBUG)
1077 {
1078 NRFX_LOG_DEBUG("DMA ready ISOOUT: %x", ep);
1079 }
1080 NRFX_ASSERT(NRF_USBD_EPISO_CHECK(ep));
1081 usbd_dma_pending_clear();
1082
1083 usbd_ep_state_t * p_state = ep_state_access(ep);
1084 if (NRFX_USBD_EP_ABORTED == p_state->status)
1085 {
1086 /* Nothing to do - just ignore */
1087 }
1088 else if (p_state->handler.consumer == NULL)
1089 {
1090 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << ep2bit(ep))));
1091 /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */
1092 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OK);
1093 m_event_handler(&evt);
1094 }
1095 else
1096 {
1097 /* Nothing to do */
1098 }
1099 }
1100
1101
ev_dma_epin0_handler(void)1102 static void ev_dma_epin0_handler(void) { nrf_usbd_ep0in_dma_handler(); }
ev_dma_epin1_handler(void)1103 static void ev_dma_epin1_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN1 ); }
ev_dma_epin2_handler(void)1104 static void ev_dma_epin2_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN2 ); }
ev_dma_epin3_handler(void)1105 static void ev_dma_epin3_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN3 ); }
ev_dma_epin4_handler(void)1106 static void ev_dma_epin4_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN4 ); }
ev_dma_epin5_handler(void)1107 static void ev_dma_epin5_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN5 ); }
ev_dma_epin6_handler(void)1108 static void ev_dma_epin6_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN6 ); }
ev_dma_epin7_handler(void)1109 static void ev_dma_epin7_handler(void) { nrf_usbd_epin_dma_handler(NRFX_USBD_EPIN7 ); }
ev_dma_epin8_handler(void)1110 static void ev_dma_epin8_handler(void) { nrf_usbd_epiniso_dma_handler(NRFX_USBD_EPIN8 ); }
1111
ev_dma_epout0_handler(void)1112 static void ev_dma_epout0_handler(void) { nrf_usbd_ep0out_dma_handler(); }
ev_dma_epout1_handler(void)1113 static void ev_dma_epout1_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT1); }
ev_dma_epout2_handler(void)1114 static void ev_dma_epout2_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT2); }
ev_dma_epout3_handler(void)1115 static void ev_dma_epout3_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT3); }
ev_dma_epout4_handler(void)1116 static void ev_dma_epout4_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT4); }
ev_dma_epout5_handler(void)1117 static void ev_dma_epout5_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT5); }
ev_dma_epout6_handler(void)1118 static void ev_dma_epout6_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT6); }
ev_dma_epout7_handler(void)1119 static void ev_dma_epout7_handler(void) { nrf_usbd_epout_dma_handler(NRFX_USBD_EPOUT7); }
ev_dma_epout8_handler(void)1120 static void ev_dma_epout8_handler(void) { nrf_usbd_epoutiso_dma_handler(NRFX_USBD_EPOUT8); }
1121
ev_sof_handler(void)1122 static void ev_sof_handler(void)
1123 {
1124 nrfx_usbd_evt_t evt = {
1125 NRFX_USBD_EVT_SOF,
1126 .data = { .sof = { .framecnt = (uint16_t)nrf_usbd_framecntr_get(NRF_USBD) }}
1127 };
1128
1129 /* Process isochronous endpoints */
1130 uint32_t iso_ready_mask = (1U << ep2bit(NRFX_USBD_EPIN8));
1131 if (nrf_usbd_episoout_size_get(NRF_USBD, NRFX_USBD_EPOUT8) != NRF_USBD_EPISOOUT_NO_DATA)
1132 {
1133 iso_ready_mask |= (1U << ep2bit(NRFX_USBD_EPOUT8));
1134 }
1135 m_ep_ready |= iso_ready_mask;
1136
1137 m_event_handler(&evt);
1138 }
1139
1140 /**
1141 * @brief React on data transfer finished.
1142 *
1143 * Auxiliary internal function.
1144 * @param ep Endpoint number.
1145 * @param bitpos Bit position for selected endpoint number.
1146 */
usbd_ep_data_handler(nrfx_usbd_ep_t ep,uint8_t bitpos)1147 static void usbd_ep_data_handler(nrfx_usbd_ep_t ep, uint8_t bitpos)
1148 {
1149 NRFX_LOG_DEBUG("USBD event: EndpointData: %x", ep);
1150 /* Mark endpoint ready for next DMA access */
1151 m_ep_ready |= (1U << bitpos);
1152
1153 if (NRF_USBD_EPIN_CHECK(ep))
1154 {
1155 /* IN endpoint (Device -> Host) */
1156
1157 /* Secure against the race condition that occurs when an IN transfer is interrupted
1158 * by an OUT transaction, which in turn is interrupted by a process with higher priority.
1159 * If the IN events ENDEPIN and EPDATA arrive during that high priority process,
1160 * the OUT handler might call usbd_ep_data_handler without calling
1161 * nrf_usbd_epin_dma_handler (or nrf_usbd_ep0in_dma_handler) for the IN transaction.
1162 */
1163 if (nrf_usbd_event_get_and_clear(NRF_USBD, nrfx_usbd_ep_to_endevent(ep)))
1164 {
1165 if (ep != NRFX_USBD_EPIN0)
1166 {
1167 nrf_usbd_epin_dma_handler(ep);
1168 }
1169 else
1170 {
1171 nrf_usbd_ep0in_dma_handler();
1172 }
1173 }
1174
1175 if (0 == (m_ep_dma_waiting & (1U << bitpos)))
1176 {
1177 NRFX_LOG_DEBUG("USBD event: EndpointData: In finished");
1178 /* No more data to be send - transmission finished */
1179 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OK);
1180 m_event_handler(&evt);
1181 }
1182 }
1183 else
1184 {
1185 /* OUT endpoint (Host -> Device) */
1186 if (0 == (m_ep_dma_waiting & (1U << bitpos)))
1187 {
1188 NRFX_LOG_DEBUG("USBD event: EndpointData: Out waiting");
1189 /* No buffer prepared - send event to the application */
1190 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_WAITING);
1191 m_event_handler(&evt);
1192 }
1193 }
1194 }
1195
ev_setup_data_handler(void)1196 static void ev_setup_data_handler(void)
1197 {
1198 usbd_ep_data_handler(m_last_setup_dir, ep2bit(m_last_setup_dir));
1199 }
1200
ev_setup_handler(void)1201 static void ev_setup_handler(void)
1202 {
1203 NRFX_LOG_DEBUG("USBD event: Setup (rt:%.2x r:%.2x v:%.4x i:%.4x l:%u )",
1204 nrf_usbd_setup_bmrequesttype_get(NRF_USBD),
1205 nrf_usbd_setup_brequest_get(NRF_USBD),
1206 nrf_usbd_setup_wvalue_get(NRF_USBD),
1207 nrf_usbd_setup_windex_get(NRF_USBD),
1208 nrf_usbd_setup_wlength_get(NRF_USBD));
1209 uint8_t bmRequestType = nrf_usbd_setup_bmrequesttype_get(NRF_USBD);
1210
1211 if ((m_ep_dma_waiting | ((~m_ep_ready) & NRFX_USBD_EPIN_BIT_MASK))
1212 & (1U <<ep2bit(m_last_setup_dir)))
1213 {
1214 NRFX_LOG_DEBUG("USBD drv: Trying to abort last transfer on EP0");
1215 usbd_ep_abort(m_last_setup_dir);
1216 }
1217
1218 m_last_setup_dir =
1219 ((bmRequestType & USBD_BMREQUESTTYPE_DIRECTION_Msk) ==
1220 (USBD_BMREQUESTTYPE_DIRECTION_HostToDevice << USBD_BMREQUESTTYPE_DIRECTION_Pos)) ?
1221 NRFX_USBD_EPOUT0 : NRFX_USBD_EPIN0;
1222
1223 (void)(NRFX_ATOMIC_FETCH_AND(
1224 &m_ep_dma_waiting,
1225 ~((1U << ep2bit(NRFX_USBD_EPOUT0)) | (1U << ep2bit(NRFX_USBD_EPIN0)))));
1226 m_ep_ready |= 1U << ep2bit(NRFX_USBD_EPIN0);
1227
1228
1229 const nrfx_usbd_evt_t evt = {
1230 .type = NRFX_USBD_EVT_SETUP
1231 };
1232 m_event_handler(&evt);
1233 }
1234
ev_usbevent_handler(void)1235 static void ev_usbevent_handler(void)
1236 {
1237 uint32_t event = nrf_usbd_eventcause_get_and_clear(NRF_USBD);
1238
1239 if (event & NRF_USBD_EVENTCAUSE_ISOOUTCRC_MASK)
1240 {
1241 NRFX_LOG_DEBUG("USBD event: ISOOUTCRC");
1242 /* Currently no support */
1243 }
1244 if (event & NRF_USBD_EVENTCAUSE_SUSPEND_MASK)
1245 {
1246 NRFX_LOG_DEBUG("USBD event: SUSPEND");
1247 m_bus_suspend = true;
1248 const nrfx_usbd_evt_t evt = {
1249 .type = NRFX_USBD_EVT_SUSPEND
1250 };
1251 m_event_handler(&evt);
1252 }
1253 if (event & NRF_USBD_EVENTCAUSE_RESUME_MASK)
1254 {
1255 NRFX_LOG_DEBUG("USBD event: RESUME");
1256 m_bus_suspend = false;
1257 const nrfx_usbd_evt_t evt = {
1258 .type = NRFX_USBD_EVT_RESUME
1259 };
1260 m_event_handler(&evt);
1261 }
1262 if (event & NRF_USBD_EVENTCAUSE_WUREQ_MASK)
1263 {
1264 NRFX_LOG_DEBUG("USBD event: WUREQ (%s)", m_bus_suspend ? "In Suspend" : "Active");
1265 if (m_bus_suspend)
1266 {
1267 NRFX_ASSERT(!nrf_usbd_lowpower_check(NRF_USBD));
1268 m_bus_suspend = false;
1269
1270 nrf_usbd_dpdmvalue_set(NRF_USBD, NRF_USBD_DPDMVALUE_RESUME);
1271 nrf_usbd_task_trigger(NRF_USBD, NRF_USBD_TASK_DRIVEDPDM);
1272
1273 const nrfx_usbd_evt_t evt = {
1274 .type = NRFX_USBD_EVT_WUREQ
1275 };
1276 m_event_handler(&evt);
1277 }
1278 }
1279 }
1280
ev_epdata_handler(void)1281 static void ev_epdata_handler(void)
1282 {
1283 /* Get all endpoints that have acknowledged transfer */
1284 uint32_t dataepstatus = nrf_usbd_epdatastatus_get_and_clear(NRF_USBD);
1285 NRFX_LOG_DEBUG("USBD event: EndpointEPStatus: %x", dataepstatus);
1286
1287 /* All finished endpoint have to be marked as busy */
1288 while (dataepstatus)
1289 {
1290 uint8_t bitpos = (uint8_t)NRF_CTZ(dataepstatus);
1291 nrfx_usbd_ep_t ep = bit2ep(bitpos);
1292 dataepstatus &= ~(1UL << bitpos);
1293
1294 (void)(usbd_ep_data_handler(ep, bitpos));
1295 }
1296 if (NRFX_USBD_EARLY_DMA_PROCESS)
1297 {
1298 /* Speed up */
1299 usbd_dmareq_process();
1300 }
1301 }
1302
1303 /**
1304 * @brief Function to select the endpoint to start.
1305 *
1306 * Function that realizes algorithm to schedule right channel for EasyDMA transfer.
1307 * It gets a variable with flags for the endpoints currently requiring transfer.
1308 *
1309 * @param[in] req Bit flags for channels currently requiring transfer.
1310 * Bits 0...8 used for IN endpoints.
1311 * Bits 16...24 used for OUT endpoints.
1312 * @note
1313 * This function would be never called with 0 as a @c req argument.
1314 * @return The bit number of the endpoint that should be processed now.
1315 */
usbd_dma_scheduler_algorithm(uint32_t req)1316 static uint8_t usbd_dma_scheduler_algorithm(uint32_t req)
1317 {
1318 /* Only prioritized scheduling mode is supported. */
1319 return (uint8_t)NRF_CTZ(req);
1320 }
1321
1322 /**
1323 * @brief Get the size of isochronous endpoint.
1324 *
1325 * The size of isochronous endpoint is configurable.
1326 * This function returns the size of isochronous buffer taking into account
1327 * current configuration.
1328 *
1329 * @param[in] ep Endpoint number.
1330 *
1331 * @return The size of endpoint buffer.
1332 */
usbd_ep_iso_capacity(nrfx_usbd_ep_t ep)1333 static inline size_t usbd_ep_iso_capacity(nrfx_usbd_ep_t ep)
1334 {
1335 (void)ep;
1336 nrf_usbd_isosplit_t split = nrf_usbd_isosplit_get(NRF_USBD);
1337 if (NRF_USBD_ISOSPLIT_HALF == split)
1338 {
1339 return NRFX_USBD_ISOSIZE / 2;
1340 }
1341 return NRFX_USBD_ISOSIZE;
1342 }
1343
1344 /**
1345 * @brief Process all DMA requests.
1346 *
1347 * Function that have to be called from USBD interrupt handler.
1348 * It have to be called when all the interrupts connected with endpoints transfer
1349 * and DMA transfer are already handled.
1350 */
usbd_dmareq_process(void)1351 static void usbd_dmareq_process(void)
1352 {
1353 if (!m_dma_pending)
1354 {
1355 uint32_t req;
1356 while (0 != (req = m_ep_dma_waiting & m_ep_ready))
1357 {
1358 uint8_t pos;
1359 if (NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST && ((req & USBD_EPISO_BIT_MASK) != 0))
1360 {
1361 pos = usbd_dma_scheduler_algorithm(req & USBD_EPISO_BIT_MASK);
1362 }
1363 else
1364 {
1365 pos = usbd_dma_scheduler_algorithm(req);
1366 }
1367 nrfx_usbd_ep_t ep = bit2ep(pos);
1368 usbd_ep_state_t * p_state = ep_state_access(ep);
1369
1370 nrfx_usbd_ep_transfer_t transfer;
1371 bool continue_transfer;
1372
1373 NRFX_STATIC_ASSERT(offsetof(usbd_ep_state_t, handler.feeder) ==
1374 offsetof(usbd_ep_state_t, handler.consumer));
1375 NRFX_ASSERT((p_state->handler.feeder) != NULL);
1376
1377 if (NRF_USBD_EPIN_CHECK(ep))
1378 {
1379 /* Device -> Host */
1380 continue_transfer = p_state->handler.feeder(
1381 &transfer,
1382 p_state->p_context,
1383 p_state->max_packet_size);
1384
1385 if (!continue_transfer)
1386 {
1387 p_state->handler.feeder = NULL;
1388 }
1389 }
1390 else
1391 {
1392 /* Host -> Device */
1393 const size_t rx_size = nrfx_usbd_epout_size_get(ep);
1394 continue_transfer = p_state->handler.consumer(
1395 &transfer,
1396 p_state->p_context,
1397 p_state->max_packet_size,
1398 rx_size);
1399
1400 if (transfer.p_data.rx == NULL)
1401 {
1402 /* Dropping transfer - allow processing */
1403 NRFX_ASSERT(transfer.size == 0);
1404 }
1405 else if (transfer.size < rx_size)
1406 {
1407 NRFX_LOG_DEBUG("Endpoint %x overload (r: %u, e: %u)", ep, rx_size, transfer.size);
1408 p_state->status = NRFX_USBD_EP_OVERLOAD;
1409 (void)(NRFX_ATOMIC_FETCH_AND(&m_ep_dma_waiting, ~(1U << pos)));
1410 NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_OVERLOAD);
1411 m_event_handler(&evt);
1412 /* This endpoint will not be transmitted now, repeat the loop */
1413 continue;
1414 }
1415 else
1416 {
1417 /* Nothing to do - only check integrity if assertions are enabled */
1418 NRFX_ASSERT(transfer.size == rx_size);
1419 }
1420
1421 if (!continue_transfer)
1422 {
1423 p_state->handler.consumer = NULL;
1424 }
1425 }
1426
1427 usbd_dma_pending_set();
1428 m_ep_ready &= ~(1U << pos);
1429 if (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
1430 {
1431 NRFX_LOG_DEBUG(
1432 "USB DMA process: Starting transfer on EP: %x, size: %u",
1433 ep,
1434 transfer.size);
1435 }
1436 /* Update number of currently transferred bytes */
1437 p_state->transfer_cnt += transfer.size;
1438 /* Start transfer to the endpoint buffer */
1439 nrf_usbd_ep_easydma_set(NRF_USBD, ep, transfer.p_data.addr, (uint32_t)transfer.size);
1440
1441 usbd_dma_start(ep);
1442 /* There is a lot of USBD registers that cannot be accessed during EasyDMA transfer.
1443 * This is quick fix to maintain stability of the stack.
1444 * It cost some performance but makes stack stable. */
1445 while (!nrf_usbd_event_check(NRF_USBD, nrfx_usbd_ep_to_endevent(ep)))
1446 {
1447 /* Empty */
1448 }
1449 /* DMA finished, track if total bytes transferred is even or odd */
1450 m_dma_odd ^= nrf_usbd_ep_amount_get(NRF_USBD, ep) & 1;
1451
1452 if (NRFX_USBD_DMAREQ_PROCESS_DEBUG)
1453 {
1454 NRFX_LOG_DEBUG("USB DMA process - finishing");
1455 }
1456 /* Transfer started - exit the loop */
1457 break;
1458 }
1459 }
1460 else
1461 {
1462 if (NRFX_USBD_DMAREQ_PROCESS_DEBUG)
1463 {
1464 NRFX_LOG_DEBUG("USB DMA process - EasyDMA busy");
1465 }
1466 }
1467 }
1468
1469 /**
1470 * @brief Wait for a specified eventcause and clear it afterwards.
1471 */
usbd_eventcause_wait_and_clear(nrf_usbd_eventcause_mask_t eventcause)1472 static inline void usbd_eventcause_wait_and_clear(nrf_usbd_eventcause_mask_t eventcause)
1473 {
1474 while (0 == (eventcause & nrf_usbd_eventcause_get(NRF_USBD)))
1475 {
1476 /* Empty loop */
1477 }
1478 nrf_usbd_eventcause_clear(NRF_USBD, eventcause);
1479 }
1480
1481 /**
1482 * @brief Begin errata 171.
1483 */
usbd_errata_171_begin(void)1484 static inline void usbd_errata_171_begin(void)
1485 {
1486 NRFX_CRITICAL_SECTION_ENTER();
1487 if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
1488 {
1489 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1490 *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
1491 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1492 }
1493 else
1494 {
1495 *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
1496 }
1497 NRFX_CRITICAL_SECTION_EXIT();
1498 }
1499
1500 /**
1501 * @brief End errata 171.
1502 */
usbd_errata_171_end(void)1503 static inline void usbd_errata_171_end(void)
1504 {
1505 NRFX_CRITICAL_SECTION_ENTER();
1506 if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
1507 {
1508 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1509 *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
1510 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1511 }
1512 else
1513 {
1514 *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
1515 }
1516 NRFX_CRITICAL_SECTION_EXIT();
1517 }
1518
1519 /**
1520 * @brief Begin erratas 187 and 211.
1521 */
usbd_errata_187_211_begin(void)1522 static inline void usbd_errata_187_211_begin(void)
1523 {
1524 NRFX_CRITICAL_SECTION_ENTER();
1525 if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
1526 {
1527 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1528 *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
1529 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1530 }
1531 else
1532 {
1533 *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
1534 }
1535 NRFX_CRITICAL_SECTION_EXIT();
1536 }
1537
1538 /**
1539 * @brief End erratas 187 and 211.
1540 */
usbd_errata_187_211_end(void)1541 static inline void usbd_errata_187_211_end(void)
1542 {
1543 NRFX_CRITICAL_SECTION_ENTER();
1544 if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
1545 {
1546 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1547 *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
1548 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1549 }
1550 else
1551 {
1552 *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
1553 }
1554 NRFX_CRITICAL_SECTION_EXIT();
1555 }
1556
1557 /**
1558 * @brief Enable USBD peripheral.
1559 */
usbd_enable(void)1560 static void usbd_enable(void)
1561 {
1562 if (nrfx_usbd_errata_187())
1563 {
1564 usbd_errata_187_211_begin();
1565 }
1566
1567 if (nrfx_usbd_errata_171())
1568 {
1569 usbd_errata_171_begin();
1570 }
1571
1572 /* Enable the peripheral */
1573 nrf_usbd_enable(NRF_USBD);
1574
1575 /* Waiting for peripheral to enable, this should take a few us */
1576 usbd_eventcause_wait_and_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
1577
1578 if (nrfx_usbd_errata_171())
1579 {
1580 usbd_errata_171_end();
1581 }
1582
1583 if (nrfx_usbd_errata_187())
1584 {
1585 usbd_errata_187_211_end();
1586 }
1587 }
1588 /** @} */
1589
1590 /**
1591 * @brief USBD interrupt service routines.
1592 *
1593 */
1594 static const nrfx_irq_handler_t m_isr[] =
1595 {
1596 [USBD_INTEN_USBRESET_Pos ] = ev_usbreset_handler,
1597 [USBD_INTEN_STARTED_Pos ] = ev_started_handler,
1598 [USBD_INTEN_ENDEPIN0_Pos ] = ev_dma_epin0_handler,
1599 [USBD_INTEN_ENDEPIN1_Pos ] = ev_dma_epin1_handler,
1600 [USBD_INTEN_ENDEPIN2_Pos ] = ev_dma_epin2_handler,
1601 [USBD_INTEN_ENDEPIN3_Pos ] = ev_dma_epin3_handler,
1602 [USBD_INTEN_ENDEPIN4_Pos ] = ev_dma_epin4_handler,
1603 [USBD_INTEN_ENDEPIN5_Pos ] = ev_dma_epin5_handler,
1604 [USBD_INTEN_ENDEPIN6_Pos ] = ev_dma_epin6_handler,
1605 [USBD_INTEN_ENDEPIN7_Pos ] = ev_dma_epin7_handler,
1606 [USBD_INTEN_EP0DATADONE_Pos] = ev_setup_data_handler,
1607 [USBD_INTEN_ENDISOIN_Pos ] = ev_dma_epin8_handler,
1608 [USBD_INTEN_ENDEPOUT0_Pos ] = ev_dma_epout0_handler,
1609 [USBD_INTEN_ENDEPOUT1_Pos ] = ev_dma_epout1_handler,
1610 [USBD_INTEN_ENDEPOUT2_Pos ] = ev_dma_epout2_handler,
1611 [USBD_INTEN_ENDEPOUT3_Pos ] = ev_dma_epout3_handler,
1612 [USBD_INTEN_ENDEPOUT4_Pos ] = ev_dma_epout4_handler,
1613 [USBD_INTEN_ENDEPOUT5_Pos ] = ev_dma_epout5_handler,
1614 [USBD_INTEN_ENDEPOUT6_Pos ] = ev_dma_epout6_handler,
1615 [USBD_INTEN_ENDEPOUT7_Pos ] = ev_dma_epout7_handler,
1616 [USBD_INTEN_ENDISOOUT_Pos ] = ev_dma_epout8_handler,
1617 [USBD_INTEN_SOF_Pos ] = ev_sof_handler,
1618 [USBD_INTEN_USBEVENT_Pos ] = ev_usbevent_handler,
1619 [USBD_INTEN_EP0SETUP_Pos ] = ev_setup_handler,
1620 [USBD_INTEN_EPDATA_Pos ] = ev_epdata_handler
1621 };
1622
1623 /**
1624 * @name Interrupt handlers
1625 *
1626 * @{
1627 */
nrfx_usbd_irq_handler(void)1628 void nrfx_usbd_irq_handler(void)
1629 {
1630 const uint32_t enabled = nrf_usbd_int_enable_get(NRF_USBD);
1631 uint32_t to_process = enabled;
1632 uint32_t active = 0;
1633
1634 /* Check all enabled interrupts */
1635 while (to_process)
1636 {
1637 uint8_t event_nr = (uint8_t)NRF_CTZ(to_process);
1638 if (nrf_usbd_event_get_and_clear(NRF_USBD,
1639 (nrf_usbd_event_t)nrfx_bitpos_to_event(event_nr)))
1640 {
1641 active |= 1UL << event_nr;
1642 }
1643 to_process &= ~(1UL << event_nr);
1644 }
1645
1646 /* Process the active interrupts */
1647 bool setup_active = 0 != (active & NRF_USBD_INT_EP0SETUP_MASK);
1648 active &= (uint32_t)~NRF_USBD_INT_EP0SETUP_MASK;
1649
1650 while (active)
1651 {
1652 uint8_t event_nr = (uint8_t)NRF_CTZ(active);
1653 m_isr[event_nr]();
1654 active &= ~(1UL << event_nr);
1655 }
1656 usbd_dmareq_process();
1657
1658 if (setup_active)
1659 {
1660 m_isr[USBD_INTEN_EP0SETUP_Pos]();
1661 }
1662 }
1663
1664 /** @} */
1665 /** @} */
1666
nrfx_usbd_init(nrfx_usbd_event_handler_t event_handler)1667 nrfx_err_t nrfx_usbd_init(nrfx_usbd_event_handler_t event_handler)
1668 {
1669 NRFX_ASSERT(event_handler);
1670
1671 if (m_drv_state != NRFX_DRV_STATE_UNINITIALIZED)
1672 {
1673 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
1674 return NRFX_ERROR_ALREADY;
1675 #else
1676 return NRFX_ERROR_INVALID_STATE;
1677 #endif
1678 }
1679
1680 m_event_handler = event_handler;
1681 m_drv_state = NRFX_DRV_STATE_INITIALIZED;
1682
1683 uint8_t n;
1684 for (n = 0; n < NRF_USBD_EPIN_CNT; ++n)
1685 {
1686 nrfx_usbd_ep_t ep = NRFX_USBD_EPIN(n);
1687 nrfx_usbd_ep_max_packet_size_set(ep, NRF_USBD_EPISO_CHECK(ep) ?
1688 (NRFX_USBD_ISOSIZE / 2) : NRFX_USBD_EPSIZE);
1689 usbd_ep_state_t * p_state = ep_state_access(ep);
1690 p_state->status = NRFX_USBD_EP_OK;
1691 p_state->handler.feeder = NULL;
1692 p_state->transfer_cnt = 0;
1693 }
1694 for (n = 0; n < NRF_USBD_EPOUT_CNT; ++n)
1695 {
1696 nrfx_usbd_ep_t ep = NRFX_USBD_EPOUT(n);
1697 nrfx_usbd_ep_max_packet_size_set(ep, NRF_USBD_EPISO_CHECK(ep) ?
1698 (NRFX_USBD_ISOSIZE / 2) : NRFX_USBD_EPSIZE);
1699 usbd_ep_state_t * p_state = ep_state_access(ep);
1700 p_state->status = NRFX_USBD_EP_OK;
1701 p_state->handler.consumer = NULL;
1702 p_state->transfer_cnt = 0;
1703 }
1704
1705 return NRFX_SUCCESS;
1706 }
1707
nrfx_usbd_uninit(void)1708 void nrfx_usbd_uninit(void)
1709 {
1710 NRFX_ASSERT(m_drv_state == NRFX_DRV_STATE_INITIALIZED);
1711
1712 m_event_handler = NULL;
1713 m_drv_state = NRFX_DRV_STATE_UNINITIALIZED;
1714 return;
1715 }
1716
nrfx_usbd_init_check(void)1717 bool nrfx_usbd_init_check(void)
1718 {
1719 return (m_drv_state != NRFX_DRV_STATE_UNINITIALIZED);
1720 }
1721
nrfx_usbd_enable(void)1722 void nrfx_usbd_enable(void)
1723 {
1724 NRFX_ASSERT(m_drv_state == NRFX_DRV_STATE_INITIALIZED);
1725
1726 /* Prepare for READY event receiving */
1727 nrf_usbd_eventcause_clear(NRF_USBD, NRF_USBD_EVENTCAUSE_READY_MASK);
1728
1729 usbd_enable();
1730
1731 if (nrfx_usbd_errata_223() && m_first_enable)
1732 {
1733 nrf_usbd_disable(NRF_USBD);
1734
1735 usbd_enable();
1736
1737 m_first_enable = false;
1738 }
1739
1740 #if NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211
1741 if (nrfx_usbd_errata_187() || nrfx_usbd_errata_211())
1742 #else
1743 if (nrfx_usbd_errata_187())
1744 #endif
1745 {
1746 usbd_errata_187_211_begin();
1747 }
1748
1749 if (nrfx_usbd_errata_166())
1750 {
1751 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x800)) = 0x7E3;
1752 *((volatile uint32_t *)((uint32_t)(NRF_USBD) + 0x804)) = 0x40;
1753 __ISB();
1754 __DSB();
1755 }
1756
1757 nrf_usbd_isosplit_set(NRF_USBD, NRF_USBD_ISOSPLIT_HALF);
1758
1759 if (NRFX_USBD_CONFIG_ISO_IN_ZLP)
1760 {
1761 nrfx_usbd_isoinconfig_set(NRF_USBD_ISOINCONFIG_ZERODATA);
1762 }
1763 else
1764 {
1765 nrfx_usbd_isoinconfig_set(NRF_USBD_ISOINCONFIG_NORESP);
1766 }
1767
1768 m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << NRFX_USBD_EPIN_BITPOS_0);
1769 m_ep_dma_waiting = 0;
1770 m_dma_odd = 0;
1771 usbd_dma_pending_clear();
1772 m_last_setup_dir = NRFX_USBD_EPOUT0;
1773
1774 m_drv_state = NRFX_DRV_STATE_POWERED_ON;
1775
1776 #if NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211
1777 if (nrfx_usbd_errata_187() && !nrfx_usbd_errata_211())
1778 #else
1779 if (nrfx_usbd_errata_187())
1780 #endif
1781 {
1782 usbd_errata_187_211_end();
1783 }
1784 }
1785
nrfx_usbd_disable(void)1786 void nrfx_usbd_disable(void)
1787 {
1788 NRFX_ASSERT(m_drv_state != NRFX_DRV_STATE_UNINITIALIZED);
1789
1790 /* Stop just in case */
1791 nrfx_usbd_stop();
1792
1793 /* Disable all parts */
1794 nrf_usbd_int_disable(NRF_USBD, nrf_usbd_int_enable_get(NRF_USBD));
1795 if (m_dma_odd)
1796 {
1797 /* Prevent invalid bus request after next USBD enable by ensuring
1798 * that total number of bytes transferred by DMA is even. */
1799 nrf_usbd_event_clear(NRF_USBD, NRF_USBD_EVENT_ENDEPIN0);
1800 nrf_usbd_ep_easydma_set(NRF_USBD, NRFX_USBD_EPIN0, (uint32_t)&m_dma_odd, 1);
1801 usbd_dma_start(NRFX_USBD_EPIN0);
1802 while (!nrf_usbd_event_check(NRF_USBD, NRF_USBD_EVENT_ENDEPIN0))
1803 {}
1804 m_dma_odd = 0;
1805 }
1806 nrf_usbd_disable(NRF_USBD);
1807 usbd_dma_pending_clear();
1808 m_drv_state = NRFX_DRV_STATE_INITIALIZED;
1809
1810 #if NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211
1811 if (nrfx_usbd_errata_211())
1812 {
1813 usbd_errata_187_211_end();
1814 }
1815 #endif
1816 }
1817
nrfx_usbd_start(bool enable_sof)1818 void nrfx_usbd_start(bool enable_sof)
1819 {
1820 NRFX_ASSERT(m_drv_state == NRFX_DRV_STATE_POWERED_ON);
1821 m_bus_suspend = false;
1822
1823 uint32_t ints_to_enable =
1824 NRF_USBD_INT_USBRESET_MASK |
1825 #if NRFX_USBD_STARTED_EV_ENABLE
1826 NRF_USBD_INT_STARTED_MASK |
1827 #endif
1828 NRF_USBD_INT_ENDEPIN0_MASK |
1829 NRF_USBD_INT_EP0DATADONE_MASK |
1830 NRF_USBD_INT_ENDEPOUT0_MASK |
1831 NRF_USBD_INT_USBEVENT_MASK |
1832 NRF_USBD_INT_EP0SETUP_MASK |
1833 NRF_USBD_INT_DATAEP_MASK;
1834
1835 if (enable_sof)
1836 {
1837 ints_to_enable |= NRF_USBD_INT_SOF_MASK;
1838 }
1839
1840 /* Enable all required interrupts */
1841 nrf_usbd_int_enable(NRF_USBD, ints_to_enable);
1842
1843 /* Enable interrupt globally */
1844 NRFX_IRQ_PRIORITY_SET(USBD_IRQn, NRFX_USBD_DEFAULT_CONFIG_IRQ_PRIORITY);
1845 NRFX_IRQ_ENABLE(USBD_IRQn);
1846
1847 /* Enable pullups */
1848 nrf_usbd_pullup_enable(NRF_USBD);
1849 }
1850
nrfx_usbd_stop(void)1851 void nrfx_usbd_stop(void)
1852 {
1853 NRFX_ASSERT(m_drv_state == NRFX_DRV_STATE_POWERED_ON);
1854
1855 /* Clear interrupt */
1856 NRFX_IRQ_PENDING_CLEAR(USBD_IRQn);
1857
1858 if (NRFX_IRQ_IS_ENABLED(USBD_IRQn))
1859 {
1860 /* Abort transfers */
1861 usbd_ep_abort_all();
1862
1863 /* Disable pullups */
1864 nrf_usbd_pullup_disable(NRF_USBD);
1865
1866 /* Disable interrupt globally */
1867 NRFX_IRQ_DISABLE(USBD_IRQn);
1868
1869 /* Disable all interrupts */
1870 nrf_usbd_int_disable(NRF_USBD, ~0U);
1871 }
1872 }
1873
nrfx_usbd_is_initialized(void)1874 bool nrfx_usbd_is_initialized(void)
1875 {
1876 return (m_drv_state >= NRFX_DRV_STATE_INITIALIZED);
1877 }
1878
nrfx_usbd_is_enabled(void)1879 bool nrfx_usbd_is_enabled(void)
1880 {
1881 return (m_drv_state >= NRFX_DRV_STATE_POWERED_ON);
1882 }
1883
nrfx_usbd_is_started(void)1884 bool nrfx_usbd_is_started(void)
1885 {
1886 return (nrfx_usbd_is_enabled() && NRFX_IRQ_IS_ENABLED(USBD_IRQn));
1887 }
1888
nrfx_usbd_suspend(void)1889 bool nrfx_usbd_suspend(void)
1890 {
1891 bool suspended = false;
1892
1893 NRFX_CRITICAL_SECTION_ENTER();
1894 if (m_bus_suspend)
1895 {
1896 if (!(nrf_usbd_eventcause_get(NRF_USBD) & NRF_USBD_EVENTCAUSE_RESUME_MASK))
1897 {
1898 nrf_usbd_lowpower_enable(NRF_USBD);
1899 if (nrf_usbd_eventcause_get(NRF_USBD) & NRF_USBD_EVENTCAUSE_RESUME_MASK)
1900 {
1901 nrf_usbd_lowpower_disable(NRF_USBD);
1902 }
1903 else
1904 {
1905 suspended = true;
1906 }
1907 }
1908 }
1909 NRFX_CRITICAL_SECTION_EXIT();
1910
1911 return suspended;
1912 }
1913
nrfx_usbd_wakeup_req(void)1914 bool nrfx_usbd_wakeup_req(void)
1915 {
1916 bool started = false;
1917
1918 NRFX_CRITICAL_SECTION_ENTER();
1919 if (m_bus_suspend && nrf_usbd_lowpower_check(NRF_USBD))
1920 {
1921 nrf_usbd_lowpower_disable(NRF_USBD);
1922 started = true;
1923
1924 if (nrfx_usbd_errata_171())
1925 {
1926 if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
1927 {
1928 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1929 *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
1930 *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
1931 }
1932 else
1933 {
1934 *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
1935 }
1936
1937 }
1938 }
1939 NRFX_CRITICAL_SECTION_EXIT();
1940
1941 return started;
1942 }
1943
nrfx_usbd_suspend_check(void)1944 bool nrfx_usbd_suspend_check(void)
1945 {
1946 return nrf_usbd_lowpower_check(NRF_USBD);
1947 }
1948
nrfx_usbd_suspend_irq_config(void)1949 void nrfx_usbd_suspend_irq_config(void)
1950 {
1951 nrf_usbd_int_disable(NRF_USBD, m_irq_disabled_in_suspend);
1952 }
1953
nrfx_usbd_active_irq_config(void)1954 void nrfx_usbd_active_irq_config(void)
1955 {
1956 nrf_usbd_int_enable(NRF_USBD, m_irq_disabled_in_suspend);
1957 }
1958
nrfx_usbd_bus_suspend_check(void)1959 bool nrfx_usbd_bus_suspend_check(void)
1960 {
1961 return m_bus_suspend;
1962 }
1963
nrfx_usbd_force_bus_wakeup(void)1964 void nrfx_usbd_force_bus_wakeup(void)
1965 {
1966 m_bus_suspend = false;
1967 }
1968
nrfx_usbd_ep_max_packet_size_set(nrfx_usbd_ep_t ep,uint16_t size)1969 void nrfx_usbd_ep_max_packet_size_set(nrfx_usbd_ep_t ep, uint16_t size)
1970 {
1971 /* Only the power of 2 size allowed for Control Endpoints */
1972 NRFX_ASSERT((((size & (size - 1)) == 0) || (NRF_USBD_EP_NR_GET(ep) != 0)));
1973 /* Only non zero size allowed for Control Endpoints */
1974 NRFX_ASSERT((size != 0) || (NRF_USBD_EP_NR_GET(ep) != 0));
1975 /* Packet size cannot be higher than maximum buffer size */
1976 NRFX_ASSERT((NRF_USBD_EPISO_CHECK(ep) && (size <= usbd_ep_iso_capacity(ep))) ||
1977 (!NRF_USBD_EPISO_CHECK(ep) && (size <= NRFX_USBD_EPSIZE)));
1978
1979 usbd_ep_state_t * p_state = ep_state_access(ep);
1980 p_state->max_packet_size = size;
1981 }
1982
nrfx_usbd_ep_max_packet_size_get(nrfx_usbd_ep_t ep)1983 uint16_t nrfx_usbd_ep_max_packet_size_get(nrfx_usbd_ep_t ep)
1984 {
1985 usbd_ep_state_t const * p_state = ep_state_access(ep);
1986 return p_state->max_packet_size;
1987 }
1988
nrfx_usbd_ep_enable_check(nrfx_usbd_ep_t ep)1989 bool nrfx_usbd_ep_enable_check(nrfx_usbd_ep_t ep)
1990 {
1991 return nrf_usbd_ep_enable_check(NRF_USBD, ep_to_hal(ep));
1992 }
1993
nrfx_usbd_ep_enable(nrfx_usbd_ep_t ep)1994 void nrfx_usbd_ep_enable(nrfx_usbd_ep_t ep)
1995 {
1996 nrf_usbd_int_enable(NRF_USBD, nrfx_usbd_ep_to_int(ep));
1997
1998 if (nrf_usbd_ep_enable_check(NRF_USBD, ep))
1999 {
2000 return;
2001 }
2002 nrf_usbd_ep_enable(NRF_USBD, ep_to_hal(ep));
2003 if ((NRF_USBD_EP_NR_GET(ep) != 0) &&
2004 NRF_USBD_EPOUT_CHECK(ep) &&
2005 !NRF_USBD_EPISO_CHECK(ep))
2006 {
2007 NRFX_CRITICAL_SECTION_ENTER();
2008 nrfx_usbd_transfer_out_drop(ep);
2009 m_ep_dma_waiting &= ~(1U << ep2bit(ep));
2010 NRFX_CRITICAL_SECTION_EXIT();
2011 }
2012 }
2013
nrfx_usbd_ep_disable(nrfx_usbd_ep_t ep)2014 void nrfx_usbd_ep_disable(nrfx_usbd_ep_t ep)
2015 {
2016 usbd_ep_abort(ep);
2017 nrf_usbd_ep_disable(NRF_USBD, ep_to_hal(ep));
2018 nrf_usbd_int_disable(NRF_USBD, nrfx_usbd_ep_to_int(ep));
2019 }
2020
nrfx_usbd_ep_default_config(void)2021 void nrfx_usbd_ep_default_config(void)
2022 {
2023 nrf_usbd_int_disable(NRF_USBD, NRF_USBD_INT_ENDEPIN1_MASK |
2024 NRF_USBD_INT_ENDEPIN2_MASK |
2025 NRF_USBD_INT_ENDEPIN3_MASK |
2026 NRF_USBD_INT_ENDEPIN4_MASK |
2027 NRF_USBD_INT_ENDEPIN5_MASK |
2028 NRF_USBD_INT_ENDEPIN6_MASK |
2029 NRF_USBD_INT_ENDEPIN7_MASK |
2030 NRF_USBD_INT_ENDISOIN0_MASK |
2031 NRF_USBD_INT_ENDEPOUT1_MASK |
2032 NRF_USBD_INT_ENDEPOUT2_MASK |
2033 NRF_USBD_INT_ENDEPOUT3_MASK |
2034 NRF_USBD_INT_ENDEPOUT4_MASK |
2035 NRF_USBD_INT_ENDEPOUT5_MASK |
2036 NRF_USBD_INT_ENDEPOUT6_MASK |
2037 NRF_USBD_INT_ENDEPOUT7_MASK |
2038 NRF_USBD_INT_ENDISOOUT0_MASK
2039 );
2040 nrf_usbd_int_enable(NRF_USBD, NRF_USBD_INT_ENDEPIN0_MASK | NRF_USBD_INT_ENDEPOUT0_MASK);
2041 nrf_usbd_ep_default_config(NRF_USBD);
2042 }
2043
nrfx_usbd_ep_transfer(nrfx_usbd_ep_t ep,nrfx_usbd_transfer_t const * p_transfer)2044 nrfx_err_t nrfx_usbd_ep_transfer(
2045 nrfx_usbd_ep_t ep,
2046 nrfx_usbd_transfer_t const * p_transfer)
2047 {
2048 nrfx_err_t ret;
2049 const uint8_t ep_bitpos = ep2bit(ep);
2050 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2051 char * p_mode = "";
2052 #endif
2053
2054 NRFX_ASSERT(NULL != p_transfer);
2055
2056 NRFX_CRITICAL_SECTION_ENTER();
2057 /* Setup data transaction can go only in one direction at a time */
2058 if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir))
2059 {
2060 ret = NRFX_ERROR_INVALID_ADDR;
2061 }
2062 else if ((m_ep_dma_waiting | ((~m_ep_ready) & NRFX_USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos))
2063 {
2064 /* IN (Device -> Host) transfer has to be transmitted out to allow new transmission */
2065 ret = NRFX_ERROR_BUSY;
2066 }
2067 else
2068 {
2069 usbd_ep_state_t * p_state = ep_state_access(ep);
2070 /* Prepare transfer context and handler description */
2071 nrfx_usbd_transfer_t * p_context;
2072 if (NRF_USBD_EPIN_CHECK(ep))
2073 {
2074 p_context = m_ep_feeder_state + NRF_USBD_EP_NR_GET(ep);
2075 if (nrfx_is_in_ram(p_transfer->p_data.tx))
2076 {
2077 /* RAM */
2078 if (0 == (p_transfer->flags & NRFX_USBD_TRANSFER_ZLP_FLAG))
2079 {
2080 p_state->handler.feeder = nrfx_usbd_feeder_ram;
2081 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2082 if (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
2083 {
2084 p_mode = "RAM";
2085 }
2086 #endif
2087 }
2088 else
2089 {
2090 p_state->handler.feeder = nrfx_usbd_feeder_ram_zlp;
2091 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2092 if (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
2093 {
2094 p_mode = "RAM_ZLP";
2095 }
2096 #endif
2097 }
2098 }
2099 else
2100 {
2101 /* Flash */
2102 if (0 == (p_transfer->flags & NRFX_USBD_TRANSFER_ZLP_FLAG))
2103 {
2104 p_state->handler.feeder = nrfx_usbd_feeder_flash;
2105 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2106 if (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
2107 {
2108 p_mode = "FLASH";
2109 }
2110 #endif
2111 }
2112 else
2113 {
2114 p_state->handler.feeder = nrfx_usbd_feeder_flash_zlp;
2115 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2116 if (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))
2117 {
2118 p_mode = "FLASH_ZLP";
2119 }
2120 #endif
2121 }
2122 }
2123 }
2124 else
2125 {
2126 p_context = m_ep_consumer_state + NRF_USBD_EP_NR_GET(ep);
2127 NRFX_ASSERT((p_transfer->p_data.rx == NULL) || (nrfx_is_in_ram(p_transfer->p_data.rx)));
2128 p_state->handler.consumer = nrfx_usbd_consumer;
2129 }
2130 *p_context = *p_transfer;
2131 p_state->p_context = p_context;
2132
2133 p_state->transfer_cnt = 0;
2134 p_state->status = NRFX_USBD_EP_OK;
2135 m_ep_dma_waiting |= 1U << ep_bitpos;
2136 ret = NRFX_SUCCESS;
2137 usbd_int_rise();
2138 }
2139 NRFX_CRITICAL_SECTION_EXIT();
2140
2141 if ((ret == NRFX_SUCCESS) &&
2142 (NRFX_USBD_ISO_DEBUG || !NRF_USBD_EPISO_CHECK(ep)))
2143 {
2144 #if NRFX_USBD_CONFIG_LOG_LEVEL > 3
2145 NRFX_LOG_DEBUG("Transfer called on endpoint %x, size: %u, mode: %s", ep, p_transfer->size, p_mode);
2146 #endif
2147 }
2148 else if (NRFX_USBD_FAILED_TRANSFERS_DEBUG &&
2149 (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))))
2150 {
2151 if (ret == NRFX_ERROR_BUSY)
2152 {
2153 NRFX_LOG_DEBUG("Transfer failed: EP is busy");
2154 }
2155 else if (ret == NRFX_ERROR_INVALID_ADDR)
2156 {
2157 NRFX_LOG_DEBUG("Transfer failed: Invalid EP");
2158 }
2159 }
2160
2161 return ret;
2162 }
2163
nrfx_usbd_ep_handled_transfer(nrfx_usbd_ep_t ep,nrfx_usbd_handler_desc_t const * p_handler)2164 nrfx_err_t nrfx_usbd_ep_handled_transfer(
2165 nrfx_usbd_ep_t ep,
2166 nrfx_usbd_handler_desc_t const * p_handler)
2167 {
2168 nrfx_err_t ret;
2169 const uint8_t ep_bitpos = ep2bit(ep);
2170 NRFX_ASSERT(NULL != p_handler);
2171
2172 NRFX_CRITICAL_SECTION_ENTER();
2173 /* Setup data transaction can go only in one direction at a time */
2174 if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir))
2175 {
2176 ret = NRFX_ERROR_INVALID_ADDR;
2177 }
2178 else if ((m_ep_dma_waiting | ((~m_ep_ready) & NRFX_USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos))
2179 {
2180 /* IN (Device -> Host) transfer has to be transmitted out to allow a new transmission */
2181 ret = NRFX_ERROR_BUSY;
2182 }
2183 else
2184 {
2185 /* Transfer can be configured now */
2186 usbd_ep_state_t * p_state = ep_state_access(ep);
2187
2188 p_state->transfer_cnt = 0;
2189 p_state->handler = p_handler->handler;
2190 p_state->p_context = p_handler->p_context;
2191 p_state->status = NRFX_USBD_EP_OK;
2192 m_ep_dma_waiting |= 1U << ep_bitpos;
2193
2194 ret = NRFX_SUCCESS;
2195 usbd_int_rise();
2196 }
2197 NRFX_CRITICAL_SECTION_EXIT();
2198
2199 if ((ret == NRFX_SUCCESS) &&
2200 (NRFX_USBD_ISO_DEBUG || !NRF_USBD_EPISO_CHECK(ep)))
2201 {
2202 NRFX_LOG_DEBUG("Transfer called on endpoint %x, mode: Handler", ep);
2203 }
2204 else if (NRFX_USBD_FAILED_TRANSFERS_DEBUG &&
2205 (NRFX_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))))
2206 {
2207 if (ret == NRFX_ERROR_BUSY)
2208 {
2209 NRFX_LOG_DEBUG("Transfer failed: EP is busy");
2210 }
2211 else if (ret == NRFX_ERROR_INVALID_ADDR)
2212 {
2213 NRFX_LOG_DEBUG("Transfer failed: Invalid EP");
2214 }
2215 }
2216
2217 return ret;
2218 }
2219
nrfx_usbd_feeder_buffer_get(void)2220 void * nrfx_usbd_feeder_buffer_get(void)
2221 {
2222 return m_tx_buffer;
2223 }
2224
nrfx_usbd_ep_status_get(nrfx_usbd_ep_t ep,size_t * p_size)2225 nrfx_usbd_ep_status_t nrfx_usbd_ep_status_get(nrfx_usbd_ep_t ep, size_t * p_size)
2226 {
2227 nrfx_usbd_ep_status_t ret;
2228
2229 usbd_ep_state_t const * p_state = ep_state_access(ep);
2230 NRFX_CRITICAL_SECTION_ENTER();
2231 *p_size = p_state->transfer_cnt;
2232 ret = (p_state->handler.consumer == NULL) ? p_state->status : NRFX_USBD_EP_BUSY;
2233 NRFX_CRITICAL_SECTION_EXIT();
2234 return ret;
2235 }
2236
nrfx_usbd_epout_size_get(nrfx_usbd_ep_t ep)2237 size_t nrfx_usbd_epout_size_get(nrfx_usbd_ep_t ep)
2238 {
2239 return nrf_usbd_epout_size_get(NRF_USBD, ep_to_hal(ep));
2240 }
2241
nrfx_usbd_ep_is_busy(nrfx_usbd_ep_t ep)2242 bool nrfx_usbd_ep_is_busy(nrfx_usbd_ep_t ep)
2243 {
2244 return (0 != ((m_ep_dma_waiting | ((~m_ep_ready) & NRFX_USBD_EPIN_BIT_MASK)) & (1U << ep2bit(ep))));
2245 }
2246
nrfx_usbd_ep_stall(nrfx_usbd_ep_t ep)2247 void nrfx_usbd_ep_stall(nrfx_usbd_ep_t ep)
2248 {
2249 NRFX_LOG_DEBUG("USB: EP %x stalled.", ep);
2250 nrf_usbd_ep_stall(NRF_USBD, ep_to_hal(ep));
2251 }
2252
nrfx_usbd_ep_stall_clear(nrfx_usbd_ep_t ep)2253 void nrfx_usbd_ep_stall_clear(nrfx_usbd_ep_t ep)
2254 {
2255 if (NRF_USBD_EPOUT_CHECK(ep) && nrfx_usbd_ep_stall_check(ep))
2256 {
2257 nrfx_usbd_transfer_out_drop(ep);
2258 }
2259 nrf_usbd_ep_unstall(NRF_USBD, ep_to_hal(ep));
2260 }
2261
nrfx_usbd_ep_stall_check(nrfx_usbd_ep_t ep)2262 bool nrfx_usbd_ep_stall_check(nrfx_usbd_ep_t ep)
2263 {
2264 return nrf_usbd_ep_is_stall(NRF_USBD, ep_to_hal(ep));
2265 }
2266
nrfx_usbd_ep_dtoggle_clear(nrfx_usbd_ep_t ep)2267 void nrfx_usbd_ep_dtoggle_clear(nrfx_usbd_ep_t ep)
2268 {
2269 nrf_usbd_dtoggle_set(NRF_USBD, ep, NRF_USBD_DTOGGLE_DATA0);
2270 }
2271
nrfx_usbd_setup_get(nrfx_usbd_setup_t * p_setup)2272 void nrfx_usbd_setup_get(nrfx_usbd_setup_t * p_setup)
2273 {
2274 memset(p_setup, 0, sizeof(nrfx_usbd_setup_t));
2275 p_setup->bmRequestType = nrf_usbd_setup_bmrequesttype_get(NRF_USBD);
2276 p_setup->bRequest = nrf_usbd_setup_brequest_get(NRF_USBD);
2277 p_setup->wValue = nrf_usbd_setup_wvalue_get(NRF_USBD);
2278 p_setup->wIndex = nrf_usbd_setup_windex_get(NRF_USBD);
2279 p_setup->wLength = nrf_usbd_setup_wlength_get(NRF_USBD);
2280 }
2281
nrfx_usbd_setup_data_clear(void)2282 void nrfx_usbd_setup_data_clear(void)
2283 {
2284 nrf_usbd_task_trigger(NRF_USBD, NRF_USBD_TASK_EP0RCVOUT);
2285 }
2286
nrfx_usbd_setup_clear(void)2287 void nrfx_usbd_setup_clear(void)
2288 {
2289 NRFX_LOG_DEBUG(">> ep0status >>");
2290 nrf_usbd_task_trigger(NRF_USBD, NRF_USBD_TASK_EP0STATUS);
2291 }
2292
nrfx_usbd_setup_stall(void)2293 void nrfx_usbd_setup_stall(void)
2294 {
2295 NRFX_LOG_DEBUG("Setup stalled.");
2296 nrf_usbd_task_trigger(NRF_USBD, NRF_USBD_TASK_EP0STALL);
2297 }
2298
nrfx_usbd_last_setup_dir_get(void)2299 nrfx_usbd_ep_t nrfx_usbd_last_setup_dir_get(void)
2300 {
2301 return m_last_setup_dir;
2302 }
2303
nrfx_usbd_transfer_out_drop(nrfx_usbd_ep_t ep)2304 void nrfx_usbd_transfer_out_drop(nrfx_usbd_ep_t ep)
2305 {
2306 NRFX_ASSERT(NRF_USBD_EPOUT_CHECK(ep));
2307
2308 NRFX_CRITICAL_SECTION_ENTER();
2309 m_ep_ready &= ~(1U << ep2bit(ep));
2310 if (!NRF_USBD_EPISO_CHECK(ep))
2311 {
2312 nrf_usbd_epout_clear(NRF_USBD, ep);
2313 }
2314 NRFX_CRITICAL_SECTION_EXIT();
2315 }
2316
2317 #endif // NRFX_CHECK(NRFX_USBD_ENABLED)
2318