uint16_t stm32fx07_ep_write_packet(usbd_device *usbd_dev, uint8_t addr, const void *buf, uint16_t len) { const uint32_t *buf32 = buf; int i; addr &= 0x7F; /* Return if endpoint is already enabled. */ if (REBASE(OTG_DIEPTSIZ(addr)) & OTG_FS_DIEPSIZ0_PKTCNT) { return 0; } /* Enable endpoint for transmission. */ REBASE(OTG_DIEPTSIZ(addr)) = OTG_FS_DIEPSIZ0_PKTCNT | len; REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_CNAK; volatile uint32_t *fifo = REBASE_FIFO(addr); /* Copy buffer to endpoint FIFO, note - memcpy does not work */ for (i = len; i > 0; i -= 4) { *fifo++ = *buf32++; } return len; }
uint16_t stm32fx07_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint16_t len) { int i; uint32_t *buf32 = buf; uint32_t extra; len = MIN(len, usbd_dev->rxbcnt); usbd_dev->rxbcnt -= len; volatile uint32_t *fifo = REBASE_FIFO(addr); for (i = len; i >= 4; i -= 4) { *buf32++ = *fifo++; } if (i) { extra = *fifo++; memcpy(buf32, &extra, i); } REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr]; REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_EPENA | (usbd_dev->force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK); return len; }
void stm32fx07_poll(usbd_device *usbd_dev) { /* Read interrupt status register. */ uint32_t intsts = REBASE(OTG_GINTSTS); int i; if (intsts & OTG_GINTSTS_ENUMDNE) { /* Handle USB RESET condition. */ REBASE(OTG_GINTSTS) = OTG_GINTSTS_ENUMDNE; usbd_dev->fifo_mem_top = usbd_dev->driver->rx_fifo_size; _usbd_reset(usbd_dev); return; } /* Note: RX and TX handled differently in this device. */ if (intsts & OTG_GINTSTS_RXFLVL) { /* Receive FIFO non-empty. */ uint32_t rxstsp = REBASE(OTG_GRXSTSP); uint32_t pktsts = rxstsp & OTG_GRXSTSP_PKTSTS_MASK; if ((pktsts != OTG_GRXSTSP_PKTSTS_OUT) && (pktsts != OTG_GRXSTSP_PKTSTS_SETUP)) { return; } uint8_t ep = rxstsp & OTG_GRXSTSP_EPNUM_MASK; uint8_t type; if (pktsts == OTG_GRXSTSP_PKTSTS_SETUP) { type = USB_TRANSACTION_SETUP; } else { type = USB_TRANSACTION_OUT; } /* Save packet size for stm32f107_ep_read_packet(). */ usbd_dev->rxbcnt = (rxstsp & OTG_GRXSTSP_BCNT_MASK) >> 4; #if 0 /* * FIXME: Why is a delay needed here? * This appears to fix a problem where the first 4 bytes * of the DATA OUT stage of a control transaction are lost. */ for (i = 0; i < 1000; i++) { __asm__("nop"); } #endif if (usbd_dev->user_callback_ctr[ep][type]) { usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep); } /* Discard unread packet data. */ for (i = 0; i < usbd_dev->rxbcnt; i += 4) { (void)*REBASE_FIFO(ep); } usbd_dev->rxbcnt = 0; }