stm32 update TX Fifo for edpt IN, both CDC + MSC work great
- call dcd_event_xfer_complete() when enough bytes received - add dcd_get_frame_number()
This commit is contained in:
@@ -171,14 +171,14 @@ static inline uint16_t tu_u16_le2be(uint16_t u16)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Min
|
// Min
|
||||||
static inline uint8_t tu_min8(uint8_t x, uint8_t y) { return (x < y) ? x : y; }
|
static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; }
|
||||||
static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; }
|
static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; }
|
||||||
static inline uint32_t tu_min32(uint32_t x, uint32_t y) { return (x < y) ? x : y; }
|
static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; }
|
||||||
|
|
||||||
// Max
|
// Max
|
||||||
static inline uint8_t tu_max8(uint8_t x, uint8_t y) { return (x > y) ? x : y; }
|
static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; }
|
||||||
static inline uint16_t tu_max16(uint16_t x, uint16_t y) { return (x > y) ? x : y; }
|
static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; }
|
||||||
static inline uint32_t tu_max32(uint32_t x, uint32_t y) { return (x > y) ? x : y; }
|
static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; }
|
||||||
|
|
||||||
// Align
|
// Align
|
||||||
static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); }
|
static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); }
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE)
|
#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE)
|
||||||
#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE)
|
#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE)
|
||||||
#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE)
|
#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE)
|
||||||
#define FIFO_BASE(_x) (uint32_t *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_FIFO_BASE + _x * USB_OTG_FIFO_SIZE)
|
#define FIFO_BASE(_x) (uint32_t *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)
|
||||||
|
|
||||||
static ATTR_ALIGNED(4) uint32_t _setup_packet[6];
|
static ATTR_ALIGNED(4) uint32_t _setup_packet[6];
|
||||||
static uint8_t _setup_offs; // We store up to 3 setup packets.
|
static uint8_t _setup_offs; // We store up to 3 setup packets.
|
||||||
@@ -80,20 +80,39 @@ static void bus_reset(void) {
|
|||||||
dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM;
|
dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM;
|
||||||
dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM;
|
dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM;
|
||||||
|
|
||||||
|
// Peripheral FIFO architecture (Rev18 RM 29.11)
|
||||||
|
//
|
||||||
|
// --------------- 312.5 ( 1250 bytes )
|
||||||
|
// | IN FIFO 3 |
|
||||||
|
// --------------- y + x + 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 2 |
|
||||||
|
// --------------- x + 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 1 |
|
||||||
|
// --------------- 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 0 |
|
||||||
|
// --------------- GRXFSIZ
|
||||||
|
// | OUT FIFO |
|
||||||
|
// | ( Shared ) |
|
||||||
|
// --------------- 0
|
||||||
|
//
|
||||||
// FIFO sizes are set up by the following rules (each word 32-bits):
|
// FIFO sizes are set up by the following rules (each word 32-bits):
|
||||||
// OUT FIFO uses (based on page 1354 of Rev 17 of reference manual):
|
// All EP OUT shared a unique OUT FIFO which uses (based on page 1354 of Rev 17 of reference manual):
|
||||||
// * 10 locations in hardware for setup packets + setup control words
|
// * 10 locations in hardware for setup packets + setup control words
|
||||||
// (up to 3 setup packets).
|
// (up to 3 setup packets).
|
||||||
// * 2 locations for OUT endpoint control words.
|
// * 2 locations for OUT endpoint control words.
|
||||||
// * 64 bytes for maximum control packet size.
|
// * 16 + 1 (data + info) for largest packet size of 64 bytes.
|
||||||
// * 1 location for global NAK (not required/used here).
|
// * 1 location for global NAK (not required/used here).
|
||||||
// IN FIFO uses 64 bytes for maximum control packet size.
|
|
||||||
//
|
//
|
||||||
// However, for OUT FIFO, 10 + 2 + 16 = 28 doesn't seem to work (TODO: why?).
|
// However, for OUT FIFO, 10 + 2 + 16 = 28 doesn't seem to work (TODO: why?).
|
||||||
// Minimum that works in practice is 35, so allocate 40 32-bit locations
|
// Minimum that works in practice is 35, so allocate 40 32-bit locations
|
||||||
// as a buffer.
|
// as a buffer.
|
||||||
USB_OTG_FS->GRXFSIZ = 40;
|
//
|
||||||
USB_OTG_FS->DIEPTXF0_HNPTXFSIZ |= (16 << USB_OTG_TX0FD_Pos); // 16 32-bit words = 64 bytes
|
// It is recommended to allocate 2 times the largest packet size, therefore
|
||||||
|
// Recommended value = 10 + 1 + 2 x (16+1) = 45 --> Let's make it 50
|
||||||
|
USB_OTG_FS->GRXFSIZ = 50;
|
||||||
|
|
||||||
|
// Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
|
||||||
|
USB_OTG_FS->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (USB_OTG_FS->GRXFSIZ & 0x0000ffffUL);
|
||||||
|
|
||||||
out_ep[0].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
|
out_ep[0].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
|
||||||
|
|
||||||
@@ -194,6 +213,15 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num)
|
|||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t dcd_get_frame_number(uint8_t rhport)
|
||||||
|
{
|
||||||
|
(void) rhport;
|
||||||
|
|
||||||
|
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
|
||||||
|
|
||||||
|
return (dev->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
/* DCD Endpoint port
|
/* DCD Endpoint port
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
@@ -222,13 +250,34 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
|||||||
desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos;
|
desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos;
|
||||||
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
|
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
|
||||||
} else {
|
} else {
|
||||||
|
// Peripheral FIFO architecture (Rev18 RM 29.11)
|
||||||
|
//
|
||||||
|
// --------------- 312.5 ( 1250 bytes )
|
||||||
|
// | IN FIFO 3 |
|
||||||
|
// --------------- y + x + 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 2 |
|
||||||
|
// --------------- x + 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 1 |
|
||||||
|
// --------------- 16 + GRXFSIZ
|
||||||
|
// | IN FIFO 0 |
|
||||||
|
// --------------- GRXFSIZ
|
||||||
|
// | OUT FIFO |
|
||||||
|
// | ( Shared ) |
|
||||||
|
// --------------- 0
|
||||||
|
//
|
||||||
|
// Since OUT FIFO = 50, FIFO0 = 16, average of FIFOx = (312-50-16) / 3 = 82 ~ 80
|
||||||
|
|
||||||
in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | \
|
in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | \
|
||||||
(epnum - 1) << USB_OTG_DIEPCTL_TXFNUM_Pos | \
|
(epnum - 1) << USB_OTG_DIEPCTL_TXFNUM_Pos | \
|
||||||
desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos | \
|
desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos | \
|
||||||
|
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | \
|
||||||
desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos;
|
desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos;
|
||||||
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
|
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
|
||||||
|
|
||||||
USB_OTG_FS->DIEPTXF[epnum - 1] = (40 << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (epnum * 0x100);
|
// Both TXFD and TXSA are in unit of 32-bit words
|
||||||
|
uint16_t const fifo_size = 80;
|
||||||
|
uint32_t const fifo_offset = (USB_OTG_FS->GRXFSIZ & 0x0000ffff) + 16 + fifo_size*(epnum-1);
|
||||||
|
USB_OTG_FS->DIEPTXF[epnum - 1] = (80 << USB_OTG_DIEPTXF_INEPTXFD_Pos) | fifo_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -587,7 +636,9 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy
|
|||||||
// on a packet-basis. The core can internally handle multiple OUT
|
// on a packet-basis. The core can internally handle multiple OUT
|
||||||
// packets; it would be more efficient to only trigger XFRC on a
|
// packets; it would be more efficient to only trigger XFRC on a
|
||||||
// completed transfer for non-0 endpoints.
|
// completed transfer for non-0 endpoints.
|
||||||
if(xfer->short_packet) {
|
|
||||||
|
// Transfer complete if short packet or total len is transferred
|
||||||
|
if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) {
|
||||||
xfer->short_packet = false;
|
xfer->short_packet = false;
|
||||||
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
|
dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user