synopsys: Fix odd/even frame handling for ISO
Current implementation always sets odd/even bit for ISO transactions. This is a good strategy only if interval is 1. For ISO endpoint interval in (micro)frames is computed as 2^(interval-1), which means that odd/frame number should stay same for interval values > 1. With this change only when interval is 1 odd/even bit is modified.
This commit is contained in:
		| @@ -136,6 +136,7 @@ typedef struct { | |||||||
|   uint8_t * buffer; |   uint8_t * buffer; | ||||||
|   uint16_t total_len; |   uint16_t total_len; | ||||||
|   uint16_t max_size; |   uint16_t max_size; | ||||||
|  |   uint8_t interval; | ||||||
| } xfer_ctl_t; | } xfer_ctl_t; | ||||||
|  |  | ||||||
| // EP size and transfer type report | // EP size and transfer type report | ||||||
| @@ -440,7 +441,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c | |||||||
|  |  | ||||||
|     in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; |     in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; | ||||||
|     // For ISO endpoint set correct odd/even bit for next frame. |     // For ISO endpoint set correct odd/even bit for next frame. | ||||||
|     if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0) |     if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) | ||||||
|     { |     { | ||||||
|       // Take odd/even bit from frame counter. |       // Take odd/even bit from frame counter. | ||||||
|       uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); |       uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); | ||||||
| @@ -457,6 +458,12 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c | |||||||
|         ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); |         ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); | ||||||
|  |  | ||||||
|     out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; |     out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; | ||||||
|  |     if ((out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP) == USB_OTG_DOEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) | ||||||
|  |     { | ||||||
|  |       // Take odd/even bit from frame counter. | ||||||
|  |       uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); | ||||||
|  |       out_ep[epnum].DOEPCTL |= (odd_frame_now ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DOEPCTL_SODDFRM_Msk); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -608,6 +615,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) | |||||||
|  |  | ||||||
|   xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); |   xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); | ||||||
|   xfer->max_size = desc_edpt->wMaxPacketSize.size; |   xfer->max_size = desc_edpt->wMaxPacketSize.size; | ||||||
|  |   xfer->interval = desc_edpt->bInterval; | ||||||
|  |  | ||||||
|   if(dir == TUSB_DIR_OUT) |   if(dir == TUSB_DIR_OUT) | ||||||
|   { |   { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jerzy Kasenberg
					Jerzy Kasenberg