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