improve nrf52 dcd, add fix for hw ACK issue with bulk
This commit is contained in:
		| @@ -66,13 +66,7 @@ typedef struct { | ||||
| }cdcd_interface_t; | ||||
|  | ||||
| // TODO multiple rhport | ||||
| #if CFG_TUSB_MCU == OPT_MCU_NRF5X | ||||
| // FIXME nrf52 OUT bug ( Controller ACK data even we didn't prepare transfer ) | ||||
| CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[600]; | ||||
| #else | ||||
| CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64]; | ||||
| #endif | ||||
|  | ||||
| CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64]; | ||||
|  | ||||
| FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true); | ||||
|   | ||||
| @@ -70,6 +70,9 @@ typedef struct | ||||
|   uint16_t actual_len; | ||||
|   uint8_t  mps; // max packet size | ||||
|  | ||||
|   // FIXME nrf52840 does not NAK OUT packet properly | ||||
|   bool     data_received; | ||||
|  | ||||
| } nom_xfer_t; | ||||
|  | ||||
| /*static*/ struct | ||||
| @@ -163,7 +166,7 @@ static void edpt_dma_end(void) | ||||
|   _dcd.dma_running = false; | ||||
| } | ||||
|  | ||||
| static void control_xact_start(void) | ||||
| static void xact_control_start(void) | ||||
| { | ||||
|   // Each transaction is up to 64 bytes | ||||
|   uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); | ||||
| @@ -200,7 +203,7 @@ bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_ | ||||
|     _dcd.control.buffer     = buffer; | ||||
|     _dcd.control.dir        = (uint8_t) dir; | ||||
|  | ||||
|     control_xact_start(); | ||||
|     xact_control_start(); | ||||
|   }else | ||||
|   { | ||||
|     // Status Phase | ||||
| @@ -220,27 +223,55 @@ static inline nom_xfer_t* get_td(uint8_t epnum, uint8_t dir) | ||||
|   return &_dcd.xfer[epnum-1][dir]; | ||||
| } | ||||
|  | ||||
| static void normal_xact_start(uint8_t epnum, uint8_t dir) | ||||
| /*------------- Bulk/Int OUT transfer -------------*/ | ||||
|  | ||||
| /** | ||||
|  * Prepare Bulk/Int out transaction, Endpoint start to accept/ACK Data | ||||
|  * @param epnum | ||||
|  */ | ||||
| static void xact_out_prepare(uint8_t epnum) | ||||
| { | ||||
|   if ( dir == TUSB_DIR_OUT ) | ||||
|   { | ||||
|     // Overwrite size will allow hw to accept data | ||||
|     NRF_USBD->SIZE.EPOUT[epnum] = 0; | ||||
|     __ISB(); __DSB(); | ||||
|   }else | ||||
|   { | ||||
|     nom_xfer_t* xfer = get_td(epnum, dir); | ||||
|   // Write any value to size will allow hw to ACK (accept data) | ||||
|   NRF_USBD->SIZE.EPOUT[epnum] = 0; | ||||
|   __ISB(); __DSB(); | ||||
| } | ||||
|  | ||||
|     // Each transaction is up to Max Packet Size | ||||
|     uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); | ||||
| static void xact_out_dma(uint8_t epnum) | ||||
| { | ||||
|   nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT); | ||||
|  | ||||
|     NRF_USBD->EPIN[epnum].PTR    = (uint32_t) xfer->buffer; | ||||
|     NRF_USBD->EPIN[epnum].MAXCNT = xact_len; | ||||
|   uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum]; | ||||
|  | ||||
|     xfer->buffer += xact_len; | ||||
|   // 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_IN); | ||||
|   } | ||||
|   edpt_dma_start(epnum, TUSB_DIR_OUT); | ||||
|  | ||||
|   xfer->buffer     += xact_len; | ||||
|   xfer->actual_len += xact_len; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*------------- Bulk/Int IN transfer -------------*/ | ||||
|  | ||||
| /** | ||||
|  * Prepare Bulk/Int in transaction, transfer data from Memory -> Endpoint | ||||
|  * @param epnum | ||||
|  */ | ||||
| static void xact_in_prepare(uint8_t epnum) | ||||
| { | ||||
|   nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN); | ||||
|  | ||||
|   // Each transaction is up to Max Packet Size | ||||
|   uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); | ||||
|  | ||||
|   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); | ||||
| } | ||||
|  | ||||
| bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) | ||||
| @@ -279,7 +310,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t | ||||
|   xfer->total_len  = total_bytes; | ||||
|   xfer->actual_len = 0; | ||||
|  | ||||
|   normal_xact_start(epnum, dir); | ||||
|   if ( dir == TUSB_DIR_OUT ) | ||||
|   { | ||||
|     if ( xfer->data_received ) | ||||
|     { | ||||
|       xfer->data_received = false; | ||||
|  | ||||
|       // FIXME nrf52840 does not NAK OUT packet properly | ||||
|       // Data already received preivously | ||||
|       xact_out_dma(epnum); | ||||
|     }else | ||||
|     { | ||||
|       xact_out_prepare(epnum); | ||||
|     } | ||||
|   }else | ||||
|   { | ||||
|     xact_in_prepare(epnum); | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
| @@ -382,7 +429,7 @@ void USBD_IRQHandler(void) | ||||
|       // IN: data transferred from Endpoint -> Host | ||||
|       if ( _dcd.control.actual_len < _dcd.control.total_len ) | ||||
|       { | ||||
|         control_xact_start(); | ||||
|         xact_control_start(); | ||||
|       }else | ||||
|       { | ||||
|         // Control IN complete | ||||
| @@ -396,7 +443,7 @@ void USBD_IRQHandler(void) | ||||
|   { | ||||
|     if ( _dcd.control.actual_len < _dcd.control.total_len ) | ||||
|     { | ||||
|       control_xact_start(); | ||||
|       xact_control_start(); | ||||
|     }else | ||||
|     { | ||||
|       // Control OUT complete | ||||
| @@ -423,7 +470,7 @@ void USBD_IRQHandler(void) | ||||
|         if ( xfer->actual_len < xfer->total_len ) | ||||
|         { | ||||
|           // more to xfer | ||||
|           normal_xact_start(epnum, TUSB_DIR_IN); | ||||
|           xact_in_prepare(epnum); | ||||
|         } else | ||||
|         { | ||||
|           // BULK/INT IN complete | ||||
| @@ -439,19 +486,17 @@ void USBD_IRQHandler(void) | ||||
|       { | ||||
|         nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT); | ||||
|  | ||||
|         uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum]; | ||||
|         if (xfer->actual_len < xfer->total_len) | ||||
|         { | ||||
|           xact_out_dma(epnum); | ||||
|         }else | ||||
|         { | ||||
|           // FIXME nrf52840 does not NAK OUT packet properly | ||||
|           // It will always ACK next package although we haven't write to SIZE yet | ||||
|  | ||||
|         // FIXME nrf52840 rev A does not NAK OUT packet properly | ||||
|         TU_ASSERT(xfer->actual_len < xfer->total_len, ); | ||||
|  | ||||
|         // 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; | ||||
|           // Mark this endpoint with data received | ||||
|           xfer->data_received = true; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -469,7 +514,7 @@ void USBD_IRQHandler(void) | ||||
|       if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) | ||||
|       { | ||||
|         // Prepare for more data from Host -> Endpoint | ||||
|         normal_xact_start(epnum, TUSB_DIR_OUT); | ||||
|         xact_out_prepare(epnum); | ||||
|       }else | ||||
|       { | ||||
|         xfer->total_len = xfer->actual_len; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach