From b05a5dcf2a2d5aa42e80cabf6aaf7a63133b5332 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 29 Oct 2011 21:30:26 +1300 Subject: [PATCH] Fixed some F105/F107 USB issues. Added user callback on SOF. Made examples depend on lib. --- Makefile | 2 +- include/libopencm3/stm32/otg_fs.h | 7 +++---- include/libopencm3/usb/usbd.h | 1 + lib/usb/usb.c | 5 +++++ lib/usb/usb_f103.c | 6 +++++- lib/usb/usb_f107.c | 29 ++++++++++++++++++++--------- lib/usb/usb_private.h | 1 + 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index fe06961f..5f58c848 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ lib: fi; \ done -examples: +examples: lib $(Q)for i in $(addsuffix /*/*,$(addprefix $@/,$(TARGETS))); do \ if [ -d $$i ]; then \ printf " BUILD $$i\n"; \ diff --git a/include/libopencm3/stm32/otg_fs.h b/include/libopencm3/stm32/otg_fs.h index e1d7a6aa..18709e88 100644 --- a/include/libopencm3/stm32/otg_fs.h +++ b/include/libopencm3/stm32/otg_fs.h @@ -39,7 +39,7 @@ #define OTG_FS_GCCFG MMIO32(USB_OTG_FS_BASE + 0x038) #define OTG_FS_CID MMIO32(USB_OTG_FS_BASE + 0x03C) #define OTG_FS_HPTXFSIZ MMIO32(USB_OTG_FS_BASE + 0x100) -#define OTG_FS_DIEPTXF(x) MMIO32(USB_OTG_FS_BASE + 0x104 + 4*(x)) +#define OTG_FS_DIEPTXF(x) MMIO32(USB_OTG_FS_BASE + 0x104 + 4*(x-1)) /* Host-mode Control and Status Registers */ #define OTG_FS_HCFG MMIO32(USB_OTG_FS_BASE + 0x400) @@ -81,7 +81,7 @@ #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))) +#define OTG_FS_FIFO(x) ((volatile u32*)(USB_OTG_FS_BASE + (((x) + 1) << 12))) /* Global CSRs */ /* OTG_FS AHB configuration register (OTG_FS_GAHBCFG) */ @@ -100,8 +100,7 @@ #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) +#define OTG_FS_GUSBCFG_PHYSEL (1 << 7) /* OTG_FS reset register (OTG_FS_GRSTCTL) */ #define OTG_FS_GRSTCTL_AHBIDL (1 << 31) diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h index c73de072..2340fb0c 100644 --- a/include/libopencm3/usb/usbd.h +++ b/include/libopencm3/usb/usbd.h @@ -41,6 +41,7 @@ extern void usbd_set_control_buffer_size(u16 size); extern void usbd_register_reset_callback(void (*callback)(void)); extern void usbd_register_suspend_callback(void (*callback)(void)); extern void usbd_register_resume_callback(void (*callback)(void)); +extern void usbd_register_sof_callback(void (*callback)(void)); typedef int (*usbd_control_callback)(struct usb_setup_data *req, u8 **buf, u16 *len, void (**complete)(struct usb_setup_data *req)); diff --git a/lib/usb/usb.c b/lib/usb/usb.c index 59c526dd..08ad5f00 100644 --- a/lib/usb/usb.c +++ b/lib/usb/usb.c @@ -80,6 +80,11 @@ void usbd_register_resume_callback(void (*callback)(void)) _usbd_device.user_callback_resume = callback; } +void usbd_register_sof_callback(void (*callback)(void)) +{ + _usbd_device.user_callback_sof = callback; +} + void usbd_set_control_buffer_size(u16 size) { _usbd_device.ctrl_buf_len = size; diff --git a/lib/usb/usb_f103.c b/lib/usb/usb_f103.c index 594d3c6b..1c9a8ec4 100644 --- a/lib/usb/usb_f103.c +++ b/lib/usb/usb_f103.c @@ -300,6 +300,10 @@ static void stm32f103_poll(void) _usbd_device.user_callback_resume(); } - if (istr & USB_ISTR_SOF) + if (istr & USB_ISTR_SOF) { + if (_usbd_device.user_callback_sof) + _usbd_device.user_callback_sof(); USB_CLR_ISTR_SOF(); + } } + diff --git a/lib/usb/usb_f107.c b/lib/usb/usb_f107.c index 134b728b..5e17ebf4 100644 --- a/lib/usb/usb_f107.c +++ b/lib/usb/usb_f107.c @@ -17,7 +17,6 @@ * along with this program. If not, see . */ -#include #include #include #include @@ -29,6 +28,7 @@ /* Receive FIFO size in 32-bit words */ #define RX_FIFO_SIZE 128 static uint16_t fifo_mem_top; +static uint16_t fifo_mem_top_ep0; static u8 force_nak[4]; @@ -64,10 +64,8 @@ const struct _usbd_driver stm32f107_usb_driver = { /** Initialize the USB device controller hardware of the STM32. */ static void stm32f107_usbd_init(void) { - rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); OTG_FS_GINTSTS = OTG_FS_GINTSTS_MMIS; - /* 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; @@ -141,6 +139,7 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, OTG_FS_GNPTXFSIZ = ((max_size / 4) << 16) | RX_FIFO_SIZE; fifo_mem_top += max_size / 4; + fifo_mem_top_ep0 = fifo_mem_top; return; } @@ -152,7 +151,7 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, 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) | - OTG_FS_DIEPCTL0_USBAEP | + OTG_FS_DIEPCTL0_USBAEP | OTG_FS_DIEPCTLX_SD0PID | (addr << 22) | max_size; if (callback) { @@ -168,6 +167,7 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr]; OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA | OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK | + OTG_FS_DOEPCTLX_SD0PID | (type << 18) | max_size; if (callback) { @@ -181,7 +181,7 @@ static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size, static void stm32f107_endpoints_reset(void) { /* The core resets the endpoints automatically on reset */ - fifo_mem_top = RX_FIFO_SIZE; + fifo_mem_top = fifo_mem_top_ep0; } static void stm32f107_ep_stall_set(u8 addr, u8 stall) @@ -242,12 +242,16 @@ static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len) addr &= 0x7F; + /* Return if endpoint is already enabled. */ + if(OTG_FS_DTXFSTS(addr) < (len >> 2)) + return 0; + /* 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); + volatile u32 *fifo = OTG_FS_FIFO(addr); for(i = len; i > 0; i -= 4) { *fifo++ = *buf32++; } @@ -270,16 +274,19 @@ static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len) len = MIN(len, rxbcnt[addr]); rxbcnt[addr] = 0; - u32 *fifo = OTG_FS_FIFO(addr); + volatile u32 *fifo = OTG_FS_FIFO(addr); for(i = len; i >= 4; i -= 4) { *buf32++ = *fifo++; } if(i) { - extra = *fifo; + extra = *fifo++; memcpy(buf32, &extra, i); } + if(len == 8) + extra = *fifo++; + OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr]; OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA | (force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK); @@ -296,6 +303,7 @@ static void stm32f107_poll(void) if (intsts & OTG_FS_GINTSTS_ENUMDNE) { /* Handle USB RESET condition */ OTG_FS_GINTSTS = OTG_FS_GINTSTS_ENUMDNE; + fifo_mem_top = RX_FIFO_SIZE; _usbd_reset(); return; } @@ -347,7 +355,10 @@ static void stm32f107_poll(void) OTG_FS_GINTSTS = OTG_FS_GINTSTS_WKUPINT; } - if (intsts & OTG_FS_GINTSTS_SOF) + if (intsts & OTG_FS_GINTSTS_SOF) { + if (_usbd_device.user_callback_sof) + _usbd_device.user_callback_sof(); OTG_FS_GINTSTS = OTG_FS_GINTSTS_SOF; + } } diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h index 40d59a11..39716b52 100644 --- a/lib/usb/usb_private.h +++ b/lib/usb/usb_private.h @@ -42,6 +42,7 @@ extern struct _usbd_device { void (*user_callback_reset)(void); void (*user_callback_suspend)(void); void (*user_callback_resume)(void); + void (*user_callback_sof)(void); struct user_control_callback { usbd_control_callback cb;