Просмотр исходного кода

Merge pull request #1 from dmitrystu/master

Merge mainline back to this
Maxthon Chan 8 лет назад
Родитель
Сommit
ded6c46137
17 измененных файлов с 1301 добавлено и 189 удалено
  1. 15 2
      .gitignore
  2. 93 53
      Makefile
  3. 37 2
      demo/cdc_loop.c
  4. 13 0
      demo/cdc_startup.c
  5. 87 0
      demo/stm32f103x6.ld
  6. 14 14
      inc/usb.h
  7. 13 5
      inc/usbd_core.h
  8. 16 9
      readme.md
  9. 47 0
      src/memmap.inc
  10. 8 5
      src/usb_32v0.c
  11. 24 39
      src/usb_32v0A.S
  12. 8 5
      src/usb_32v1.c
  13. 25 30
      src/usb_32v1A.S
  14. 10 9
      src/usb_32v2.c
  15. 48 15
      src/usb_32v3.c
  16. 842 0
      src/usb_32v3A.S
  17. 1 1
      src/usbd_core.c

+ 15 - 2
.gitignore

@@ -1,10 +1,23 @@
+#compile artefacts
 obj/*
-svd/*
-html/*
+*.hex
 *.elf
 *.map
+*.a
+
+#ide/editor files
 *.depend
 *.ebp
 *.elay
+*.sublime-project
+*.sublime-workspace
+
+#debug 
+svd/*
 openocd.cfg
+
+#doxydoc artefacts
+html/*
+
+#other junk
 .DS_Store

+ 93 - 53
Makefile

@@ -1,6 +1,6 @@
 CMSIS       ?=../../CMSIS
-CMSISDEV     = $(CMSIS)/Device/ST
-CMSISINC     = $(CMSIS)/Include
+CMSISDEV    ?= $(CMSIS)/Device
+CMSISCORE   ?= $(CMSIS)/CMSIS/Include $(CMSIS)/CMSIS/Core/Include
 FLASH       ?= st-flash
 TOOLSET     ?= arm-none-eabi-
 CC           = $(TOOLSET)gcc
@@ -8,40 +8,6 @@ LD           = $(TOOLSET)gcc
 AR           = $(TOOLSET)gcc-ar
 OBJCOPY      = $(TOOLSET)objcopy
 
-
-STARTUP.stm32l052x8  = $(CMSISDEV)/STM32L0xx/Source/Templates/gcc/startup_stm32l052xx.s
-CFLAGS.stm32l052x8   = -mcpu=cortex-m0plus -mfloat-abi=soft
-DEFINES.stm32l052x8  = STM32L0 STM32L052xx
-LDSCRIPT.stm32l052x8 = demo/stm32l052x8.ld
-
-STARTUP.stm32l100xc  = $(CMSISDEV)/STM32L1xx/Source/Templates/gcc/startup_stm32l100xc.s
-CFLAGS.stm32l100xc   = -mcpu=cortex-m3 -mfloat-abi=soft
-DEFINES.stm32l100xc  = STM32L1 STM32L100xC
-LDSCRIPT.stm32l100xc = demo/stm32l100xc.ld
-
-STARTUP.stm32l476rg  = $(CMSISDEV)/STM32L4xx/Source/Templates/gcc/startup_stm32l476xx.s
-CFLAGS.stm32l476rg   = -mcpu=cortex-m4
-DEFINES.stm32l476rg  = STM32L4 STM32L476xx
-LDSCRIPT.stm32l476rg = demo/stm32l476xg.ld
-
-
-MCU         ?= stm32l100xc
-LDFLAGS     ?= --specs=nano.specs -nostartfiles -Wl,--gc-sections
-DSRC         = $(wildcard demo/*.c) $(wildcard demo/*.S) $(STARTUP.$(MCU))
-DOBJ         = $(call fixpath, $(addsuffix .o, $(basename $(DSRC))))
-DOUT         = cdc-loop
-LDSCRIPT     = $(call fixpath, $(LDSCRIPT.$(MCU)))
-
-
-MODULE      ?= libusb_stm32.a
-CFLAGS      ?= $(CFLAGS.$(MCU))
-CFLAGS2      = -mthumb -Os -std=gnu99
-DEFINES     ?= $(DEFINES.$(MCU)) FORCE_C_DRIVER
-INCLUDES    ?= $(CMSISDEV) $(CMSISINC) .
-SOURCES      = $(wildcard src/*.c) $(wildcard src/*.S)
-OBJECTS      = $(addsuffix .o, $(basename $(SOURCES)))
-ARFLAGS     ?= -cvq
-
 ifeq ($(OS),Windows_NT)
 	RM = del /Q
 	fixpath = $(strip $(subst /,\, $1))
@@ -50,6 +16,59 @@ else
 	fixpath = $(strip $1)
 endif
 
+MODULE      ?= libusb.a
+CFLAGS      ?= -mcpu=cortex-m3
+DEFINES     ?= STM32F1 STM32F103x6
+
+ARFLAGS      = -cvq
+LDFLAGS      = --specs=nano.specs -nostartfiles -Wl,--gc-sections
+INCLUDES     = $(CMSISDEV)/ST $(CMSISCORE) inc
+CFLAGS2      = -mthumb -Os -std=gnu99
+
+OBJDIR       = obj
+SOURCES      = $(wildcard src/*.c) $(wildcard src/*.S)
+OBJECTS      = $(addprefix $(OBJDIR)/, $(addsuffix .o, $(notdir $(basename $(SOURCES)))))
+DSRC         = $(wildcard demo/*.c) $(wildcard demo/*.S) $(STARTUP)
+DOBJ         = $(addprefix $(OBJDIR)/, $(addsuffix .o, $(notdir $(basename $(DSRC)))))
+DOUT         = cdc_loop
+
+SRCPATH      = $(sort $(dir $(SOURCES) $(DSRC)))
+vpath %.c $(SRCPATH)
+vpath %.S $(SRCPATH)
+vpath %.s $(SRCPATH)
+
+
+help all:
+	@echo 'Usage: make target [program]'
+	@echo 'Available targets are:'
+	@echo '  bluepill'
+	@echo '  stm32f103x6   CDC loopback demo for STM32F103 based boards'
+	@echo '  32l100c-disco'
+	@echo '  stm32l100xc   CDC loopback demo for STM32L100xC based boards'
+	@echo '  32l476rg-nucleo'
+	@echo '  stm32l476rg   CDC loopback demo for STM32L476xG based boards'
+	@echo '  stm32l052x8   CDC loopback demo for STM32L052x8 based boards'
+	@echo '  doc           DOXYGEN documentation'
+	@echo '  module        static library module using following envars (defaults)'
+	@echo '                MODULE  module name (libusb.a)'
+	@echo '                CFLAGS  mcu specified compiler flags (-mcpu=cortex-m3)'
+	@echo '                DEFINES mcu and module specified defines (STM32F1 STM32F103x6)'
+	@echo '                        see USB Device HW driver and core API section for the'
+	@echo '                        compile-time control macros'
+	@echo ' '
+	@echo 'Environmental variables (defaults):'
+	@echo '  CMSIS         Path to the CMSIS V4 or CMSIS V5 root folder ($(CMSIS))'
+	@echo '  CMSISCORE     Path to the CMSIS Core include folder(s) ($(CMSISCORE))'
+	@echo '  CMSISDEV      Path to the CMSIS Device folder ($(CMSISDEV))'
+	@echo '  FLASH         st-link flash utility ($(FLASH))'
+	@echo ' '
+	@echo 'Examples:'
+	@echo '  make bluepill program'
+	@echo '  make module MODULE="usbd.a" CFLAGS="-mcpu=cotrex-m4" DEFINES="STM32L4 STM32L476xx USBD_VBUS_DETECT"'
+
+$(OBJDIR):
+	@mkdir $@
+
 program: $(DOUT).hex
 	$(FLASH) --reset --format ihex write $(DOUT).hex
 
@@ -59,35 +78,56 @@ $(DOUT).hex : $(DOUT).elf
 	@echo building $@
 	@$(OBJCOPY) -O ihex $< $@
 
-$(DOUT).elf : $(DOBJ) $(OBJECTS)
-	@echo building $@ for $(MCU)
-	@$(LD) $(CFLAGS) $(CFLAGS2) $(LDFLAGS) -Wl,--script='$(LDSCRIPT)' -Wl,-Map=$(DOUT).map $(DOBJ) -lc $(OBJECTS) -o $@
+$(DOUT).elf : $(OBJDIR) $(DOBJ) $(OBJECTS)
+	@echo building $@
+	@$(LD) $(CFLAGS) $(CFLAGS2) $(LDFLAGS) -Wl,--script='$(LDSCRIPT)' -Wl,-Map=$(DOUT).map $(DOBJ) $(OBJECTS) -o $@
 
 clean:
-	$(RM) $(DOUT).* $(OBJECTS)
+	@$(RM) $(DOUT).*
+	@$(RM) $(call fixpath, $(OBJDIR)/*.*)
 
 doc:
 	doxygen
 
-module: $(MODULE)
-
+module: clean $(MODULE)
 
-$(MODULE): $(OBJECTS)
+$(MODULE): $(OBJDIR) $(OBJECTS)
 	@$(AR) $(ARFLAGS) $(MODULE) $(OBJECTS)
 
-%.o: %.c
-	@echo compiling $@
+$(OBJDIR)/%.o: %.c
+	@echo compiling $<
 	@$(CC) $(CFLAGS) $(CFLAGS2) $(addprefix -D, $(DEFINES)) $(addprefix -I, $(INCLUDES)) -c $< -o $@
 
-%.o: %.S
-	@echo assembling $@
+$(OBJDIR)/%.o: %.S
+	@echo assembling $<
 	@$(CC) $(CFLAGS) $(CFLAGS2) $(addprefix -D, $(DEFINES)) $(addprefix -I, $(INCLUDES)) -c $< -o $@
 
-%.o: %.s
-	@echo assembling $@
+$(OBJDIR)/%.o: %.s
+	@echo assembling $<
 	@$(CC) $(CFLAGS) $(CFLAGS2) $(addprefix -D, $(DEFINES)) $(addprefix -I, $(INCLUDES)) -c $< -o $@
 
-
-.INTERMEDIATE: $(OBJECTS) $(DOBJ)
-
-.PHONY: module doc demo clean program
+.PHONY: module doc demo clean program help all
+
+stm32f103x6 bluepill:
+	@$(MAKE) clean demo STARTUP='$(CMSISDEV)/ST/STM32F1xx/Source/Templates/gcc/startup_stm32f103x6.s' \
+						LDSCRIPT='demo/stm32f103x6.ld' \
+						DEFINES='STM32F1 STM32F103x6 USBD_SOF_DISABLED USBD_ASM_DRIVER' \
+						CFLAGS='-mcpu=cortex-m3 -mthumb'
+
+stm32l052x8:
+	@$(MAKE) clean demo STARTUP='$(CMSISDEV)/ST/STM32L0xx/Source/Templates/gcc/startup_stm32l052xx.s' \
+						LDSCRIPT='demo/stm32l052x8.ld' \
+						DEFINES='STM32L0 STM32L052xx USBD_SOF_DISABLED' \
+						CFLAGS='-mcpu=cortex-m0plus -mthumb'
+
+stm32l100xc 32l100c-disco:
+	@$(MAKE) clean demo STARTUP='$(CMSISDEV)/ST/STM32L1xx/Source/Templates/gcc/startup_stm32l100xc.s' \
+						LDSCRIPT='demo/stm32l100xc.ld' \
+						DEFINES='STM32L1 STM32L100xC USBD_SOF_DISABLED' \
+						CFLAGS='-mcpu=cortex-m3 -mthumb'
+
+stm32l476xg 32l476rg-nucleo:
+	@$(MAKE) clean demo STARTUP='$(CMSISDEV)/ST/STM32L4xx/Source/Templates/gcc/startup_stm32l476xx.s' \
+						LDSCRIPT='demo/stm32l476xg.ld' \
+						DEFINES='STM32L4 STM32L476xx USBD_SOF_DISABLED' \
+						CFLAGS='-mcpu=cortex-m4 -mthumb'

+ 37 - 2
demo/cdc_loop.c

@@ -16,8 +16,9 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
+#include "stm32.h"
 #include "usb.h"
-#include "inc/usb_cdc.h"
+#include "usb_cdc.h"
 
 #define CDC_EP0_SIZE    0x08
 #define CDC_RXD_EP      0x01
@@ -27,6 +28,8 @@
 #define CDC_NTF_SZ      0x08
 #define CDC_LOOPBACK
 
+//#define CDC_USE_IRQ   /* uncomment to build interrupt-based demo */
+
 struct cdc_config {
     struct usb_config_descriptor        config;
     struct usb_interface_descriptor     comm;
@@ -281,11 +284,43 @@ static void cdc_init_usbd(void) {
     usbd_reg_descr(&udev, cdc_getdesc);
 }
 
+#if defined(CDC_USE_IRQ)
+#if defined(STM32L052xx)
+    #define USB_HANDLER     USB_IRQHandler
+    #define USB_NVIC_IRQ    USB_IRQn
+#elif defined(STM32L100xC)
+    #define USB_HANDLER     USB_LP_IRQHandler
+    #define USB_NVIC_IRQ    USB_LP_IRQn
+#elif defined(STM32L476xx)
+    #define USB_HANDLER     OTG_FS_IRQHandler
+    #define USB_NVIC_IRQ    OTG_FS_IRQn
+#elif defined(STM32F103x6)
+    #define USB_HANDLER     USB_LP_CAN1_RX0_IRQHandler
+    #define USB_NVIC_IRQ    USB_LP_CAN1_RX0_IRQn
+#else
+    #error Not supported
+#endif
+
+void USB_HANDLER(void) {
+    usbd_poll(&udev);
+}
+
 void main(void) {
     cdc_init_usbd();
+    NVIC_EnableIRQ(USB_NVIC_IRQ);
     usbd_enable(&udev, true);
     usbd_connect(&udev, true);
     while(1) {
-    usbd_poll(&udev);
+        __WFI();
     }
 }
+#else
+void main(void) {
+    cdc_init_usbd();
+    usbd_enable(&udev, true);
+    usbd_connect(&udev, true);
+    while(1) {
+        usbd_poll(&udev);
+    }
+}
+#endif

+ 13 - 0
demo/cdc_startup.c

@@ -65,6 +65,19 @@ static void cdc_init_rcc (void) {
     /* set GP11 and GP12 as USB data pins AF10 */
     _BST(GPIOA->AFR[1], (0x0A << 12) | (0x0A << 16));
     _BMD(GPIOA->MODER, (0x03 << 22) | (0x03 << 24), (0x02 << 22) | (0x02 << 24));
+
+#elif defined(STM32F103x6)
+    /* set flash latency 1WS */
+    _BMD(FLASH->ACR, FLASH_ACR_LATENCY, FLASH_ACR_LATENCY_1);
+    /* use PLL 48MHz clock from 8Mhz HSI */
+    _BMD(RCC->CFGR,
+         RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC | RCC_CFGR_USBPRE,
+         RCC_CFGR_PLLMULL12 | RCC_CFGR_USBPRE);
+    _BST(RCC->CR, RCC_CR_PLLON);
+    _WBS(RCC->CR, RCC_CR_PLLRDY);
+    /* switch to PLL */
+    _BMD(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
+    _WVL(RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_PLL);
 #else
     #error Not supported
 #endif

+ 87 - 0
demo/stm32f103x6.ld

@@ -0,0 +1,87 @@
+ENTRY(Reset_Handler)
+MEMORY
+{
+    ROM  (rx): ORIGIN = 0x08000000, LENGTH =  32K
+    RAM (rwx): ORIGIN = 0x20000000, LENGTH =  10K
+}
+SECTIONS
+{
+    .text :
+    {
+        KEEP(*(.isr_vector))
+        *(.text*)
+        KEEP(*(.init))  KEEP(*(.fini))
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+        *crtbegin.o(.dtors)
+        *crtbegin?.o(.dtors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o).dtors)
+        *(SORT(.dtors.*))
+        *(.dtors)
+        *(.rodata*)
+        KEEP(*(.eh_frame*))
+    } > ROM
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > ROM
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > ROM
+    __exidx_end = .;
+    __etext = .;
+    .data : AT (__etext)
+    {
+        __data_start__ = .;
+        *(vtable)
+        *(.data*)
+        . = ALIGN(4);
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+        . = ALIGN(4);
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+        . = ALIGN(4);
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        KEEP(*(SORT(.fini_array.*)))
+        KEEP(*(.fini_array))
+        PROVIDE_HIDDEN (__fini_array_end = .);
+        . = ALIGN(4);
+        __data_end__ = .;
+    } > RAM
+    .bss (NOLOAD) :
+    {
+        __bss_start__ = .;
+        *(.bss*)
+        *(COMMON)
+        __bss_end__ = .;
+    } > RAM
+    .heap (NOLOAD) :
+    {
+        __end__ = .;
+        *(.heap*)
+        __HeapLimit = .;
+    } > RAM
+    .stack_dummy (NOLOAD) :
+    {
+        *(.stack)
+    } > RAM
+    __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+    __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+    PROVIDE(__stack = __StackTop);
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+    PROVIDE(_estack = __stack);
+    PROVIDE(_sidata = __etext);
+    PROVIDE(_sdata = __data_start__);
+    PROVIDE(_edata = __data_end__);
+    PROVIDE(_sbss = __bss_start__);
+    PROVIDE(_ebss = __bss_end__);
+}

+ 14 - 14
usb.h → inc/usb.h

@@ -28,43 +28,40 @@
     defined(STM32L452xx) || defined(STM32L462xx) || \
     defined(STM32F042x6) || defined(STM32F048xx) || \
     defined(STM32F070x6) || defined(STM32F070xB) || \
-    defined(STM32F072xB) || defined(STM32F078xx) \
+    defined(STM32F072xB) || defined(STM32F078xx)
 
     #define USE_STMV0_DRIVER
 
-    #if (defined(FORCE_ASM_DRIVER) || defined(STM32L052xx)) && !defined(FORCE_C_DRIVER)
-        #define USE_STMV0A_DRIVER
-    #endif
-
 #elif defined(STM32L1)
     #define USE_STMV1_DRIVER
-    #if (defined(FORCE_ASM_DRIVER) || defined(STM32L100xC)) && !defined(FORCE_C_DRIVER)
-        #define USE_STMV1A_DRIVER
-    #endif
+
 #elif defined(STM32L476xx)
     #define USE_STMV2_DRIVER
+
 #elif defined(STM32F102x6) || defined(STM32F102xB) || \
       defined(STM32F103x6) || defined(STM32F103xB) || \
       defined(STM32F103xE) || defined(STM32F103xG) || \
       defined(STM32F302x8) || defined(STM32F302xC) || defined(STM32F302xE) || \
       defined(STM32F303xC) || defined(STM32F303xE) || \
       defined(STM32F373xC)
-    #define USE_STMV3_DRIVER
+
+      #define USE_STMV3_DRIVER
+
 #else
     #error Unsupported STM32 family
 #endif
 
 
-#include "inc/usbd_core.h"
+#include "usbd_core.h"
 #if !defined(__ASSEMBLER__)
-    #include "inc/usb_std.h"
-    #if defined(USE_STMV0A_DRIVER)
+    #include "usb_std.h"
+    #if defined(USE_STMV0_DRIVER) && defined(USBD_ASM_DRIVER)
         extern const struct usbd_driver usb_stmv0a;
         #define usbd_hw usb_stmv0a
     #elif defined(USE_STMV0_DRIVER)
         extern const struct usbd_driver usb_stmv0;
         #define usbd_hw usb_stmv0
-    #elif defined(USE_STMV1A_DRIVER)
+    #elif defined(USE_STMV1_DRIVER) && defined(USBD_ASM_DRIVER)
         extern const struct usbd_driver usb_stmv1a;
         #define usbd_hw usb_stmv1a
     #elif defined(USE_STMV1_DRIVER)
@@ -73,7 +70,10 @@
     #elif defined(USE_STMV2_DRIVER)
         extern const struct usbd_driver usb_stmv2;
         #define usbd_hw usb_stmv2
-#elif defined(USE_STMV3_DRIVER)
+    #elif defined(USE_STMV3_DRIVER) && defined(USBD_ASM_DRIVER)
+        extern const struct usbd_driver usb_stmv3a;
+        #define usbd_hw usb_stmv3a
+    #elif defined(USE_STMV3_DRIVER)
         extern const struct usbd_driver usb_stmv3;
         #define usbd_hw usb_stmv3
     #endif

+ 13 - 5
inc/usbd_core.h

@@ -21,9 +21,18 @@
 
 /**\addtogroup USBD_HW_CORE USB Device HW driver and core API
  * @{ */
+#if defined(__DOXYGEN__)
+/**\name Compile-time control macros
+ * @{ */
+#define USBD_SOF_DISABLED   /**<\brief Disables SOF handling.*/
+#define USBD_VBUS_DETECT    /**<\brief Enables Vbus detection for V2 driver.*/
+#define USBD_DP_PORT        /**<\brief DP pullup port for F103/F303 driver.*/
+#define USBD_DP_PIN         /**<\brief DP pullup pin for F103/F303 driver.*/
+/** @} */
+#endif
 
 /**\addtogroup USBD_HW USB hardware driver
- * \brief Contains HW driver API 
+ * \brief Contains HW driver API
  * @{ */
 /**\anchor USB_EVENTS
  * \name USB device events
@@ -36,8 +45,7 @@
 #define usbd_evt_eprx       5   /**<\brief Data packet received.*/
 #define usbd_evt_epsetup    6   /**<\brief Setup packet received.*/
 #define usbd_evt_error      7   /**<\brief Data error.*/
-#define usbd_evt_esof       8   /**<\brief Missed SOF.*/
-#define usbd_evt_count      9
+#define usbd_evt_count      8
 /** @} */
 
 /**\anchor USB_LANES_STATUS
@@ -58,7 +66,7 @@
 /** @} */
 
 /**\addtogroup USBD_CORE USB device core
- * \brief Contains core API 
+ * \brief Contains core API
  * @{ */
 #define USB_EPTYPE_DBLBUF   0x04    /**<\brief Doublebuffered endpoint (bulk endpoint only).*/
 
@@ -181,7 +189,7 @@ typedef usbd_respond (*usbd_ctl_callback)(usbd_device *dev, usbd_ctlreq *req, us
 /**\brief USB get descriptor callback function
  * \details Called when GET_DESCRIPTOR request issued
  * \param[in] req pointer to usb control request structure
- * \param[in,out] address pointer to the descriptor in memory. Points to req->data by default. You 
+ * \param[in,out] address pointer to the descriptor in memory. Points to req->data by default. You
  * can use this buffer.
  * \param[in,out] dsize descriptor size. maximum buffer size by default.
  * \return usbd_ack if you passed the correct descriptor, usbd_fail otherwise.

+ 16 - 9
readme.md

@@ -5,6 +5,12 @@
 + Completely separated USB hardware driver and usb core
 + Easy to use.
 
+### Requirements ###
+
++ [CMSIS V4](https://github.com/ARM-software/CMSIS) or [CMSIS V5](https://github.com/ARM-software/CMSIS_5).
++ Device peripheral access layer header files for STM32. See [Vendor Template](https://github.com/ARM-software/CMSIS/tree/master/Device/_Template_Vendor) for details.
++ [stm32.h](https://github.com/dmitrystu/stm32h) STM32 universal header
+
 ### Supported hardware ###
 
 | HW driver  | Written on | Endpoints |                     Features | MCU series |
@@ -13,8 +19,9 @@
 | usb_stmv0a | GCC ASM    | 8         | Internal S/N, Doublebuffered, BC1.2 | STM32L0x2 STM32L0x3 STM32L4x2 STM32L4x3 STM32F0x2 STM32F0x8 |
 | usb_stmv1  | GCC C      | 8         | Internal S/N, Doublebuffered | STM32L1xx  |
 | usb_stmv1a | GCC ASM    | 8         | Internal S/N, Doublebuffered | STM32L1xx  |
-| usb_stmv2  | GCC C      | 6         | Internal S/N, Doublebuffered, BC1.2 | STM32L4x5 STM32L4x6 (OTG FS (Device mode)) |
-| usb_stmv3  | GCC C      | 8         | Internal S/N, Doublebuffered | STM32F1xx STM32F3xx  |
+| usb_stmv2  | GCC C      | 6         | Internal S/N, Doublebuffered, BC1.2 | STM32L4x5 STM32L4x6 (OTG FS Device mode) |
+| usb_stmv3  | GCC C      | 8         | Internal S/N, Doublebuffered, optional DP control | STM32F102 STM32F103 STM32F3xx  |
+| usb_stmv3a | GCC ASM    | 8         | Internal S/N, Doublebuffered, optional DP control | STM32F102 STM32F103 STM32F3xx  |
 
 1. Single physical endpoint can be used to implement
   + one bi-directional/single-buffer logical endpoint (CONTROL)
@@ -37,23 +44,23 @@ make module MODULE=path/module.a DEFINES="mcu spcified defines" CFLAGS="cpu cpec
 ```
 + to build demo
 ```
-make demo MCU=stm32l100xc
-make demo MCU=stm32l052x8
-make demo MCU=stm32l476rg
+make bluepill program
+make stm32l052x8
 ```
-+ to flash demo using st-flash
++ to get a help
 ```
-make program
+make help
 ```
 
 ### Default values: ###
 | Variable | Default Value                       | Means                         |
 |----------|-------------------------------------|-------------------------------|
-| CMSIS    | ../../cmsis                         | path to CMSIS root folder     |
+| CMSIS    | ../../CMSIS                         | path to CMSIS root folder     |
+| CMSISDEV | $(CMSIS)/Device                     | path to CMSIS device folder   |
+| CMSISCORE| $(CMSIS)/CMSIS/Include $(CMSIS)/CMSIS/Core/Include | path to CMSIS core headers |
 | MCU      | stm32l100xc                         | MCU selection for demo project|
 | CFLAGS   | -mcpu=cortex-m3 -mfloat-abi=soft    | MCU specified compiler flags  |
 | DEFINES  | STM32L1 STM32L100xC                 | MCU specified defines         |
-| INCLUDES | $(CMSIS)/device/ST $(CMSIS)/include | path to ST CMSIS includes     |
 
 ### Useful Resources ###
 1. [USB Implementers Forum official site](http://www.usb.org/home)

+ 47 - 0
src/memmap.inc

@@ -61,6 +61,53 @@
     #else
         #define UID_BASE        0x1FF800D0
     #endif
+#elif defined(STM32F102x6) || defined(STM32F102xB) || \
+      defined(STM32F103x6) || defined(STM32F103xB) || \
+      defined(stm32F103xE) || defined(STM32F103xG)
+    #define USB_EPBASE      0x40005C00
+    #define USB_REGBASE     0x40005C40
+    #define USB_CNTR        0x00
+    #define USB_ISTR        0x04
+    #define USB_FNR         0x08
+    #define USB_DADDR       0x0C
+    #define USB_BTABLE      0x10
+    #define USB_PMABASE     0x40006000
+    #define RCC_BASE        0x40021000
+    #define RCC_APB1ENR     0x1C
+    #define RCC_APB1RSTR    0x10
+    #define UID_BASE        0x1FFFF7E8
+    #define GPIOA           0x40010800
+    #define GPIOB           0x40010C00
+    #define GPIOC           0x40011000
+    #define GPIOD           0x40011400
+    #define GPIOE           0x40011800
+    #define GPIOF           0x40011C00
+    #define GPIOG           0x40012000
+    #define GPIO_CRL        0x00
+    #define GPIO_CRH        0x04
+    #define GPIO_BSRR       0x10
+#elif defined(STM32F303xB) || defined(STM32F303xC)
+
+    #define USB_EPBASE      0x40005C00
+    #define USB_REGBASE     0x40005C40
+    #define USB_CNTR        0x00
+    #define USB_ISTR        0x04
+    #define USB_FNR         0x08
+    #define USB_DADDR       0x0C
+    #define USB_BTABLE      0x10
+    #define USB_PMABASE     0x40006000
+
+    #define RCC_BASE        0x40021000
+    #define RCC_APB1ENR     0x1C
+    #define RCC_APB1RSTR    0x10
+    #define UID_BASE        0x1FFFF7AC
+
+    #define GPIOA           0x48000000
+    #define GPIOB           0x48000400
+    #define GPIOC           0x48000800
+    #define GPIOD           0x48000C00
+    #define GPIOE           0x48001000
+    #define GPIOF           0x48001400
 #else
     #error Unsupported MCU
 #endif

+ 8 - 5
src/usb_32v0.c

@@ -16,7 +16,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "stm32.h"
-#include "../usb.h"
+#include "usb.h"
 
 #if defined(USE_STMV0_DRIVER)
 
@@ -145,7 +145,11 @@ void enable(bool enable) {
         RCC->APB1ENR  |=  RCC_APB1ENR_USBEN;
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
         RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST;
-        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_ERRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
+        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_ERRM |
+#if !defined(USBD_SOF_DISABLED)
+        USB_CNTR_SOFM |
+#endif
+        USB_CNTR_SUSPM | USB_CNTR_WKUPM;
     } else if (RCC->APB1ENR & RCC_APB1ENR_USBEN) {
         USB->BCDR = 0;
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
@@ -402,9 +406,11 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
             ep_deconfig(i);
         }
         _ev = usbd_evt_reset;
+#if !defined(USBD_SOF_DISABLED)
     } else if (_istr & USB_ISTR_SOF) {
         _ev = usbd_evt_sof;
         USB->ISTR &= ~USB_ISTR_SOF;
+#endif
     } else if (_istr & USB_ISTR_WKUP) {
         _ev = usbd_evt_wkup;
         USB->CNTR &= ~USB_CNTR_FSUSP;
@@ -413,9 +419,6 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
         _ev = usbd_evt_susp;
         USB->CNTR |= USB_CNTR_FSUSP;
         USB->ISTR &= ~USB_ISTR_SUSP;
-    } else if (_istr & USB_ISTR_ESOF) {
-        USB->ISTR &= ~USB_ISTR_ESOF;
-        _ev = usbd_evt_esof;
     } else if (_istr & USB_ISTR_ERR) {
         USB->ISTR &= ~USB_ISTR_ERR;
         _ev = usbd_evt_error;

+ 24 - 39
src/usb_32v0A.S

@@ -17,7 +17,7 @@
     #define __ASSEMBLER__
 #endif
 
-#include "../usb.h"
+#include "usb.h"
 #if defined(USE_STMV0_DRIVER)
 #include "memmap.inc"
 
@@ -163,7 +163,6 @@ _get_serial_desc:
     .thumb_func
     .type   _connect, %function
 _connect:
-#if 1
     ldr     r3, =#USB_REGBASE
     movs    r1, #0x03               //BCDEN + DCDEN
     movs    r2, #usbd_lane_dsc
@@ -191,20 +190,11 @@ _connect:
     subs    r1, r0, #1
     sbcs    r0, r1
     lsls    r0, #15
-    strh    r1, [r3, #USB_BCDR]
+    strh    r0, [r3, #USB_BCDR]
     mov     r0, r2
     bx      lr
-#else
-    subs    r1, r0, #1
-    sbcs    r0, r1
-    lsls    r0, #15
-    ldr     r1, =#USB_REGBASE
-    strh    r0, [r1, #USB_BCDR]      //USB->BCDR
-    bx      lr
-#endif
     .size   _connect, . - _connect
 
-
     .thumb_func
     .type   _setaddr, %function
 _setaddr:
@@ -255,8 +245,12 @@ _enable:
     str     r0, [r2, #RCC_APB1RSTR]     //RCC->APB1RSTR |= USBRST
     bics    r0, r3
     str     r0, [r2, #RCC_APB1RSTR]     //RCC->APB1RSTR &= ~USBRST
-    movs    r0, #0xBE
-    lsls    r0, #0x08           // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
+#if !defined(USBD_SOF_DISABLED)
+    movs    r0, #0xBE                   // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
+#else
+    movs    r0, #0xBC                   // CTRM | ERRM | WKUPM | SUSPM | RESETM
+#endif
+    lsls    r0, #0x08
     strh    r0, [r1]            //set USB->CNTR
     bx      lr
 .L_disable:
@@ -395,19 +389,18 @@ _ep_read:
 .L_epr_dbl:
     lsrs    r0, r5, #8
     eors    r0, r5
-    lsrs    r0, #6          // SW_RX ^ DTOG_RX -> CF
-    bcc     .L_epr_notog    // jmp if SW_RX != DTOG_RX (VALID)
+    lsrs    r0, #7          // SW_RX ^ DTOG_RX -> CF
+    bcs     .L_epr_notog    // jmp if SW_RX != DTOG_RX (VALID)
     ldr     r0, =#EP_NOTOG
     ands    r5, r0
     adds    r5, #EP_RX_SWBUF
     strh    r5, [r3]        // toggling SW_RX
-    ldrh    r5, [r3]
 .L_epr_notog:
-    mvns    r5, r5
-    lsls    r5, #8          // shift ~SW_RX to DTOG_RX
+    ldrh    r5, [r3]
+    lsls    r5, #8          // shift SW_RX to DTOG_RX
 .L_epr_iso:
     lsrs    r5, #15         // DTOG_RX -> CF
-    bcc     .L_epr_sngl
+    bcs     .L_epr_sngl
     subs    r4, #0x04       // set RXADDR0
 .L_epr_sngl:
     ldrh    r0, [r4, #RXCOUNT]
@@ -477,8 +470,6 @@ _ep_write:
     lsrs    r0, #4
     cmp     r0, #0x43       // (OK) TX_VALID + ISO
     beq     .L_epw_iso
-    cmp     r0, #0x13       // (OK) TX_VALID + DBLBULK
-    beq     .L_epw_dbl
     cmp     r0, #0x12       // (OK) TX_NAK + DBLBULK
     beq     .L_epw_dbl
     cmp     r0, #0x02       // (OK) TX_NAK + BULK
@@ -735,20 +726,20 @@ _evt_poll:
     movs    r2, 0x07
     ands    r2, r0
 /* checking USB->ISTR for events */
-    lsls    r0, #17             //CTRM -> CF
+#if !defined(USBD_SOF_DISABLED)
+    lsrs    r1, r0, #10         //SOFM -> CF
+    bcs     .L_ep_sofm
+#endif
+    lsrs    r1, r0, #16         //CTRM -> CF
     bcs     .L_ep_ctrm
-    lsls    r0, #2              //ERRM -> CF
+    lsrs    r1, r0, #14         //ERRM -> CF
     bcs     .L_ep_errm
-    lsls    r0, #1              //WKUPM -> CF
+    lsrs    r1, r0, #13         //WKUPM -> CF
     bcs     .L_ep_wkupm
-    lsls    r0, #1              //SUSPM -> CF
+    lsrs    r1, r0, #12         //SUSPM -> CF
     bcs     .L_ep_suspm
-    lsls    r0, #1              //RESETM -> CF
+    lsrs    r1, r0, #11         //RESETM -> CF
     bcs     .L_ep_resetm
-    lsls    r0, #1              //SOFM -> CF
-    bcs     .L_ep_sofm
-    lsls    r0, #1
-    bcs     .L_ep_esofm
     /* exit with no callback */
     pop     {r0, r1, r4 , r5}
     bx      lr
@@ -783,17 +774,12 @@ _evt_poll:
     movs    r1, #usbd_evt_error
     movs    r4, #ISTRBIT(13)
     b      .L_ep_clristr
-
+#if !defined(USBD_SOF_DISABLED)
 .L_ep_sofm:
     movs    r1, #usbd_evt_sof
     movs    r4, #ISTRBIT(9)
     b       .L_ep_clristr
-
-.L_ep_esofm:
-    movs    r1, #usbd_evt_esof
-    movs    r4, #ISTRBIT(8)
-    b       .L_ep_clristr
-
+#endif
 .L_ep_wkupm:
     ldrh    r1, [r3, #USB_CNTR]     //R1 USB->CNTR
     movs    r5, #0x08
@@ -843,7 +829,6 @@ _evt_poll:
     bx      r3
     .size   _evt_poll, . - _evt_poll
 
-
     .pool
 
    .end

+ 8 - 5
src/usb_32v1.c

@@ -16,7 +16,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "stm32.h"
-#include "../usb.h"
+#include "usb.h"
 
 #if defined(USE_STMV1_DRIVER)
 
@@ -148,7 +148,11 @@ void enable(bool enable) {
         RCC->APB2ENR  |= RCC_APB2ENR_SYSCFGEN;
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
         RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST;
-        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_ERRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM ;
+        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_ERRM |
+#if !defined(USBD_SOF_DISABLED)
+        USB_CNTR_SOFM |
+#endif
+        USB_CNTR_SUSPM | USB_CNTR_WKUPM;
     } else if (RCC->APB1ENR & RCC_APB1ENR_USBEN) {
         SYSCFG->PMC &= ~SYSCFG_PMC_USB_PU;
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
@@ -392,9 +396,11 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
             ep_deconfig(i);
         }
         _ev = usbd_evt_reset;
+#if !defined(USBD_SOF_DISABLED)
     } else if (_istr & USB_ISTR_SOF) {
         _ev = usbd_evt_sof;
         USB->ISTR &= ~USB_ISTR_SOF;
+#endif
     } else if (_istr & USB_ISTR_WKUP) {
         _ev = usbd_evt_wkup;
         USB->CNTR &= ~USB_CNTR_FSUSP;
@@ -403,9 +409,6 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
         _ev = usbd_evt_susp;
         USB->CNTR |= USB_CNTR_FSUSP;
         USB->ISTR &= ~USB_ISTR_SUSP;
-    } else if (_istr & USB_ISTR_ESOF) {
-        USB->ISTR &= ~USB_ISTR_ESOF;
-        _ev = usbd_evt_esof;
     } else if (_istr & USB_ISTR_ERR) {
         USB->ISTR &= ~USB_ISTR_ERR;
         _ev = usbd_evt_error;

+ 25 - 30
src/usb_32v1A.S

@@ -17,7 +17,7 @@
     #define __ASSEMBLER__
 #endif
 
-#include "../usb.h"
+#include "usb.h"
 #if defined(USE_STMV1_DRIVER)
 #include "memmap.inc"
 
@@ -210,7 +210,6 @@ _get_frame:
     .thumb_func
     .type   _enable, %function
 _enable:
-
     ldr     r2, =#RCC_BASE        //RCC
     movs    r3, #0x01
     lsls    r3, #23             //USBEN or USBRST
@@ -232,8 +231,12 @@ _enable:
     orrs    r0, r3
     str     r0, [r2, #RCC_APB2ENR]
 /* setting up USB CNTR */
-    movs    r0, #0xBE
-    lsls    r0, #0x08                   // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
+#if !defined(USBD_SOF_DISABLED)
+    movs    r0, #0xBE                   // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
+#else
+    movs    r0, #0xBC                   // CTRM | ERRM | WKUPM | SUSPM | RESETM
+#endif
+    lsls    r0, #0x08
     strh    r0, [r1, #USB_CNTR]         //set USB->CNTR
     bx      lr
 .L_disable:
@@ -346,7 +349,7 @@ _ep_read:
     push    {r4, r5, lr}
     ldr     r3, =#USB_EPBASE
     ldr     r4, =#USB_PMABASE
-    lsls    r0,  #28
+    lsls    r0, #28
     lsrs    r0, #26
     adds    r3, r0          // *EPR -> R3
     lsls    r0, #2
@@ -374,19 +377,18 @@ _ep_read:
 .L_epr_dbl:
     lsrs    r0, r5, #8
     eors    r0, r5
-    lsrs    r0, #6          // SW_RX ^ DTOG_RX -> CF
-    bcc     .L_epr_notog    // jmp if SW_RX != DTOG_RX (VALID)
+    lsrs    r0, #7          // SW_RX ^ DTOG_RX -> CF
+    bcs     .L_epr_notog    // jmp if SW_RX != DTOG_RX (VALID)
     ldr     r0, =#EP_NOTOG
     ands    r5, r0
     adds    r5, #EP_RX_SWBUF
     strh    r5, [r3]        // toggling SW_RX
-    ldrh    r5, [r3]
 .L_epr_notog:
-    mvns    r5, r5
-    lsls    r5, #8          // shift ~SW_RX to DTOG_RX
+    ldrh    r5, [r3]
+    lsls    r5, #8          // shift SW_RX to DTOG_RX
 .L_epr_iso:
     lsrs    r5, #15         // DTOG_RX -> CF
-    bcc     .L_epr_sngl
+    bcs     .L_epr_sngl
     subs    r4, #0x08       // set RXADDR0
 .L_epr_sngl:
     ldrh    r0, [r4, #RXCOUNT]
@@ -456,8 +458,6 @@ _ep_write:
     lsrs    r0, #4
     cmp     r0, #0x43       // (OK) TX_VALID + ISO
     beq     .L_epw_iso
-    cmp     r0, #0x13       // (OK) TX_VALID + DBLBULK
-    beq     .L_epw_dbl
     cmp     r0, #0x12       // (OK) TX_NAK + DBLBULK
     beq     .L_epw_dbl
     cmp     r0, #0x02       // (OK) TX_NAK + BULK
@@ -719,20 +719,20 @@ _evt_poll:
     movs    r2, 0x07
     ands    r2, r0
 /* checking USB->ISTR for events */
-    lsls    r0, #17             //CTRM -> CF
+#if !defined(USBD_SOF_DISABLED)
+    lsrs    r1, r0, #10         //SOFM -> CF
+    bcs     .L_ep_sofm
+#endif
+    lsrs    r1, r0, #11         //RESETM -> CF
+    bcs     .L_ep_resetm
+    lsrs    r1, r0, #16         //CTRM -> CF
     bcs     .L_ep_ctrm
-    lsls    r0, #2              //ERRM -> CF
+    lsrs    r1, r0, #14         //ERRM -> CF
     bcs     .L_ep_errm
-    lsls    r0, #1              //WKUPM -> CF
+    lsrs    r1, r0, #13         //WKUPM -> CF
     bcs     .L_ep_wkupm
-    lsls    r0, #1              //SUSPM -> CF
+    lsrs    r1, r0, #12         //SUSPM -> CF
     bcs     .L_ep_suspm
-    lsls    r0, #1              //RESETM -> CF
-    bcs     .L_ep_resetm
-    lsls    r0, #1              //SOFM -> CF
-    bcs     .L_ep_sofm
-    lsls    r0, #1
-    bcs     .L_ep_esofm
     /* exit with no callback */
     pop     {r0, r1, r4 , r5}
     bx      lr
@@ -767,17 +767,12 @@ _evt_poll:
     movs    r1, #usbd_evt_error
     movs    r4, #ISTRBIT(13)
     b      .L_ep_clristr
-
+#if !defined(USBD_SOF_DISABLED)
 .L_ep_sofm:
     movs    r1, #usbd_evt_sof
     movs    r4, #ISTRBIT(9)
     b       .L_ep_clristr
-
-.L_ep_esofm:
-    movs    r1, #usbd_evt_esof
-    movs    r4, #ISTRBIT(8)
-    b       .L_ep_clristr
-
+#endif
 .L_ep_wkupm:
     ldrh    r1, [r3, #0]            //R1 USB->CNTR
     movs    r5, #0x08

+ 10 - 9
src/usb_32v2.c

@@ -16,11 +16,10 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "stm32.h"
-#include "../usb.h"
+#include "usb.h"
 
 #if defined(USE_STMV2_DRIVER)
 
-#define VBUS_DETECTION  0
 #define MAX_EP          6
 #define MAX_RX_PACKET   128
 #define MAX_CONTROL_EP  1
@@ -108,7 +107,7 @@ void enable(bool enable) {
         OTG->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL |
                        _VAL2FLD(USB_OTG_GUSBCFG_TRDT, 0x06);
         /* configuring Vbus sense and powerup PHY */
-#if (VBUS_DETECTION)
+#if defined(USBD_VBUS_DETECT)
         OTG->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_PWRDWN;
 #else
         OTG->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL;
@@ -125,7 +124,9 @@ void enable(bool enable) {
         OTGD->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
         /* unmask core interrupts */
         OTG->GINTMSK  = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
+#if !defined(USBD_SOF_DISABLED)
                         USB_OTG_GINTMSK_SOFM |
+#endif
                         USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM |
                         USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_RXFLVLM;
         /* clear pending interrupts */
@@ -135,7 +136,7 @@ void enable(bool enable) {
         /* setting max RX FIFO size */
         OTG->GRXFSIZ = RX_FIFO_SZ;
         /* setting up EP0 TX FIFO SZ as 64 byte */
-        OTG->GNPTXFSIZ = RX_FIFO_SZ | (0x10 << 16);
+        OTG->DIEPTXF0_HNPTXFSIZ = RX_FIFO_SZ | (0x10 << 16);
     } else {
         if (RCC->AHB2ENR & RCC_AHB2ENR_OTGFSEN) {
             _BCL(PWR->CR2, PWR_CR2_USV);
@@ -154,7 +155,7 @@ void reset (void) {
 
 uint8_t connect(bool connect) {
     uint8_t res;
-#if (VBUS_DETECTION)
+#if defined(USBD_VBUS_DETECT)
     #define SET_GCCFG(x) OTG->GCCFG = USB_OTG_GCCFG_VBDEN | (x)
 #else
     #define SET_GCCFG(x) OTG->GCCFG = (x)
@@ -196,7 +197,7 @@ void setaddr (uint8_t addr) {
  * \return true if TX fifo is successfully set
  */
 static bool set_tx_fifo(uint8_t ep, uint16_t epsize) {
-    uint32_t _fsa = OTG->GNPTXFSIZ;
+    uint32_t _fsa = OTG->DIEPTXF0_HNPTXFSIZ;
     /* calculating initial TX FIFO address. next from EP0 TX fifo */
     _fsa = 0xFFFF & (_fsa + (_fsa >> 16));
     /* looking for next free TX fifo address */
@@ -323,7 +324,6 @@ void ep_deconfig(uint8_t ep) {
     /* disabling endpoint */
     if ((epi->DIEPCTL & USB_OTG_DIEPCTL_EPENA) && (ep != 0)) {
         epi->DIEPCTL = USB_OTG_DIEPCTL_EPDIS;
-        _WBS(epi->DIEPINT, USB_OTG_DIEPINT_EPDISD);
     }
     /* clean EP interrupts */
     epi->DIEPINT = 0xFF;
@@ -335,7 +335,6 @@ void ep_deconfig(uint8_t ep) {
     _BCL(epo->DOEPCTL, USB_OTG_DOEPCTL_USBAEP);
     if ((epo->DOEPCTL & USB_OTG_DOEPCTL_EPENA) && (ep != 0)) {
         epo->DOEPCTL = USB_OTG_DOEPCTL_EPDIS;
-        _WBS(epo->DOEPINT, USB_OTG_DOEPINT_EPDISD);
     }
     epo->DOEPINT = 0xFF;
 }
@@ -434,9 +433,11 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
                 OTG->GRXSTSP;
                 continue;
             }
+#if !defined(USBD_SOF_DISABLED)
         } else if (_t & USB_OTG_GINTSTS_SOF) {
             OTG->GINTSTS = USB_OTG_GINTSTS_SOF;
             evt = usbd_evt_sof;
+#endif
         } else if (_t & USB_OTG_GINTSTS_USBSUSP) {
             evt = usbd_evt_susp;
             OTG->GINTSTS = USB_OTG_GINTSTS_USBSUSP;
@@ -466,7 +467,7 @@ uint16_t get_serialno_desc(void *buffer) {
     uint32_t fnv = 2166136261;
     fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x00));
     fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x04));
-    fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x14));
+    fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x08));
     for (int i = 28; i >= 0; i -= 4 ) {
         uint16_t c = (fnv >> i) & 0x0F;
         c += (c < 10) ? '0' : ('A' - 10);

+ 48 - 15
src/usb_32v3.c

@@ -17,7 +17,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "stm32.h"
-#include "../usb.h"
+#include "usb.h"
 
 #if defined(USE_STMV3_DRIVER)
 
@@ -148,27 +148,61 @@ bool ep_isstalled(uint8_t ep) {
     }
 }
 
+void reset (void) {
+    USB->CNTR |= USB_CNTR_FRES;
+    USB->CNTR &= ~USB_CNTR_FRES;
+}
+
+uint8_t connect(bool connect) {
+#if defined(USBD_DP_PORT) && defined(USBD_DP_PIN) && defined(STM32F3)
+    uint32_t _t = USBD_DP_PORT->MODER & ~(0x03 << (2 * USBD_DP_PIN));
+    if (connect) {
+        _t |= (0x01 << (2 * USBD_DP_PIN));
+        USBD_DP_PORT->BSRR = (0x0001 << USBD_DP_PIN);
+    }
+    USBD_DP_PORT->MODER = _t;
+#elif defined(USBD_DP_PORT) && defined(USBD_DP_PIN) && defined(STM32F1)
+#if (USBD_DP_PIN < 8)
+    uint32_t _t = USBD_DP_PORT->CRL & ~(0x0F << (4 * USBD_DP_PIN));
+    if (connect) {
+        _t |= (0x02 << (4 * USBD_DP_PIN));
+        USBD_DP_PORT->BSRR = (0x0001 << USBD_DP_PIN);
+    } else {
+        _t |= (0x04 << (4 * USBD_DP_PIN));
+    }
+    USBD_DP_PORT->CRL = _t;
+#else
+    uint32_t _t = USBD_DP_PORT->CRH & ~(0x0F << (4 * (USBD_DP_PIN - 8)));
+    if (connect) {
+        _t |= (0x02 << (4 * (USBD_DP_PIN - 8)));
+        USBD_DP_PORT->BSRR = (0x0001 << USBD_DP_PIN);
+    } else {
+       _t |= (0x04 << (4 * (USBD_DP_PIN - 8)));
+    }
+    USBD_DP_PORT->CRH = _t;
+#endif
+#endif
+    return usbd_lane_unk;
+}
+
 void enable(bool enable) {
     if (enable) {
         RCC->APB1ENR  |= RCC_APB1ENR_USBEN;
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
         RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST;
-        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_ERRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM ;
+        USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_ERRM |
+#if !defined(USBD_SOF_DISABLED)
+        USB_CNTR_SOFM |
+#endif
+        USB_CNTR_SUSPM | USB_CNTR_WKUPM;
     } else if (RCC->APB1ENR & RCC_APB1ENR_USBEN) {
         RCC->APB1RSTR |= RCC_APB1RSTR_USBRST;
         RCC->APB1ENR &= ~RCC_APB1ENR_USBEN;
+        /* disconnecting DP if configured */
+        connect(0);
     }
 }
 
-void reset (void) {
-    USB->CNTR |= USB_CNTR_FRES;
-    USB->CNTR &= ~USB_CNTR_FRES;
-}
-
-uint8_t connect(bool connect) {
-    return usbd_lane_unk;
-}
-
 void setaddr (uint8_t addr) {
     USB->DADDR = USB_DADDR_EF | addr;
 }
@@ -391,9 +425,11 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
             ep_deconfig(i);
         }
         _ev = usbd_evt_reset;
+#if !defined(USBD_SOF_DISABLED)
     } else if (_istr & USB_ISTR_SOF) {
         _ev = usbd_evt_sof;
         USB->ISTR &= ~USB_ISTR_SOF;
+#endif
     } else if (_istr & USB_ISTR_WKUP) {
         _ev = usbd_evt_wkup;
         USB->CNTR &= ~USB_CNTR_FSUSP;
@@ -402,9 +438,6 @@ void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
         _ev = usbd_evt_susp;
         USB->CNTR |= USB_CNTR_FSUSP;
         USB->ISTR &= ~USB_ISTR_SUSP;
-    } else if (_istr & USB_ISTR_ESOF) {
-        USB->ISTR &= ~USB_ISTR_ESOF;
-        _ev = usbd_evt_esof;
     } else if (_istr & USB_ISTR_ERR) {
         USB->ISTR &= ~USB_ISTR_ERR;
         _ev = usbd_evt_error;
@@ -429,7 +462,7 @@ uint16_t get_serialno_desc(void *buffer) {
     uint32_t fnv = 2166136261;
     fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x00));
     fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x04));
-    fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x14));
+    fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x08));
     for (int i = 28; i >= 0; i -= 4 ) {
         uint16_t c = (fnv >> i) & 0x0F;
         c += (c < 10) ? '0' : ('A' - 10);

+ 842 - 0
src/usb_32v3A.S

@@ -0,0 +1,842 @@
+/* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
+ *
+ * Copyright ©2016 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined (__ASSEMBLER__)
+    #define __ASSEMBLER__
+#endif
+
+#include "usb.h"
+#if defined(USE_STMV3_DRIVER)
+#include "memmap.inc"
+
+#define EP_SETUP    0x0800
+#define EP_TYPE     0x0600
+#define EP_KIND     0x0100
+#define EP_ADDR     0x000F
+
+#define EP_RX_CTR   0x8000
+#define EP_RX_DTOG  0x4000
+#define EP_RX_STAT  0x3000
+#define EP_RX_SWBUF 0x0040
+
+#define EP_RX_DIS   0x0000
+#define EP_RX_STAL  0x1000
+#define EP_RX_NAK   0x2000
+#define EP_RX_VAL   0x3000
+
+#define EP_TX_CTR   0x0080
+#define EP_TX_DTOG  0x0040
+#define EP_TX_STAT  0x0030
+#define EP_TX_SWBUF 0x4000
+
+#define EP_TX_DIS   0x0000
+#define EP_TX_STAL  0x0010
+#define EP_TX_NAK   0x0020
+#define EP_TX_VAL   0x0030
+
+#define RXADDR0     0x00
+#define RXCOUNT0    0x04
+#define RXADDR1     0x08
+#define RXCOUNT1    0x0C
+
+#define TXADDR0     0x00
+#define TXCOUNT0    0x04
+#define TXADDR1     0x08
+#define TXCOUNT1    0x0C
+
+#define TXADDR      0x00
+#define TXCOUNT     0x04
+#define RXADDR      0x08
+#define RXCOUNT     0x0C
+
+
+
+#define EP_NOTOG    (EP_RX_CTR | EP_TX_CTR | EP_SETUP | EP_TYPE | EP_KIND | EP_ADDR)
+
+#define TGL_SET(mask, bits)  ((EP_NOTOG | (mask))<<16 | (bits))
+
+#define TX_STALL    TGL_SET(EP_TX_STAT,                            EP_TX_STAL)
+#define RX_STALL    TGL_SET(EP_RX_STAT,                            EP_RX_STAL)
+#define TX_USTALL   TGL_SET(EP_TX_STAT | EP_TX_DTOG,               EP_TX_NAK)
+#define RX_USTALL   TGL_SET(EP_RX_STAT | EP_RX_DTOG,               EP_RX_VAL)
+#define DTX_USTALL  TGL_SET(EP_TX_STAT | EP_TX_DTOG | EP_TX_SWBUF, EP_TX_VAL)
+#define DRX_USTALL  TGL_SET(EP_RX_STAT | EP_RX_DTOG | EP_RX_SWBUF, EP_RX_VAL | EP_RX_SWBUF)
+
+
+    .syntax unified
+    .cpu cortex-m3
+    .text
+    .thumb
+
+
+    .globl  usb_stmv3a
+    .align  2
+usb_stmv3a:
+    .long   0
+    .long   _enable
+    .long   _reset
+    .long   _connect
+    .long   _setaddr
+    .long   _ep_config
+    .long   _ep_deconfig
+    .long   _ep_read
+    .long   _ep_write
+    .long   _ep_setstall
+    .long   _ep_isstalled
+    .long   _evt_poll
+    .long   _get_frame
+    .long   _get_serial_desc
+    .size   usb_stmv3a, . - usb_stmv3a
+
+
+    .thumb_func
+    .type _get_serial_desc, %function
+
+/*  uint16_t get_serial_desc (void *buffer)
+ *  R0 <- buffer for the string descriptor
+ *  descrpitor size -> R0
+ */
+_get_serial_desc:
+    push    {r4, r5, lr}
+    movs    r1, #18             //descriptor size 18 bytes
+    strb    r1, [r0]
+    movs    r1, #0x03           //DTYPE_STRING
+    strb    r1, [r0, #0x01]
+    ldr     r5, .L_uid_base     //UID3 this is the serial number
+    ldr     r4, .L_fnv1a_offset //FNV1A offset
+    ldr     r2, [r5, 0x00]      //UID0
+    bl      .L_fnv1a
+    ldr     r2, [r5, 0x04]      //UID1
+    bl      .L_fnv1a
+    ldr     r2, [r5, 0x08]      //UID2
+    bl      .L_fnv1a
+    movs    r3, #28
+.L_gsn_loop:
+    lsrs    r1, r4, r3
+    and     r1, #0x0F
+    cmp     r1, #0x09
+    ite     gt
+    addgt   r1, #55
+    addle   r1, #48
+.L_gsn_store:
+    adds    r0, #0x02
+    strb    r1, [r0]
+    lsrs    r1, #0x08
+    strb    r1, [r0, #0x01]
+    subs    r3, #0x04
+    bpl     .L_gsn_loop
+    movs    r0, #18
+    pop     {r4, r5, pc}
+
+.L_fnv1a:
+    movs    r3, #0x04
+.L_fnv1a_loop:
+    uxtb    r1, r2
+    eors    r4, r1
+    ldr     r1, .L_fnv1a_prime       //FNV1A prime
+    muls    r4, r1
+    lsrs    r2, #0x08
+    subs    r3, #0x01
+    bne     .L_fnv1a_loop
+    bx      lr
+
+    .align 2
+.L_uid_base:        .long   UID_BASE
+.L_fnv1a_offset:    .long   2166136261
+.L_fnv1a_prime:     .long   16777619
+
+    .size _get_serial_desc, . - _get_serial_desc
+
+    .thumb_func
+    .type   _connect, %function
+_connect:
+#if defined(USBD_DP_PORT) && defined(USBD_DP_PIN) && defined(STM32F1)
+    #if (USBD_DP_PIN < 8)
+    #define GPIO_CRx    GPIO_CRL
+    #define DP_PIN      (4 * USBD_DP_PIN)
+    #else
+    #define GPIO_CRx    GPIO_CRH
+    #define DP_PIN      (4 * (USBD_DP_PIN - 8))
+    #endif
+    ldr     r3, =#USBD_DP_PORT
+    ldr     r2, [r3, #GPIO_CRx]
+    movs    r1, #0x0F
+    bics    r2, r2, r1, LSL #DP_PIN
+    movs    r1, #0x04
+    cbz     r0, .L_store
+    movs    r1, #0x01
+    lsls    r1, #USBD_DP_PIN
+    str     r1, [r3, #GPIO_BSRR]
+    movs    r1, #0x02
+.L_store:    
+    orrs    r2, r2, r1, LSL #DP_PIN
+    str     r2, [r3, #GPIO_CRx]
+#elif defined(USBD_DP_PORT) && defined(USBD_DP_PIN) && defined(STM32F3)
+    ldr     r3, =#USBD_DP_PORT
+    ldr     r2, [r3, #GPIO_MODER]
+    movs    r1, #0x03
+    bics    r2, r2, r1, LSL #(2 * USBD_DP_PIN)
+    movs    r1, #0x01
+    cbz     r0, .L_store
+    orrs    r2, r2, r1, LSL #(2 * USBD_DP_PIN)
+    lsls    r1, #USBD_DP_PIN
+    str     r1, [r3, #GPIO_BSRR]
+.L_store:
+    str     r2, [r3, #GPIO_MODER]
+#endif
+    movs    r0, #usbd_lane_unk
+    bx      lr
+    .size   _connect, . - _connect
+
+
+    .thumb_func
+    .type   _setaddr, %function
+_setaddr:
+    ldr     r1, =#USB_REGBASE
+    adds    r0, #0x80
+    strh    r0, [r1, #USB_DADDR]     //USB->DADDR
+    bx      lr
+    .size   _setaddr, . - _setaddr
+
+    .thumb_func
+    .type   _reset, %function
+_reset:
+    ldr     r2, =#USB_REGBASE
+    movs    r0, #0x01           //FRES
+    ldrh    r1, [r2, #USB_CNTR]
+    orrs    r1, r0
+    strh    r1, [r2, #USB_CNTR]  // set FRES
+    bics    r1, r0
+    strh    r1, [r2, #USB_CNTR]  // clr FRES
+    bx      lr
+    .size   _reset, . - _reset
+
+    .thumb_func
+    .type   _get_frame, %function
+_get_frame:
+    ldr     r0, =#USB_REGBASE
+    ldrh    r0, [r0, #USB_FNR]     //FNR
+    lsls    r0, #21
+    lsrs    r0, #21
+    bx      lr
+    .size   _get_frame, . - _get_frame
+
+    .thumb_func
+    .type   _enable, %function
+_enable:
+    ldr     r2, =#RCC_BASE        //RCC
+    movs    r3, #0x01
+    lsls    r3, #23             //USBEN or USBRST
+    cbz     r0, .L_disable
+.L_enable:
+/* enabling and resetting USB peripheral */
+    ldr     r1, =#USB_REGBASE
+    ldr     r0, [r2, #RCC_APB1ENR]
+    orrs    r0, r3
+    str     r0, [r2, #RCC_APB1ENR]     //RCC->APB1ENR |= USBEN
+    ldr     r0, [r2, #RCC_APB1RSTR]
+    orrs    r0, r3
+    str     r0, [r2, #RCC_APB1RSTR]     //RCC->APB1RSTR |= USBRST
+    bics    r0, r3
+    str     r0, [r2, #RCC_APB1RSTR]     //RCC->APB1RSTR &= ~USBRST
+/* setting up USB CNTR */
+#if !defined(USBD_SOF_DISABLED)
+    movs    r0, #0xBE                   // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
+#else
+    movs    r0, #0xBC                   // CTRM | ERRM | WKUPM | SUSPM | RESETM
+#endif
+    lsls    r0, #0x08
+    strh    r0, [r1, #USB_CNTR]         //set USB->CNTR
+    bx      lr
+.L_disable:
+    ldr     r0, [r2, #RCC_APB1ENR]
+    tst     r0, r3
+    beq     .L_enable_end               // usb is already disabled
+/* disabling USB peripheral */
+    bics    r0, r3
+    str     r0, [r2, #RCC_APB1ENR]
+    movs    r0, #0
+    b       _connect                    // jump to disconnect subroutine
+.L_enable_end:
+    bx      lr
+    .size   _enable, . - _enable
+
+    .thumb_func
+    .type   _ep_setstall, %function
+
+/*void ep_settall(uint8_t ep, bool stall)
+ * in  R0 <- endpoint number
+ * in  R1 <- 0 if unstall, !0 if stall
+ */
+_ep_setstall:
+    push    {r4, lr}
+    lsls    r2, r0, #28
+    lsrs    r2, #26
+    ldr     r3, =#USB_EPBASE
+    adds    r3, r2          // epr -> r3
+    movs    r2, 0x30        // TX_STAT_MASK -> r2
+    ldrh    r4, [r3]
+    lsls    r4, #21
+    lsrs    r4, #29         // EP_TYPE | EP_KIND -> R4 LSB
+    cmp     r4, #0x04       // ISO ?
+    beq     .L_eps_exit
+    cmp     r0, #0x80
+    blo     .L_eps_rx
+.L_eps_tx:
+    ldr     r0, =#TX_STALL   //stall TX
+    cmp     r1, #0x00
+    bne     .L_eps_reg_set
+.L_eps_tx_unstall:
+    ldr     r0, =#DTX_USTALL //unstall dblbulk or iso TX (VALID and clr DTOG_TX & SWBUF_TX)
+    cmp     r4, #0x01       // if doublebuffered bulk endpoint
+    beq     .L_eps_reg_set
+    ldr     r0, =#TX_USTALL  // unstall other TX (NAKED + clr DTOG_TX)
+    b       .L_eps_reg_set
+.L_eps_rx:
+    lsls    r2, #8          // RX_STAT_MASK -> R2
+    ldr     r0,=#RX_STALL    //stall RX
+    cmp     r1, #0x00
+    bne     .L_eps_reg_set
+.L_eps_rx_unstall:
+    ldr     r0, =#DRX_USTALL //unstall dblbulk or iso (VALID. clr DTOG_RX set SWBUF_RX)
+    cmp     r4, #0x01       // if dblbulk
+    beq     .L_eps_reg_set
+    ldr     r0, =#RX_USTALL  // unstall other RX (VALID + clr
+/* R0 - mask and toggle bits
+ * R2 - mask for STAT bits
+ * R3 - endpoint register pointer
+ */
+.L_eps_reg_set:
+    ldrh    r1, [r3]        // *epr -> r1
+    ands    r2, r1          // check if endpoint disabled
+    beq     .L_eps_exit     // do nothing
+    eors    r1, r0
+    lsrs    r0, #16
+    ands    r1, r0
+    strh    r1, [r3]
+.L_eps_exit:
+    pop     {r4, pc}
+    .size   _ep_setstall, . - _ep_setstall
+
+
+    .thumb_func
+    .type   _ep_isstalled, %function
+/* bool ep_isstalled(uint8t ep) */
+_ep_isstalled:
+    ldr     r1, =#USB_EPBASE
+    lsls    r2, r0, #28
+    lsrs    r2, #26
+    ldr     r1, [r1, r2]
+    lsls    r1, #17
+    cmp     r0, #0x80
+    bhs     .L_eis_check
+    lsls    r1, #8
+.L_eis_check:
+    lsrs    r1, r1, #28
+    subs    r1, #0x01
+    subs    r0, r1, #0x01
+    sbcs    r1, r1
+    rsbs    r0, r1, #0
+    bx      lr
+    .size  _ep_isstalled, . - _ep_isstalled
+
+
+    .thumb_func
+    .type       _ep_read, %function
+/* int32_t _ep_read(uint8_t ep, void *buf, uint16_t blen)
+ * in  R0 <- endpoint
+ * in  R1 <- *buffer
+ * in  R2 <- length of the buffer
+ * out length of the recieved data -> R0 or 0 on error
+ */
+_ep_read:
+    push    {r4, r5, lr}
+    ldr     r3, =#USB_EPBASE
+    ldr     r4, =#USB_PMABASE
+    lsls    r0, #28
+    add     r3, r3, r0, LSR #26     //*EPR -> R3
+    add     r4, r4, r0, LSR #24     //*EPT -> R4
+    ldrh    r5, [r3]                // reading epr
+/* validating endpoint */
+    movs    r0, #0x37
+    ands    r0, r0, r5, LSR #8
+    cmp     r0, #0x34       // (OK) RX_VALID + ISO
+    beq     .L_epr_iso
+    cmp     r0, #0x31       // (OK) RX_VALID + DBLBULK
+    beq     .L_epr_dbl
+    cmp     r0, #0x20       // (OK) RX_NAKED + BULK
+    beq     .L_epr_sngl
+    cmp     r0, #0x22       // (OK) RX_NAKED + CTRL
+    beq     .L_epr_sngl
+    cmp     r0, #0x26       // (OK) RX_NAKED + INTR
+    beq     .L_epr_sngl
+    movs    r0, #0xFF       // endpoint contains no valid data
+    sxtb    r0, r0
+    b       .L_epr_exit
+/* processing */
+.L_epr_dbl:
+//    lsrs    r0, r5, #8
+//    eors    r0, r5
+    eors    r0, r5, r5, LSR #8
+    lsrs    r0, #7          // SW_RX ^ DTOG_RX -> CF
+    bcs     .L_epr_notog    // jmp if SW_RX != DTOG_RX (VALID)
+    ldr     r0, =#EP_NOTOG
+    ands    r5, r0
+    adds    r5, #EP_RX_SWBUF
+    strh    r5, [r3]        // toggling SW_RX
+.L_epr_notog:
+    ldrh    r5, [r3]
+    lsls    r5, #8          // shift SW_RX to DTOG_RX
+.L_epr_iso:
+    lsrs    r5, #15         // DTOG_RX -> CF
+    bcs     .L_epr_sngl
+    subs    r4, #0x08       // set RXADDR0
+.L_epr_sngl:
+    ldrh    r0, [r4, #RXCOUNT]
+    lsrs    r5, r0, #0x0A
+    lsls    r5, #0x0A       // r5 = r5 & ~0x03FF
+    strh    r5, [r4, #RXCOUNT]
+    lsls    r0, #22
+    lsrs    r0, #22         // r0 &= 0x3FF (RX count)
+    ldrh    r5, [r4, #RXADDR]
+    ldr     r4, =#USB_PMABASE
+    lsls    r5, #0x01
+    adds    r5, r4          // R5 now has a physical address
+    cmp     r2, r0
+    blo     .L_epr_read
+    mov     r2, r0          // if buffer is larger
+.L_epr_read:
+    cmp     r2, #1
+    blo     .L_epr_read_end
+    ldrh    r4, [r5]
+    strb    r4, [r1]
+    beq     .L_epr_read_end
+    lsrs    r4, #8
+    strb    r4, [r1, #1]
+    adds    r1, #2
+    adds    r5, #4
+    subs    r2, #2
+    bhi     .L_epr_read
+.L_epr_read_end:
+    ldrh    r5, [r3]        // reload EPR
+    lsls    r1, r5, #21
+    lsrs    r1, #29
+    cmp     r1, #0x04
+    beq     .L_epr_exit     // ep is iso. no needs to set it to valid
+    cmp     r1, #0x01
+    beq     .L_epr_exit     // ep is dblbulk. no needs to set it to valid
+    ldr     r2, =#TGL_SET(EP_RX_STAT , EP_RX_VAL)
+    eors    r5, r2
+    and     r5, r5, r2, LSR #16
+    strh    r5, [r3]        // set ep to VALID state
+.L_epr_exit:
+    pop     {r4, r5, pc}
+    .size   _ep_read, . - _ep_read
+
+
+    .thumb_func
+    .type   _ep_write, %function
+/* int32_t ep_write(uint8_t ep, void *buf, uint16_t blen)
+ * R0 -> endpoint
+ * R1 -> *buffer
+ * R2 -> data length
+ * result -> R0
+ */
+_ep_write:
+    push    {r4, r5, r6, lr}
+    ldr     r3, =#USB_EPBASE
+    ldr     r4, =#USB_PMABASE
+    lsls    r0, #28
+    add     r3, r3, r0, LSR #26     //*EPR -> R3
+    add     r4, r4, r0, LSR #24     //*EPT -> R4    
+    ldrh    r5, [r3]        // reading epr
+    movs    r0, #0x73
+    and     r0, r0, r5, LSR #4
+    cmp     r0, #0x43       // (OK) TX_VALID + ISO
+    beq     .L_epw_iso
+    cmp     r0, #0x12       // (OK) TX_NAK + DBLBULK
+    beq     .L_epw_dbl
+    cmp     r0, #0x02       // (OK) TX_NAK + BULK
+    beq     .L_epw_sngl
+    cmp     r0, #0x22       // (OK) TX_NAK + CONTROL
+    beq     .L_epw_sngl
+    cmp     r0, #0x62       // (OK) TX_NAK + INTERRUPT
+    beq     .L_epw_sngl
+    movs    r0, #0xFF       // -1 error
+    sxtb    r0, r0
+    b       .L_epw_exit
+.L_epw_dbl:
+    mvns    r5, r5
+    lsrs    r5, #8          // ~SWBUF_TX -> DTOG_TX
+.L_epw_iso:
+    lsrs    r5, #7          // DTOG_TX -> CF
+    bcs     .L_epw_sngl
+    adds    r4, #8          // TXADDR1 -> R4
+.L_epw_sngl:
+    strh    r2, [r4, #TXCOUNT]
+    mov     r0, r2          // save count for return
+    ldrh    r5, [r4, #TXADDR]
+    ldr     r4, =#USB_PMABASE
+    lsls    r5, #1
+    adds    r5, r4          // PMA BUFFER -> R5
+.L_epw_write:
+    cmp     r2, #1
+    blo     .L_epw_write_end
+    ldrb    r4, [r1]
+    beq     .L_epw_store
+    ldrb    r6, [r1, #1]
+    lsls    r6, #8
+    orrs    r4, r6
+.L_epw_store:
+    strh    r4, [r5]
+    adds    r5, #4
+    adds    r1, #2
+    subs    r2, #2
+    bhi     .L_epw_write
+.L_epw_write_end:
+    ldrh    r5, [r3]        // reload EPR
+    lsls    r1, r5, #21
+    lsrs    r1, #29
+    cmp     r1, #0x04
+    beq     .L_epw_exit     // isochronous ep. do nothing
+    ldr     r2, =#TGL_SET(EP_TX_STAT, EP_TX_VAL)
+    cmp     r1, #0x01
+    bne     .L_epw_setstate // NOT a doublebuffered bulk
+    ldr     r2, =#TGL_SET(EP_TX_SWBUF, EP_TX_SWBUF)
+    bics    r5, r2          // clear TX_SWBUF
+.L_epw_setstate:
+    eors    r5, r2
+//    lsrs    r2, #16
+//    ands    r5, r2
+    and     r5, r5, r2, LSR #16
+    strh    r5, [r3]
+.L_epw_exit:
+    pop     {r4, r5, r6, pc}
+    .size   _ep_write, .- _ep_write
+
+
+
+/* internal function */
+/* requester size passed in R2 */
+/* result returns in R0 CF=1 if OK*/
+
+_get_next_pma:
+    push    {r1, r3, r4, lr}
+    movs    r1, #16
+    movs    r3, #1
+    lsls    r3, #9          //R3 MAX_PMA_SIZE 512b
+    ldr     r0, =#USB_PMABASE
+.L_gnp_chkaddr:
+    ldrh    r4, [r0, #0]    //txaddr
+    tst     r4, r4
+    beq     .L_gnp_nxtaddr
+    cmp     r3, r4
+    blo     .L_gnp_nxtaddr
+    mov     r3, r4
+.L_gnp_nxtaddr:
+    adds    r0, #8
+    subs    r1, #1
+    bne     .L_gnp_chkaddr
+    subs    r0, r3, r2
+    blo     .L_gnp_exit
+    cmp     r0, #0x40       //check for the pma table overlap
+.L_gnp_exit:
+    pop     {r1, r3, r4, pc}
+
+
+
+    .size   _get_next_pma, . - _get_next_pma
+
+    .thumb_func
+    .type   _ep_config, %function
+/* bool ep_config(uint8_t ep, uint8_t eptype, uint16_t epsize)
+ * R0 <- ep
+ * R1 <- eptype
+ * R2 <- epsize
+ * result -> R0
+ */
+_ep_config:
+    push    {r4, r5, lr}
+    movs    r3, 0x01
+    ands    r3, r2
+    adds    r2, r3      //R2 -> halfword aligned epsize
+    movs    r3, #0x00   //BULK
+    cmp     r1, #0x02   // is eptype bulk ?
+    beq     .L_epc_settype
+    movs    r3, #0x01   //DBLBULK
+    cmp     r1, #0x06
+    beq     .L_epc_settype
+    movs    r3, #0x02   //CONTROL
+    cmp     r1, #0x00
+    beq     .L_epc_settype
+    movs    r3, #0x04   //ISO
+    cmp     r1, #0x01
+    beq     .L_epc_settype
+    movs    r3, #0x06   //INTERRUPT
+.L_epc_settype:
+    lsls    r3, #8
+    lsls    r4, r0, #28
+    lsrs    r4, #28
+    orrs    r3, r4
+    lsls    r4, #2
+    ldr     r5, =#USB_EPBASE
+    strh    r3, [r5, r4]    //setup EPTYPE EPKIND EPADDR
+    cmp     r1, #0x00       // is a control ep ?
+    beq     .L_epc_setuptx
+    cmp     r0, #0x80
+    blo     .L_epc_setuprx
+.L_epc_setuptx:
+    ldr     r5, =#USB_PMABASE
+    lsls    r4, #2
+    adds    r5, r4
+    bl      _get_next_pma
+    bcc     .L_epc_fail
+    strh    r0, [r5, #TXADDR]    //store txaddr or txaddr0
+    movs    r0, #0x00
+    strh    r0, [r5, #TXCOUNT]    //store txcnt
+    cmp     r1, #0x06       // is DBLBULK
+    beq     .L_epc_txdbl
+    ldr     r3, =#TX_USTALL  //set state NAKED , clr DTOG_TX
+    cmp     r1, #0x01       // is ISO
+    bne     .L_epc_txsetstate   //
+.L_epc_txdbl:
+    ldr     r3, =#DTX_USTALL //set state VALID clr DTOG_TX & SWBUF_TX
+    bl      _get_next_pma
+    bcc     .L_epc_fail
+    strh    r0, [r5, #TXADDR1]    //store txaddr1
+    movs    r0, #0x00
+    strh    r0, [r5, #TXCOUNT1]    //store txcnt
+.L_epc_txsetstate:
+    ldr     r5, =#USB_EPBASE
+    lsrs    r4, #2
+    ldrh    r0, [r5, r4]
+    eors    r0, r3
+    lsrs    r3, #16
+    ands    r0, r3
+    strh    r0, [r5, r4]
+    cmp     r1, #0x00       //is a control ep ?
+    bne     .L_epc_exit
+.L_epc_setuprx:
+    mov     r3, r2
+    cmp     r2, #62
+    bls     .L_epc_rxbb
+    movs    r3, #0x1F
+    ands    r3, r2
+    bne     .L_epc_rxaa
+    subs    r2, #0x20
+.L_epc_rxaa:
+    bics    r2, r3
+    lsrs    r3, r2, #4
+    adds    r3, #0x40
+    adds    r2, #0x20
+.L_epc_rxbb:
+    lsls    r3, #9
+    ldr     r5, =#USB_PMABASE
+    lsls    r4, #2
+    adds    r5, r4
+/* RX or RX1 */
+    bl      _get_next_pma
+    bcc     .L_epc_fail
+    strh    r0, [r5, #RXADDR]
+    strh    r3, [r5, #RXCOUNT]
+    ldr     r0, =#RX_USTALL
+/* check if doublebuffered */
+    cmp     r1, 0x06    //if dblbulk
+    beq     .L_epc_rxdbl
+    cmp     r1, 0x01    // iso
+    bne     .L_epc_rxsetstate
+.L_epc_rxdbl:
+    bl      _get_next_pma
+    bcc     .L_epc_fail
+    strh    r0, [r5, #RXADDR0]    //store rxaddr0
+    strh    r3, [r5, #RXCOUNT0]    //store rxcnt0
+    ldr     r0, =#DRX_USTALL
+.L_epc_rxsetstate:
+    ldr     r5, =#USB_EPBASE
+    lsrs    r4, #2
+    ldrh    r3, [r5, r4]
+    eors    r3, r0
+    lsrs    r0, #16
+    ands    r3, r0
+    strh    r3, [r5, r4]
+.L_epc_exit:
+    movs    r0, #0x01
+    pop     {r4, r5, pc}
+.L_epc_fail:
+    movs    r0, #0x00
+    pop     {r4, r5, pc}
+
+    .size   _ep_config, . - _ep_config
+
+    .thumb_func
+    .type   _ep_deconfig, %function
+
+
+/* void ep_deconfig( uint8_t ep)
+ * R0 <- ep
+ */
+_ep_deconfig:
+    lsls    r1, r0, #28
+    lsrs    r1, #26
+    ldr     r2, =#USB_EPBASE
+    ldr     r3, =#USB_PMABASE
+    adds    r2, r1
+    lsls    r1, #1
+    adds    r3, r1
+/* clearing endpoint register */
+    ldr     r1, =#EP_NOTOG
+    ldrh    r0, [r2]
+    bics    r0, r1
+    strh    r0, [r2]
+/* clearing PMA data */
+    movs    r0, #0x00
+    strh    r0, [r3, #TXADDR]
+    strh    r0, [r3, #TXCOUNT]
+    strh    r0, [r3, #RXADDR]
+    strh    r0, [r3, #RXCOUNT]
+    bx      lr
+
+    .size   _ep_deconfig, . - _ep_config
+
+
+
+
+#define ISTRSHIFT   8
+#define ISTRBIT(bit) ((1 << bit) >> ISTRSHIFT)
+
+
+    .thumb_func
+    .type     _evt_poll, %function
+/*void evt_poll(usbd_device *dev, usbd_evt_callback callback)*/
+_evt_poll:
+    push    {r0, r1, r4, r5}
+    ldr     r3, =#USB_REGBASE
+    ldrh    r0, [r3, #4]        //USB->ISTR -> R2
+/* ep_index -> R2 */
+    movs    r2, 0x07
+    ands    r2, r0
+/* checking USB->ISTR for events */
+#if !defined(USBD_SOF_DISABLED)
+    lsrs    r1, r0, #10         //SOFM -> CF
+    bcs     .L_ep_sofm
+#endif
+    lsrs    r1, r0, #11         //RESETM -> CF
+    bcs     .L_ep_resetm
+    lsrs    r1, r0, #16         //CTRM -> CF
+    bcs     .L_ep_ctrm
+    lsrs    r1, r0, #14         //ERRM -> CF
+    bcs     .L_ep_errm
+    lsrs    r1, r0, #13         //WKUPM -> CF
+    bcs     .L_ep_wkupm
+    lsrs    r1, r0, #12         //SUSPM -> CF
+    bcs     .L_ep_suspm
+    /* exit with no callback */
+    pop     {r0, r1, r4 , r5}
+    bx      lr
+
+.L_ep_ctrm:
+    movs    r5, #0x80           // CTR_TX mask to R5
+    ldr     r0,=#USB_EPBASE
+//    lsrs    r0, #2
+//    adds    r0, r2
+//    lsls    r0, #2              // R0 ep register address
+    add     r0, r0, r2, LSL #2  // R0 ep register address
+    ldrh    r4, [r0]            // R4 EPR valur
+    lsrs    r3, r4, #8          // CTR_TX -> CF
+    bcc     .L_ep_ctr_rx
+/* CTR_TX event */
+    movs    r1, #usbd_evt_eptx
+    orrs    r2, r5              // set endpoint tx
+    b       .L_ep_clr_ctr
+.L_ep_ctr_rx:
+/* CTR_RX  RX or SETUP */
+    lsls    r5, #0x08           // set mask to CRT_RX
+    movs    r1, #usbd_evt_eprx
+    lsls    r3, r4, #21         //SETUP -> CF
+    bcc     .L_ep_clr_ctr
+    movs    r1, #usbd_evt_epsetup
+.L_ep_clr_ctr:
+    bics    r4, r5              //clear CTR flag
+    ldr     r5, =#EP_NOTOG
+    ands    r4, r5
+    strh    r4, [r0]            // store
+    b       .L_ep_callback
+.L_ep_errm:
+    movs    r1, #usbd_evt_error
+    movs    r4, #ISTRBIT(13)
+    b      .L_ep_clristr
+#if !defined(USBD_SOF_DISABLED)
+.L_ep_sofm:
+    movs    r1, #usbd_evt_sof
+    movs    r4, #ISTRBIT(9)
+    b       .L_ep_clristr
+#endif
+.L_ep_wkupm:
+    ldrh    r1, [r3, #0]            //R1 USB->CNTR
+    movs    r5, #0x08
+    bics    r1, r5                  //clr FSUSP
+    strh    r1, [r3, #0]            //USB->CNTR R2
+    movs    r1, #usbd_evt_wkup
+    movs    r4, #ISTRBIT(12)
+    b       .L_ep_clristr
+
+.L_ep_suspm:
+    ldrh    r1, [r3, #0]            //R1 USB->CNTR
+    movs    r5, #0x08
+    orrs    r1, r5                  //set FSUSP
+    strh    r1, [r3, #0]            //USB->CNTR R2
+    movs    r1, #usbd_evt_susp
+    movs    r4, #ISTRBIT(11)
+    b       .L_ep_clristr
+
+/* do reset routine */
+.L_ep_resetm:
+    movs    r1, #7
+    ldr     r2, =#USB_EPBASE
+    ldr     r0, =#USB_PMABASE
+    ldr     r5, =#EP_NOTOG
+.L_ep_reset_loop:
+    ldrh    r4, [r2]
+    bics    r4, r5
+    strh    r4, [r2]
+    movs    r4, #0
+    strh    r4, [r0, #TXADDR]
+    strh    r4, [r0, #TXCOUNT]
+    strh    r4, [r0, #RXADDR]
+    strh    r4, [r0, #RXCOUNT]
+    adds    r2, #0x04
+    adds    r0, #0x10
+    subs    r1, #1
+    bpl     .L_ep_reset_loop
+    movs    r2, #0x00
+    strh    r2, [r3, #0x10]     // 0 -> USB->BTABLE
+    movs    r1, #usbd_evt_reset
+    movs    r4, #ISTRBIT(10)
+.L_ep_clristr:
+    lsls    r4, #ISTRSHIFT
+    ldrh    r0, [r3, #4]
+    bics    r0, r4
+    strh    r0, [r3, #4]
+.L_ep_callback:
+    pop     {r0, r3, r4, r5 }
+    bx      r3
+
+    .size   _evt_poll, . - _evt_poll
+
+    .pool
+
+   .end
+
+#endif

+ 1 - 1
src/usbd_core.c

@@ -16,7 +16,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
-#include "../usb.h"
+#include "usb.h"
 
 #define _MIN(a, b) ((a) < (b)) ? (a) : (b)