From 554feb7f274d853fc024165b3c3074d38a01e0c0 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 20 Feb 2011 12:28:23 +1300 Subject: USB driver for Connectivity-line devices partially working. --- include/libopencm3/stm32/otg_fs.h | 177 ++++++++++++++++++++++++++++++++++- include/libopencm3/stm32/rcc.h | 4 + include/libopencm3/usb/cdc.h | 2 +- lib/usb/usb_f107.c | 188 +++++++++++++++++++++++++++++++++++--- 4 files changed, 354 insertions(+), 17 deletions(-) diff --git a/include/libopencm3/stm32/otg_fs.h b/include/libopencm3/stm32/otg_fs.h index 0f07e89..d39593e 100644 --- a/include/libopencm3/stm32/otg_fs.h +++ b/include/libopencm3/stm32/otg_fs.h @@ -78,8 +78,10 @@ #define OTG_FS_DOEPTSIZ(x) MMIO32(USB_OTG_FS_BASE + 0xB10 + 0x20*(x)) /* Power and clock gating control and status register */ -#define OTH_FS_PCGCR MMIO32(USB_OTG_FS_BASE + 0xE00) +#define OTG_FS_PCGCCTL MMIO32(USB_OTG_FS_BASE + 0xE00) +/* Data FIFO */ +#define OTG_FS_FIFO(x) ((u32*)(USB_OTG_FS_BASE + (((x) + 1) << 12))) /* Global CSRs */ /* OTG_FS AHB configuration register (OTG_FS_GAHBCFG) */ @@ -91,11 +93,58 @@ #define OTG_FS_GUSBCFG_TOCAL 0x00000003 #define OTG_FS_GUSBCFG_SRPCAP 0x00000100 #define OTG_FS_GUSBCFG_HNPCAP 0x00000200 -#define OTG_FS_GUSBCFG_TRDT 0x00003C00 +#define OTG_FS_GUSBCFG_TRDT_MASK (0xf << 10) +#define OTG_FS_GUSBCFG_TRDT_16BIT (0x5 << 10) +#define OTG_FS_GUSBCFG_TRDT_8BIT (0x9 << 10) #define OTG_FS_GUSBCFG_NPTXRWEN 0x00004000 #define OTG_FS_GUSBCFG_FHMOD 0x20000000 #define OTG_FS_GUSBCFG_FDMOD 0x40000000 #define OTG_FS_GUSBCFG_CTXPKT 0x80000000 +/* WARNING: not in reference manual */ +#define OTG_FS_GUSBCFG_PHYSEL (1 << 6) + +/* OTG_FS reset register (OTG_FS_GRSTCTL) */ +#define OTG_FS_GRSTCTL_AHBIDL (1 << 31) +/* Bits 30:11 - Reserved */ +#define OTG_FS_GRSTCTL_TXFNUM_MASK (0x1f << 6) +#define OTG_FS_GRSTCTL_TXFFLSH (1 << 5) +#define OTG_FS_GRSTCTL_RXFFLSH (1 << 4) +/* Bit 3 - Reserved */ +#define OTG_FS_GRSTCTL_FCRST (1 << 2) +#define OTG_FS_GRSTCTL_HSRST (1 << 1) +#define OTG_FS_GRSTCTL_CSRST (1 << 0) + +/* OTG_FS interrupt status register (OTG_FS_GINTSTS) */ +#define OTG_FS_GINTSTS_WKUPINT (1 << 31) +#define OTG_FS_GINTSTS_SRQINT (1 << 30) +#define OTG_FS_GINTSTS_DISCINT (1 << 29) +#define OTG_FS_GINTSTS_CIDSCHG (1 << 28) +/* Bit 27 - Reserved */ +#define OTG_FS_GINTSTS_PTXFE (1 << 26) +#define OTG_FS_GINTSTS_HCINT (1 << 25) +#define OTG_FS_GINTSTS_HPRTINT (1 << 24) +/* Bits 23:22 - Reserved */ +#define OTG_FS_GINTSTS_IPXFR (1 << 21) +#define OTG_FS_GINTSTS_INCOMPISOOUT (1 << 21) +#define OTG_FS_GINTSTS_IISOIXFR (1 << 20) +#define OTG_FS_GINTSTS_OEPINT (1 << 19) +#define OTG_FS_GINTSTS_IEPINT (1 << 18) +/* Bits 17:16 - Reserved */ +#define OTG_FS_GINTSTS_EOPF (1 << 15) +#define OTG_FS_GINTSTS_ISOODRP (1 << 14) +#define OTG_FS_GINTSTS_ENUMDNE (1 << 13) +#define OTG_FS_GINTSTS_USBRST (1 << 12) +#define OTG_FS_GINTSTS_USBSUSP (1 << 11) +#define OTG_FS_GINTSTS_ESUSP (1 << 10) +/* Bits 9:8 - Reserved */ +#define OTG_FS_GINTSTS_GONAKEFF (1 << 7) +#define OTG_FS_GINTSTS_GINAKEFF (1 << 6) +#define OTG_FS_GINTSTS_NPTXFE (1 << 5) +#define OTG_FS_GINTSTS_RXFLVL (1 << 4) +#define OTG_FS_GINTSTS_SOF (1 << 3) +#define OTG_FS_GINTSTS_OTGINT (1 << 2) +#define OTG_FS_GINTSTS_MMIS (1 << 1) +#define OTG_FS_GINTSTS_CMOD (1 << 0) /* OTG_FS interrupt mask register (OTG_FS_GINTMSK) */ #define OTG_FS_GINTMSK_MMISM 0x00000002 @@ -125,15 +174,139 @@ #define OTG_FS_GINTMSK_SRQIM 0x40000000 #define OTG_FS_GINTMSK_WUIM 0x80000000 +/* OTG_FS Receive Status Pop Register (OTG_FS_GRXSTSP) */ +/* Bits 31:25 - Reserved */ +#define OTG_FS_GRXSTSP_FRMNUM_MASK (0xf << 21) +#define OTG_FS_GRXSTSP_PKTSTS_MASK (0xf << 17) +#define OTG_FS_GRXSTSP_PKTSTS_GOUTNAK (0x1 << 17) +#define OTG_FS_GRXSTSP_PKTSTS_OUT (0x2 << 17) +#define OTG_FS_GRXSTSP_PKTSTS_OUT_COMP (0x3 << 17) +#define OTG_FS_GRXSTSP_PKTSTS_SETUP_COMP (0x4 << 17) +#define OTG_FS_GRXSTSP_PKTSTS_SETUP (0x6 << 17) +#define OTG_FS_GRXSTSP_DPID_MASK (0x3 << 15) +#define OTG_FS_GRXSTSP_DPID_DATA0 (0x0 << 15) +#define OTG_FS_GRXSTSP_DPID_DATA1 (0x2 << 15) +#define OTG_FS_GRXSTSP_DPID_DATA2 (0x1 << 15) +#define OTG_FS_GRXSTSP_DPID_MDATA (0x3 << 15) +#define OTG_FS_GRXSTSP_BCNT_MASK (0x7ff << 4) +#define OTG_FS_GRXSTSP_EPNUM_MASK (0xf << 0) + +/* OTG_FS general core configuration register (OTG_FS_GCCFG) */ +/* Bits 31:21 - Reserved */ +#define OTG_FS_GCCFG_SOFOUTEN (1 << 20) +#define OTG_FS_GCCFG_VBUSBSEN (1 << 19) +#define OTG_FS_GCCFG_VBUSASEN (1 << 18) +/* Bit 17 - Reserved */ +#define OTG_FS_GCCFG_PWRDWN (1 << 16) +/* Bits 15:0 - Reserved */ + /* Device-mode CSRs */ +/* OTG_FS device control register (OTG_FS_DCTL) */ +/* Bits 31:12 - Reserved */ +#define OTG_FS_DCTL_POPRGDNE (1 << 11) +#define OTG_FS_DCTL_CGONAK (1 << 10) +#define OTG_FS_DCTL_SGONAK (1 << 9) +#define OTG_FS_DCTL_SGINAK (1 << 8) +#define OTG_FS_DCTL_TCTL_MASK (7 << 4) +#define OTG_FS_DCTL_GONSTS (1 << 3) +#define OTG_FS_DCTL_GINSTS (1 << 2) +#define OTG_FS_DCTL_SDIS (1 << 1) +#define OTG_FS_DCTL_RWUSIG (1 << 0) + /* OTG_FS device configuration register (OTG_FS_DCFG) */ #define OTG_FS_DCFG_DSPD 0x0003 #define OTG_FS_DCFG_NZLSOHSK 0x0004 #define OTG_FS_DCFG_DAD 0x07F0 #define OTG_FS_DCFG_PFIVL 0x1800 +/* OTG_FS Device IN Endpoint Common Interrupt Mask Register (OTG_FS_DIEPMSK) */ +/* Bits 31:10 - Reserved */ +#define OTG_FS_DIEPMSK_BIM (1 << 9) +#define OTG_FS_DIEPMSK_TXFURM (1 << 8) +/* Bit 7 - Reserved */ +#define OTG_FS_DIEPMSK_INEPNEM (1 << 6) +#define OTG_FS_DIEPMSK_INEPNMM (1 << 5) +#define OTG_FS_DIEPMSK_ITTXFEMSK (1 << 4) +#define OTG_FS_DIEPMSK_TOM (1 << 3) +/* Bit 2 - Reserved */ +#define OTG_FS_DIEPMSK_EPDM (1 << 1) +#define OTG_FS_DIEPMSK_XFRCM (1 << 0) + +/* OTG_FS Device OUT Endpoint Common Interrupt Mask Register (OTG_FS_DOEPMSK) */ +/* Bits 31:10 - Reserved */ +#define OTG_FS_DOEPMSK_BOIM (1 << 9) +#define OTG_FS_DOEPMSK_OPEM (1 << 8) +/* Bit 7 - Reserved */ +#define OTG_FS_DOEPMSK_B2BSTUP (1 << 6) +/* Bit 5 - Reserved */ +#define OTG_FS_DOEPMSK_OTEPDM (1 << 4) +#define OTG_FS_DOEPMSK_STUPM (1 << 3) +/* Bit 2 - Reserved */ +#define OTG_FS_DOEPMSK_EPDM (1 << 1) +#define OTG_FS_DOEPMSK_XFRCM (1 << 0) + +/* OTG_FS Device Control IN Endpoint 0 Control Register (OTG_FS_DIEPCTL0) */ +#define OTG_FS_DIEPCTL0_EPENA (1 << 31) +#define OTG_FS_DIEPCTL0_EPDIS (1 << 30) +/* Bits 29:28 - Reserved */ +#define OTG_FS_DIEPCTL0_SNAK (1 << 27) +#define OTG_FS_DIEPCTL0_CNAK (1 << 26) +#define OTG_FS_DIEPCTL0_TXFNUM_MASK (0xf << 22) +#define OTG_FS_DIEPCTL0_STALL (1 << 21) +/* Bit 20 - Reserved */ +#define OTG_FS_DIEPCTL0_EPTYP_MASK (0x3 << 18) +#define OTG_FS_DIEPCTL0_NAKSTS (1 << 17) +/* Bit 16 - Reserved */ +#define OTG_FS_DIEPCTL0_USBAEP (1 << 15) +/* Bits 14:2 - Reserved */ +#define OTG_FS_DIEPCTL0_MPSIZ_MASK (0x3 << 0) +#define OTG_FS_DIEPCTL0_MPSIZ_64 (0x0 << 0) +#define OTG_FS_DIEPCTL0_MPSIZ_32 (0x1 << 0) +#define OTG_FS_DIEPCTL0_MPSIZ_16 (0x2 << 0) +#define OTG_FS_DIEPCTL0_MPSIZ_8 (0x3 << 0) + +/* OTG_FS Device Control OUT Endpoint 0 Control Register (OTG_FS_DOEPCTL0) */ +#define OTG_FS_DOEPCTL0_EPENA (1 << 31) +#define OTG_FS_DOEPCTL0_EPDIS (1 << 30) +/* Bits 29:28 - Reserved */ +#define OTG_FS_DOEPCTL0_SNAK (1 << 27) +#define OTG_FS_DOEPCTL0_CNAK (1 << 26) +/* Bits 25:22 - Reserved */ +#define OTG_FS_DOEPCTL0_STALL (1 << 21) +#define OTG_FS_DOEPCTL0_SNPM (1 << 20) +#define OTG_FS_DOEPCTL0_EPTYP_MASK (0x3 << 18) +#define OTG_FS_DOEPCTL0_NAKSTS (1 << 17) +/* Bit 16 - Reserved */ +#define OTG_FS_DOEPCTL0_USBAEP (1 << 15) +/* Bits 14:2 - Reserved */ +#define OTG_FS_DOEPCTL0_MPSIZ_MASK (0x3 << 0) +#define OTG_FS_DOEPCTL0_MPSIZ_64 (0x0 << 0) +#define OTG_FS_DOEPCTL0_MPSIZ_32 (0x1 << 0) +#define OTG_FS_DOEPCTL0_MPSIZ_16 (0x2 << 0) +#define OTG_FS_DOEPCTL0_MPSIZ_8 (0x3 << 0) + +/* OTG_FS Device IN Endpoint Interrupt Register (OTG_FS_DIEPINTx) */ +/* Bits 31:8 - Reserved */ +#define OTG_FS_DIEPINTX_TXFE (1 << 7) +#define OTG_FS_DIEPINTX_INEPNE (1 << 6) +/* Bit 5 - Reserved */ +#define OTG_FS_DIEPINTX_ITTXFE (1 << 4) +#define OTG_FS_DIEPINTX_TOC (1 << 3) +/* Bit 2 - Reserved */ +#define OTG_FS_DIEPINTX_EPDISD (1 << 1) +#define OTG_FS_DIEPINTX_XFRC (1 << 0) +/* OTG_FS Device OUT Endpoint 0 Transfer Size Regsiter (OTG_FS_DOEPTSIZ0) */ +/* Bit 31 - Reserved */ +#define OTG_FS_DIEPSIZ0_STUPCNT_1 (0x1 << 29) +#define OTG_FS_DIEPSIZ0_STUPCNT_2 (0x2 << 29) +#define OTG_FS_DIEPSIZ0_STUPCNT_3 (0x3 << 29) +#define OTG_FS_DIEPSIZ0_STUPCNT_MASK (0x3 << 29) +/* Bits 28:20 - Reserved */ +#define OTG_FS_DIEPSIZ0_PKTCNT (1 << 19) +/* Bits 18:7 - Reserved */ +#define OTG_FS_DIEPSIZ0_XFRSIZ_MASK (0x7f << 0) #endif diff --git a/include/libopencm3/stm32/rcc.h b/include/libopencm3/stm32/rcc.h index 0880627..a618439 100644 --- a/include/libopencm3/stm32/rcc.h +++ b/include/libopencm3/stm32/rcc.h @@ -230,6 +230,10 @@ /* --- RCC_AHBENR values --------------------------------------------------- */ +#define RCC_AHBENR_ETHMACENRX (1 << 16) +#define RCC_AHBENR_ETHMACENTX (1 << 15) +#define RCC_AHBENR_ETHMACEN (1 << 14) +#define RCC_AHBENR_OTGFSEN (1 << 12) #define RCC_AHBENR_SDIOEN (1 << 10) #define RCC_AHBENR_FSMCEN (1 << 8) #define RCC_AHBENR_CRCEN (1 << 6) diff --git a/include/libopencm3/usb/cdc.h b/include/libopencm3/usb/cdc.h index 2bdc18b..808d004 100644 --- a/include/libopencm3/usb/cdc.h +++ b/include/libopencm3/usb/cdc.h @@ -112,7 +112,7 @@ struct usb_cdc_line_coding { /* Table 30: Class-Specific Notification Codes for PSTN subclasses */ /* ... */ -#define USB_CDC_NOTIFY_SERIAL_STATE 0x28 +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 /* ... */ /* Notification Structure */ diff --git a/lib/usb/usb_f107.c b/lib/usb/usb_f107.c index 338735a..a681b60 100644 --- a/lib/usb/usb_f107.c +++ b/lib/usb/usb_f107.c @@ -23,6 +23,8 @@ #include #include "usb_private.h" +#include + static void stm32f107_usbd_init(void); static void stm32f107_set_address(u8 addr); static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, @@ -34,6 +36,10 @@ static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len); static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len); static void stm32f107_poll(void); +/* We keep a backup copy of the out endpoint size registers to restore them + * after a transaction */ +static u32 doeptsiz[4]; + const struct _usbd_driver stm32f107_usb_driver = { .init = stm32f107_usbd_init, .set_address = stm32f107_set_address, @@ -49,13 +55,49 @@ const struct _usbd_driver stm32f107_usb_driver = { /** Initialize the USB device controller hardware of the STM32. */ static void stm32f107_usbd_init(void) { + int i; /* TODO: Enable interrupts on Reset, Transfer, Suspend and Resume */ + + /* WARNING: Undocumented! Select internal PHY */ + OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_PHYSEL; + /* Enable VBUS sensing in device mode and power down the phy */ + OTG_FS_GCCFG |= OTG_FS_GCCFG_VBUSBSEN | OTG_FS_GCCFG_PWRDWN; + + for(i = 0; i < 800000; i++) __asm__("nop"); + + /* Wait for AHB idle */ + while(!(OTG_FS_GRSTCTL & OTG_FS_GRSTCTL_AHBIDL)); + /* Do core soft reset */ + OTG_FS_GRSTCTL |= OTG_FS_GRSTCTL_CSRST; + while(OTG_FS_GRSTCTL & OTG_FS_GRSTCTL_CSRST); + + for(i = 0; i < 800000; i++) __asm__("nop"); + + /* Force peripheral only mode. */ + OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_FDMOD; + + /* Full speed device */ + OTG_FS_DCFG |= OTG_FS_DCFG_DSPD; + + /* Restart the phy clock */ + OTG_FS_PCGCCTL = 0; + + + /* Unmask interrupts for TX and RX */ + OTG_FS_GINTMSK &= OTG_FS_GINTMSK_RXFLVLM; } static void stm32f107_set_address(u8 addr) { - (void)addr; + /* There is something badly wrong gere! */ + /* TODO: Set device address and enable. */ + + /* This I think is correct, but doesn't work at all... */ + //OTG_FS_DCFG = (OTG_FS_DCFG & ~OTG_FS_DCFG_DAD) | (addr << 4); + + /* This is obviously incorrect, but sometimes works... */ + OTG_FS_DCFG |= addr << 4; } static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, @@ -65,12 +107,39 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, * Allocate FIFO memory for endpoint. * Install callback funciton. */ - (void)type; (void)max_size; - u8 dir = addr & 0x80; addr &= 0x7f; - if (dir || (addr == 0)) { + if(addr == 0) { /* For the default control endpoint */ + /* Configure IN part */ + if(max_size >= 64) { + OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_64; + } else if(max_size >= 32) { + OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_32; + } else if(max_size >= 16) { + OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_16; + } else { + OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_8; + } + OTG_FS_DIEPTSIZ0 = (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK); + OTG_FS_DIEPCTL0 |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK; + + /* Configure OUT part */ + doeptsiz[0] = OTG_FS_DIEPSIZ0_STUPCNT_1 | (1 << 19) | + (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK); + OTG_FS_DOEPTSIZ(0) = doeptsiz[0]; + OTG_FS_DOEPCTL(0) |= OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK; + + return; + } + + /* TODO: Configuration for other endpoints */ + if (dir) { + OTG_FS_DIEPTSIZ(addr) = (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK); + OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_EPENA | + OTG_FS_DIEPCTL0_SNAK | (type << 18) | + (addr << 22) | max_size; + if (callback) { _usbd_device. user_callback_ctr[addr][USB_TRANSACTION_IN] = @@ -79,6 +148,12 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, } if (!dir) { + doeptsiz[addr] = (1 << 19) | + (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK); + OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr]; + OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA | + OTG_FS_DIEPCTL0_CNAK | (type << 18) | max_size; + if (callback) { _usbd_device. user_callback_ctr[addr][USB_TRANSACTION_OUT] = @@ -94,8 +169,28 @@ static void stm32f107_endpoints_reset(void) static void stm32f107_ep_stall_set(u8 addr, u8 stall) { - /* TODO: set or clear stall condition */ - (void)addr; (void)stall; + if(addr == 0) { + if(stall) + OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL; + else + OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL; + } + + if(addr & 0x80) { + addr &= 0x7F; + + if(stall) + OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL; + else + OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL; + /* TODO: Reset to DATA0 */ + } else { + if(stall) + OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL; + else + OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL; + /* TODO: Reset to DATA0 */ + } } static u8 stm32f107_ep_stall_get(u8 addr) @@ -108,18 +203,51 @@ static u8 stm32f107_ep_stall_get(u8 addr) static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len) { + const u32 *buf32 = buf; + int i; + addr &= 0x7F; - /* TODO: Send packet on endpoint */ - (void)buf; + /* Enable endpoint for transmission */ + OTG_FS_DIEPTSIZ(addr) = (1 << 19) | len; + OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_CNAK; + + /* Copy buffer to endpoint FIFO */ + u32 *fifo = OTG_FS_FIFO(addr); + for(i = len; i > 0; i -= 4) { + *fifo++ = *buf32++; + } return len; } +/* Received packet size for each endpoint. This is assigned in + * stm32f107_poll() which reads the packet status push register GRXSTSP + * for use in stm32f107_ep_read_packet(). + */ +static uint16_t rxbcnt[4]; + static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len) { - /* TODO: Read packet from endpoint */ - (void)addr; (void)buf; (void)len; + int i; + u32 *buf32 = buf; + u32 extra; + + len = MIN(len, rxbcnt[addr]); + rxbcnt[addr] = 0; + + u32 *fifo = OTG_FS_FIFO(addr); + for(i = len; i >= 4; i -= 4) { + *buf32++ = *fifo++; + } + + if(i) { + extra = *fifo; + memcpy(buf32, &extra, i); + } + + OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr]; + OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA | OTG_FS_DOEPCTL0_CNAK; return len; } @@ -127,23 +255,55 @@ static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len) static void stm32f107_poll(void) { /* TODO: Read interrupt status register */ + u32 intsts = OTG_FS_GINTSTS; - /* TODO: Handle USB RESET condition */ - if (0) { + if (intsts & OTG_FS_GINTSTS_ENUMDNE) { + /* TODO: Handle USB RESET condition */ + OTG_FS_GINTSTS = OTG_FS_GINTSTS_ENUMDNE; _usbd_reset(); return; } /* TODO: Handle transfer complete condition */ - if (0) { - u8 ep; + /* Note: RX and TX handled differently in this device. */ + if (intsts & OTG_FS_GINTSTS_RXFLVL) { + /* Receive FIFO non-empty */ + u32 rxstsp = OTG_FS_GRXSTSP; + u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK; + if((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) && + (pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP)) return; + + u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK; u8 type; + if(pktsts == OTG_FS_GRXSTSP_PKTSTS_SETUP) + type = USB_TRANSACTION_SETUP; + else + type = USB_TRANSACTION_OUT; + + /* Save packet size for stm32f107_ep_read_packet() */ + rxbcnt[ep] = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4; if (_usbd_device.user_callback_ctr[ep][type]) _usbd_device.user_callback_ctr[ep][type] (ep); /* TODO: clear any interrupt flag */ } + /* There is no global interrupt flag for transmit complete. + * the XFRC bit must be checked in each OTG_FS_DIEPINT(x) + */ + /* TODO: Check on endpoint interrupt... */ + { + int i; + for (i = 0; i < 4; i++) { /* Iterate over endpoints */ + if(OTG_FS_DIEPINT(i) & OTG_FS_DIEPINTX_XFRC) { + /* Transfer complete */ + if (_usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN]) + _usbd_device.user_callback_ctr[i][USB_TRANSACTION_IN] (i); + OTG_FS_DIEPINT(i) = OTG_FS_DIEPINTX_XFRC; + } + } + } + /* TODO: Handle suspend condition */ if (0) { /* TODO: Clear suspend interrupt flag */ -- cgit v1.2.3