| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2018-03-26 22:48:53 +07:00
										 |  |  |     @file     dcd_nrf5x.c | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  |     @author   hathach | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @section LICENSE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Software License Agreement (BSD License) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  |     Copyright (c) 2018, hathach (tinyusb.org) | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  |     All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |     notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |     notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |     documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  |     3. Neither the name of the copyright holders nor the | 
					
						
							|  |  |  |     names of its contributors may be used to endorse or promote products | 
					
						
							|  |  |  |     derived from this software without specific prior written permission. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY | 
					
						
							|  |  |  |     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
					
						
							|  |  |  |     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | 
					
						
							|  |  |  |     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  |     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
					
						
							|  |  |  |     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  |     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  |     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 13:14:59 +07:00
										 |  |  | #include "tusb_option.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if MODE_DEVICE_SUPPORTED && CFG_TUSB_MCU == OPT_MCU_NRF5X
 | 
					
						
							| 
									
										
										
										
											2018-03-26 22:54:34 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  | // TODO remove
 | 
					
						
							|  |  |  | #include "nrf.h"
 | 
					
						
							|  |  |  | #include "nrf_power.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | #include "nrf_usbd.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-20 19:52:21 +07:00
										 |  |  | #include "nrf_clock.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | #include "nrf_drv_usbd_errata.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:44:39 +07:00
										 |  |  | #include "device/dcd.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /* MACRO TYPEDEF CONSTANT ENUM
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Max allowed by USB specs
 | 
					
						
							|  |  |  |   MAX_PACKET_SIZE   = 64, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Mask of all END event (IN & OUT) for all endpoints. ENDEPIN0-7, ENDEPOUT0-7, ENDISOIN, ENDISOOUT
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |   EDPT_END_ALL_MASK = 0x1FFBFCUL | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:30:53 +07:00
										 |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /* VARIABLE DECLARATION
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | typedef struct | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint8_t* buffer; | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   uint16_t total_len; | 
					
						
							|  |  |  |   uint16_t actual_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint8_t  mps; // max packet size
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // FIXME Errata 104 walkaround
 | 
					
						
							|  |  |  |   uint16_t frame_num; | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |   uint8_t  prev_size; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | } nom_xfer_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*static*/ struct | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | { | 
					
						
							|  |  |  |   struct | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     uint8_t* buffer; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     uint16_t len; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |     uint8_t  dir; | 
					
						
							|  |  |  |   }control; | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   // Non control: 7 endpoints IN & OUT (offset 1)
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |   nom_xfer_t xfer[7][2]; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  |   volatile bool dma_running; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | }_dcd; | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | void bus_reset(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for(int i=0; i<8; i++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->TASKS_STARTEPIN[i] = 0; | 
					
						
							|  |  |  |     NRF_USBD->TASKS_STARTEPOUT[i] = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NRF_USBD->TASKS_STARTISOIN  = 0; | 
					
						
							|  |  |  |   NRF_USBD->TASKS_STARTISOOUT = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   varclr(&_dcd); | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /* Controller API
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | bool dcd_init (uint8_t rhport) | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-04 16:48:52 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-04-05 18:36:59 +07:00
										 |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_connect (uint8_t rhport) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_disconnect (uint8_t rhport) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_set_address (uint8_t rhport, uint8_t dev_addr) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   // Set Address is automatically update by hw controller
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_set_config (uint8_t rhport, uint8_t config_num) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   (void) config_num; | 
					
						
							|  |  |  |   // Nothing to do
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /* Control
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | static void edpt_dma_start(uint8_t epnum, uint8_t dir) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |   // Only one dma could be active, TODO resolve when this is called in ISR and dma is running
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |   while ( _dcd.dma_running )  | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     TU_ASSERT ( 0 == (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk), ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   _dcd.dma_running = true; | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( dir == TUSB_DIR_OUT ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->TASKS_STARTEPOUT[epnum] = 1; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->TASKS_STARTEPIN[epnum] = 1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   __ISB(); __DSB(); | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void edpt_dma_end(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   _dcd.dma_running = false; | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void control_xact_start(void) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |   // Each transaction is up to 64 bytes
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   uint8_t const xact_len = min16_of(_dcd.control.len, MAX_PACKET_SIZE); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   if ( _dcd.control.dir == TUSB_DIR_OUT ) | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     // TODO control out
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     NRF_USBD->EPOUT[0].PTR    = (uint32_t) _dcd.control.buffer; | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     NRF_USBD->EPOUT[0].MAXCNT = xact_len; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     NRF_USBD->TASKS_EP0RCVOUT = 1; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     __ISB(); __DSB(); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     NRF_USBD->EPIN[0].PTR        = (uint32_t) _dcd.control.buffer; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |     NRF_USBD->EPIN[0].MAXCNT     = xact_len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  |     edpt_dma_start(0, TUSB_DIR_IN); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   _dcd.control.buffer += xact_len; | 
					
						
							|  |  |  |   _dcd.control.len    -= xact_len; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_t length) | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( length ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Data Phase
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     _dcd.control.len    = length; | 
					
						
							|  |  |  |     _dcd.control.buffer = buffer; | 
					
						
							|  |  |  |     _dcd.control.dir    = (uint8_t) dir; | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     control_xact_start(); | 
					
						
							|  |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Status Phase
 | 
					
						
							|  |  |  |     NRF_USBD->TASKS_EP0STATUS = 1; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     __ISB(); __DSB(); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  | static inline nom_xfer_t* get_td(uint8_t epnum, uint8_t dir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return &_dcd.xfer[epnum-1][dir]; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  | static void normal_xact_start(uint8_t epnum, uint8_t dir) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   if ( dir == TUSB_DIR_OUT ) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |     // Errata : HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
 | 
					
						
							| 
									
										
										
										
											2018-03-20 18:33:06 +07:00
										 |  |  |     // use the back door interface as sdk for walk around
 | 
					
						
							| 
									
										
										
										
											2018-03-20 19:52:21 +07:00
										 |  |  |     if ( nrf_drv_usbd_errata_sizeepout_rw() ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + 2*epnum; | 
					
						
							|  |  |  |       *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0; | 
					
						
							|  |  |  |       (void) (((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Overwrite size will allow hw to accept data
 | 
					
						
							|  |  |  |       NRF_USBD->SIZE.EPOUT[epnum] = 0; | 
					
						
							|  |  |  |       __ISB(); __DSB(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |     nom_xfer_t* xfer = get_td(epnum, dir); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Each transaction is up to Max Packet Size
 | 
					
						
							|  |  |  |     uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     NRF_USBD->EPIN[epnum].PTR    = (uint32_t) xfer->buffer; | 
					
						
							|  |  |  |     NRF_USBD->EPIN[epnum].MAXCNT = xact_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     xfer->buffer += xact_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     edpt_dma_start(epnum, TUSB_DIR_IN); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress); | 
					
						
							|  |  |  |   uint8_t const dir   = edpt_dir(desc_edpt->bEndpointAddress); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |   _dcd.xfer[epnum-1][dir].mps = desc_edpt->wMaxPacketSize.size; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( dir == TUSB_DIR_OUT ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->INTENSET = BIT_(USBD_INTEN_ENDEPOUT0_Pos + epnum); | 
					
						
							|  |  |  |     NRF_USBD->EPOUTEN |= BIT_(epnum); | 
					
						
							|  |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->INTENSET = BIT_(USBD_INTEN_ENDEPIN0_Pos + epnum); | 
					
						
							|  |  |  |     NRF_USBD->EPINEN  |= BIT_(epnum); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   __ISB(); __DSB(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uint8_t const epnum = edpt_number(ep_addr); | 
					
						
							|  |  |  |   uint8_t const dir   = edpt_dir(ep_addr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |   nom_xfer_t* xfer = get_td(epnum, dir); | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   xfer->buffer     = buffer; | 
					
						
							|  |  |  |   xfer->total_len  = total_bytes; | 
					
						
							|  |  |  |   xfer->actual_len = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // FIXME Errata 104 walkaround
 | 
					
						
							|  |  |  |   if ( nrf_drv_usbd_errata_104() ) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |     xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR; | 
					
						
							|  |  |  |     xfer->prev_size = NRF_USBD->SIZE.EPOUT[epnum]; | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   normal_xact_start(epnum, dir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-21 16:08:42 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ( ep_addr == 0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->TASKS_EP0STALL = 1; | 
					
						
							|  |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 16:08:42 +07:00
										 |  |  |   __ISB(); __DSB(); | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-21 16:08:42 +07:00
										 |  |  |   if ( ep_addr ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  | bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr) | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-23 12:17:47 +07:00
										 |  |  |   (void) rhport; | 
					
						
							| 
									
										
										
										
											2018-03-20 18:33:06 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // USBD shouldn't check control endpoint state
 | 
					
						
							|  |  |  |   if ( 0 == ep_addr ) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint8_t const epnum = edpt_number(ep_addr); | 
					
						
							|  |  |  |   uint8_t const dir   = edpt_dir(ep_addr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |   nom_xfer_t* xfer = get_td(epnum, dir); | 
					
						
							| 
									
										
										
										
											2018-03-20 18:33:06 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return xfer->actual_len < xfer->total_len; | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *------------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static uint16_t frame_sofar(uint16_t fr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint16_t diff = (uint16_t) NRF_USBD->FRAMECNTR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( diff > fr ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     diff -= fr; | 
					
						
							|  |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     diff = (diff + 1024) - fr; // Frame counter cap at 1024
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-14 12:25:06 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return diff; | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | void USBD_IRQHandler(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint32_t const inten  = NRF_USBD->INTEN; | 
					
						
							|  |  |  |   uint32_t int_status = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |   volatile uint32_t* regevt = &NRF_USBD->EVENTS_USBRESET; | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for(int i=0; i<32; i++) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |     if ( BIT_TEST_(inten, i) && regevt[i]  ) | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  |     { | 
					
						
							|  |  |  |       int_status |= BIT_(i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |       // event clear
 | 
					
						
							|  |  |  |       regevt[i] = 0; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       __ISB(); __DSB(); | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   /*------------- Interrupt Processing -------------*/ | 
					
						
							|  |  |  |   if ( int_status & USBD_INTEN_USBRESET_Msk ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     bus_reset(); | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |     dcd_bus_event(0, USBD_BUS_EVENT_RESET); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |   if ( int_status & EDPT_END_ALL_MASK ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // DMA complete move data from SRAM -> Endpoint
 | 
					
						
							|  |  |  |     edpt_dma_end(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  |   /*------------- Control Transfer -------------*/ | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   if ( int_status & USBD_INTEN_EP0SETUP_Msk ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     uint8_t setup[8] = { | 
					
						
							|  |  |  |         NRF_USBD->BMREQUESTTYPE, NRF_USBD->BREQUEST, NRF_USBD->WVALUEL, NRF_USBD->WVALUEH, | 
					
						
							|  |  |  |         NRF_USBD->WINDEXL, NRF_USBD->WINDEXH, NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-03-14 15:21:47 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |     dcd_setup_received(0, setup); | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( int_status & USBD_INTEN_EP0DATADONE_Msk ) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     if ( _dcd.control.dir == TUSB_DIR_OUT ) | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       // OUT data from Host -> Endpoint
 | 
					
						
							|  |  |  |       // Trigger DMA to move Endpoint -> SRAM
 | 
					
						
							| 
									
										
										
										
											2018-03-15 17:09:55 +07:00
										 |  |  |       edpt_dma_start(0, TUSB_DIR_OUT); | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     }else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       // IN: data transferred from Endpoint -> Host
 | 
					
						
							|  |  |  |       if ( _dcd.control.len > 0 ) | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |       { | 
					
						
							|  |  |  |         control_xact_start(); | 
					
						
							|  |  |  |       }else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |         // Control IN complete
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |         dcd_xfer_complete(0, 0, 0, true); | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |   // OUT data moved from Endpoint -> SRAM
 | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |   if ( int_status & USBD_INTEN_ENDEPOUT0_Msk) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |     if ( _dcd.control.len > 0 ) | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     { | 
					
						
							|  |  |  |       control_xact_start(); | 
					
						
							|  |  |  |     }else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       // Control OUT complete
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |       dcd_xfer_complete(0, 0, 0, true); | 
					
						
							| 
									
										
										
										
											2018-03-15 13:22:28 +07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-14 22:01:29 +07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /*------------- Bulk/Interrupt Transfer -------------*/ | 
					
						
							|  |  |  |   if ( int_status & USBD_INTEN_EPDATA_Msk) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     uint32_t data_status = NRF_USBD->EPDATASTATUS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nrf_usbd_epdatastatus_clear(data_status); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // In: data from Endpoint -> Host
 | 
					
						
							|  |  |  |     for(uint8_t epnum=1; epnum<8; epnum++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if ( BIT_TEST_(data_status, epnum ) ) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |         nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN); | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         xfer->actual_len += NRF_USBD->EPIN[epnum].MAXCNT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ( xfer->actual_len < xfer->total_len ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           // more to xfer
 | 
					
						
							|  |  |  |           normal_xact_start(epnum, TUSB_DIR_IN); | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-03-20 18:33:06 +07:00
										 |  |  |           // BULK/INT IN complete
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |           dcd_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, true); | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // OUT: data from Host -> Endpoint
 | 
					
						
							|  |  |  |     for(uint8_t epnum=1; epnum<8; epnum++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if ( BIT_TEST_(data_status, 16+epnum ) ) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |         nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT); | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |         TU_ASSERT(xfer->actual_len < xfer->total_len, ); | 
					
						
							|  |  |  |         // FIXME Errata 104 walkaround
 | 
					
						
							|  |  |  |         if ( nrf_drv_usbd_errata_104() ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           xfer->prev_size = xact_len; | 
					
						
							|  |  |  |           xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |         // Trigger DMA move data from Endpoint -> SRAM
 | 
					
						
							|  |  |  |         NRF_USBD->EPOUT[epnum].PTR    = (uint32_t) xfer->buffer; | 
					
						
							|  |  |  |         NRF_USBD->EPOUT[epnum].MAXCNT = xact_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         edpt_dma_start(epnum, TUSB_DIR_OUT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         xfer->buffer     += xact_len; | 
					
						
							|  |  |  |         xfer->actual_len += xact_len; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // OUT: data from DMA -> SRAM
 | 
					
						
							|  |  |  |   for(uint8_t epnum=1; epnum<8; epnum++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if ( BIT_TEST_(int_status, USBD_INTEN_ENDEPOUT0_Pos+epnum) ) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |       nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uint8_t const xact_len = NRF_USBD->EPOUT[epnum].AMOUNT; | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Transfer complete if transaction len < Max Packet Size or total len is transferred
 | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |       if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |         // Prepare for more data from Host -> Endpoint
 | 
					
						
							|  |  |  |         normal_xact_start(epnum, TUSB_DIR_OUT); | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       }else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-03-20 18:33:06 +07:00
										 |  |  |         xfer->total_len = xfer->actual_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // BULK/INT OUT complete
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:47:58 +07:00
										 |  |  |         dcd_xfer_complete(0, epnum, xfer->actual_len, true); | 
					
						
							| 
									
										
										
										
											2018-03-17 02:17:40 +07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // SOF interrupt
 | 
					
						
							|  |  |  |   if ( int_status & USBD_INTEN_SOF_Msk ) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |     dcd_bus_event(0, USBD_BUS_EVENT_SOF); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 1
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |     // FIXME Errata 104 The EPDATA event might not be generated, and the related update of EPDATASTATUS does not occur.
 | 
					
						
							|  |  |  |     // There is no way for software to tell if a xfer is complete or not.
 | 
					
						
							|  |  |  |     // Walkaround: we will asssume an non-control IN transfer is always complete after 10 frames
 | 
					
						
							|  |  |  |     if ( nrf_drv_usbd_errata_104() ) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |       // Check all OUT transfer, if the SIZE changes --> consider it is complete
 | 
					
						
							| 
									
										
										
										
											2018-04-14 12:25:06 +07:00
										 |  |  |       for (int ep=1; ep<8; ep++) | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |       { | 
					
						
							|  |  |  |         nom_xfer_t* xfer = get_td(ep, TUSB_DIR_OUT); | 
					
						
							| 
									
										
										
										
											2018-04-14 12:25:06 +07:00
										 |  |  |         if ( (xfer->actual_len < xfer->total_len) && (xfer->prev_size != NRF_USBD->SIZE.EPOUT[ep]) ) | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |         { | 
					
						
							|  |  |  |           if ( frame_sofar(xfer->frame_num) > 2) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[ep]; | 
					
						
							|  |  |  |             xfer->prev_size = xact_len; | 
					
						
							|  |  |  |             xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Trigger DMA move data from Endpoint -> SRAM
 | 
					
						
							|  |  |  |             NRF_USBD->EPOUT[ep].PTR    = (uint32_t) xfer->buffer; | 
					
						
							|  |  |  |             NRF_USBD->EPOUT[ep].MAXCNT = xact_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             edpt_dma_start(ep, TUSB_DIR_OUT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             xfer->buffer     += xact_len; | 
					
						
							|  |  |  |             xfer->actual_len += xact_len; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |       // Check all the queued IN transfer, retire all transfer if 10 frames has passed
 | 
					
						
							| 
									
										
										
										
											2018-04-14 12:25:06 +07:00
										 |  |  |       for (int ep=1; ep< 8; ep++) | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |         nom_xfer_t* xfer = get_td(ep, TUSB_DIR_IN); | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (xfer->actual_len < xfer->total_len) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           // Walkaround, mark this transfer as complete
 | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  |           if (frame_sofar(xfer->frame_num) > 10) | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |           { | 
					
						
							|  |  |  |             xfer->actual_len = xfer->total_len; | 
					
						
							| 
									
										
										
										
											2018-04-12 00:33:31 +07:00
										 |  |  |             dcd_xfer_complete(0, ep | TUSB_DIR_IN_MASK, xfer->actual_len, true); | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-04-14 03:39:01 +07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-04-10 14:31:11 +07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:03:56 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 16:59:51 +07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-26 22:54:34 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |