diff options
Diffstat (limited to 'libmaple/usb')
-rw-r--r-- | libmaple/usb/README | 63 | ||||
-rw-r--r-- | libmaple/usb/rules.mk | 45 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb.c | 387 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_cdcacm.c | 709 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_lib_globals.h | 55 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_reg_map.c | 88 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_reg_map.h | 617 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_core.c | 1013 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_core.h | 251 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_def.h | 88 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_init.c | 64 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_init.h | 57 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_lib.h | 36 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_mem.c | 73 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_mem.h | 40 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_regs.c | 748 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_regs.h | 627 | ||||
-rw-r--r-- | libmaple/usb/usb_lib/usb_type.h | 77 |
18 files changed, 5038 insertions, 0 deletions
diff --git a/libmaple/usb/README b/libmaple/usb/README new file mode 100644 index 0000000..d0fca8d --- /dev/null +++ b/libmaple/usb/README @@ -0,0 +1,63 @@ +The USB submodule of libmaple is a separate piece of the codebase for +reasons that are largely historical. + +Current Status: + + There's only support for the USB device peripheral found on + STM32F103s. + + We rely on the low level core library provided by ST to implement + the USB transfer protocol for control endpoint transfers. + + The virtual com port (which is exposed via + <libmaple/usb_cdcacm.h>) serves two important purposes. + + 1) It allows serial data transfers between user sketches an a + host computer. + + 2) It allows the host PC to issue a system reset into the DFU + bootloader with the DTR + RTS + "1EAF" sequence (see + leaflabs.com/docs/bootloader.html for more information on + this). + + After reset, Maple will run the DFU bootloader for a few seconds, + during which the user can begin a DFU upload operation (uploads + application binary into RAM/FLASH). Thus, without this virtual com + port, it would be necessary to find an alternative means to reset + the chip in order to enable the bootloader. + + If you would like to develop your own USB application for whatever + reason (e.g. to use faster isochronous enpoints for streaming + audio, or implement the USB HID or Mass Storage specs), then + ensure that you leave some hook for resetting Maple remotely in + order to spin up the DFU bootloader. Please make sure to get + yourself a unique vendor/product ID pair for your application, as + some operating systems will assign a host-side driver based on + these tags. + + It would be possible to build a compound USB device, that + implements endpoints for both the virtual COM port as well as some + other components (mass storage etc.). However, this turns out to + be a burden from the host driver side, as Windows and *nix handle + compound USB devices quite differently. + + Be mindful that enabling the USB peripheral isn't "free." The + device must respond to periodic bus activity (every few + milliseconds) by servicing an ISR. Therefore, the USB application + should be disabled inside of timing critical applications. + + In order to disconnect the device from the host, a USB_DISC pin is + asserted (e.g. on Maple, this is PC12). Alternatively, the NVIC + can be directly configured to disable the USB LP/HP IRQ's. + + The files inside of usb_lib were provided by ST and are subject to + their own license, all other files were written by the LeafLabs + team and fall under the MIT license. + +TODO: + + - Generic USB driver core with series-provided backends, like + libopencm3 has. + - Strip out ST code. + - Integration with a high level USB library (like LUFA/MyUSB) to + allow users to write custom USB applications. diff --git a/libmaple/usb/rules.mk b/libmaple/usb/rules.mk new file mode 100644 index 0000000..e8ccc15 --- /dev/null +++ b/libmaple/usb/rules.mk @@ -0,0 +1,45 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +CFLAGS_$(d) = -I$(d) -I$(d)/$(MCU_SERIES) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall + +# Add usblib and series subdirectory to BUILDDIRS. +BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES) +BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib + +# Local rules and targets +sSRCS_$(d) := +cSRCS_$(d) := +# We currently only have F1 performance line support. Sigh. +ifeq ($(MCU_SERIES), stm32f1) +ifeq ($(MCU_F1_LINE), performance) +cSRCS_$(d) += $(MCU_SERIES)/usb.c +cSRCS_$(d) += $(MCU_SERIES)/usb_reg_map.c +cSRCS_$(d) += $(MCU_SERIES)/usb_cdcacm.c +cSRCS_$(d) += usb_lib/usb_core.c +cSRCS_$(d) += usb_lib/usb_init.c +cSRCS_$(d) += usb_lib/usb_mem.c +cSRCS_$(d) += usb_lib/usb_regs.c +endif +endif + +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/libmaple/usb/stm32f1/usb.c b/libmaple/usb/stm32f1/usb.c new file mode 100644 index 0000000..f694f04 --- /dev/null +++ b/libmaple/usb/stm32f1/usb.c @@ -0,0 +1,387 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb.c + * @brief USB support. + * + * This is a mess. + */ + +#include <libmaple/usb.h> + +#include <libmaple/libmaple.h> +#include <libmaple/rcc.h> + +/* Private headers */ +#include "usb_reg_map.h" +#include "usb_lib_globals.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" + +static void dispatch_ctr_lp(void); + +/* + * usb_lib/ globals + */ + +uint16 SaveTState; /* caches TX status for later use */ +uint16 SaveRState; /* caches RX status for later use */ + +/* + * Other state + */ + +typedef enum { + RESUME_EXTERNAL, + RESUME_INTERNAL, + RESUME_LATER, + RESUME_WAIT, + RESUME_START, + RESUME_ON, + RESUME_OFF, + RESUME_ESOF +} RESUME_STATE; + +struct { + volatile RESUME_STATE eState; + volatile uint8 bESOFcnt; +} ResumeS; + +static usblib_dev usblib = { + .irq_mask = USB_ISR_MSK, + .state = USB_UNCONNECTED, + .prevState = USB_UNCONNECTED, + .clk_id = RCC_USB, +}; +usblib_dev *USBLIB = &usblib; + +/* + * Routines + */ + +void usb_init_usblib(usblib_dev *dev, + void (**ep_int_in)(void), + void (**ep_int_out)(void)) { + rcc_clk_enable(dev->clk_id); + + dev->ep_int_in = ep_int_in; + dev->ep_int_out = ep_int_out; + + /* usb_lib/ declares both and then assumes that pFoo points to Foo + * (even though the names don't always match), which is stupid for + * all of the obvious reasons, but whatever. Here we are. */ + pInformation = &Device_Info; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + + pInformation->ControlState = 2; /* FIXME [0.0.12] use + CONTROL_STATE enumerator */ + pProperty->Init(); +} + +static void usb_suspend(void) { + uint16 cntr; + + /* TODO decide if read/modify/write is really what we want + * (e.g. usb_resume_init() reconfigures CNTR). */ + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_FSUSP; + USB_BASE->CNTR = cntr; + cntr |= USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + USBLIB->prevState = USBLIB->state; + USBLIB->state = USB_SUSPENDED; +} + +static void usb_resume_init(void) { + uint16 cntr; + + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + /* Enable interrupt lines */ + USB_BASE->CNTR = USB_ISR_MSK; +} + +static void usb_resume(RESUME_STATE eResumeSetVal) { + uint16 cntr; + + if (eResumeSetVal != RESUME_ESOF) { + ResumeS.eState = eResumeSetVal; + } + + switch (ResumeS.eState) { + case RESUME_EXTERNAL: + usb_resume_init(); + ResumeS.eState = RESUME_OFF; + USBLIB->state = USBLIB->prevState; + break; + case RESUME_INTERNAL: + usb_resume_init(); + ResumeS.eState = RESUME_START; + break; + case RESUME_LATER: + ResumeS.bESOFcnt = 2; + ResumeS.eState = RESUME_WAIT; + break; + case RESUME_WAIT: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + ResumeS.eState = RESUME_START; + } + break; + case RESUME_START: + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + ResumeS.eState = RESUME_ON; + ResumeS.bESOFcnt = 10; + break; + case RESUME_ON: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + USBLIB->state = USBLIB->prevState; + ResumeS.eState = RESUME_OFF; + } + break; + case RESUME_OFF: + case RESUME_ESOF: + default: + ResumeS.eState = RESUME_OFF; + break; + } +} + +#define SUSPEND_ENABLED 1 +void __irq_usb_lp_can_rx0(void) { + uint16 istr = USB_BASE->ISTR; + + /* Use USB_ISR_MSK to only include code for bits we care about. */ + +#if (USB_ISR_MSK & USB_ISTR_RESET) + if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_RESET; + pProperty->Reset(); + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_PMAOVR) + if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_PMAOVR; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_ERR) + if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ERR; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_WKUP) + if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_WKUP; + usb_resume(RESUME_EXTERNAL); + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_SUSP) + if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { + /* check if SUSPEND is possible */ + if (SUSPEND_ENABLED) { + usb_suspend(); + } else { + /* if not possible then resume after xx ms */ + usb_resume(RESUME_LATER); + } + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + USB_BASE->ISTR = ~USB_ISTR_SUSP; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_SOF) + if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_SOF; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_ESOF) + if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ESOF; + /* resume handling timing is made with ESOFs */ + usb_resume(RESUME_ESOF); /* request without change of the machine state */ + } +#endif + + /* + * Service the correct transfer interrupt. + */ + +#if (USB_ISR_MSK & USB_ISTR_CTR) + if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { + dispatch_ctr_lp(); + } +#endif +} + +/* + * Auxiliary routines + */ + +static inline uint8 dispatch_endpt_zero(uint16 istr_dir); +static inline void dispatch_endpt(uint8 ep); +static inline void set_rx_tx_status0(uint16 rx, uint16 tx); + +static void handle_setup0(void); +static void handle_in0(void); +static void handle_out0(void); + +static void dispatch_ctr_lp() { + uint16 istr; + while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) { + /* TODO WTF, figure this out: RM0008 says CTR is read-only, + * but ST's firmware claims it's clear-only, and emphasizes + * the importance of clearing it in more than one place. */ + USB_BASE->ISTR = ~USB_ISTR_CTR; + uint8 ep_id = istr & USB_ISTR_EP_ID; + if (ep_id == 0) { + /* TODO figure out why it's OK to break out of the loop + * once we're done serving endpoint zero, but not okay if + * there are multiple nonzero endpoint transfers to + * handle. */ + if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) { + return; + } + } else { + dispatch_endpt(ep_id); + } + } +} + +/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's + * code, and is ugly/confusing in its use of SaveRState/SaveTState. + * Fixing this requires filling in handle_in0(), handle_setup0(), + * handle_out0(). */ +static inline uint8 dispatch_endpt_zero(uint16 istr_dir) { + uint32 epr = (uint16)USB_BASE->EP[0]; + + if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) { + return 0; + } + + /* Cache RX/TX statuses in SaveRState/SaveTState, respectively. + * The various handle_foo0() may clobber these values + * before we reset them at the end of this routine. */ + SaveRState = epr & USB_EP_STAT_RX; + SaveTState = epr & USB_EP_STAT_TX; + + /* Set actual RX/TX statuses to NAK while we're thinking */ + set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK); + + if (istr_dir == 0) { + /* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR + * register related to the interrupting endpoint. The + * interrupting transaction is of IN type (data transmitted by + * the USB peripheral to the host PC)." */ + ASSERT_FAULT(epr & USB_EP_CTR_TX); + usb_clear_ctr_tx(USB_EP0); + handle_in0(); + } else { + /* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX + * are set in the USB_EPnR register related to the + * interrupting endpoint. The interrupting transaction is of + * OUT type (data received by the USB peripheral from the host + * PC) or two pending transactions are waiting to be + * processed." + * + * [mbolivar] Note how the following control flow (which + * replicates ST's) doesn't seem to actually handle both + * interrupts that are ostensibly pending when both CTR_RX and + * CTR_TX are set. + * + * TODO sort this mess out. + */ + if (epr & USB_EP_CTR_TX) { + usb_clear_ctr_tx(USB_EP0); + handle_in0(); + } else { /* SETUP or CTR_RX */ + /* SETUP is held constant while CTR_RX is set, so clear it + * either way */ + usb_clear_ctr_rx(USB_EP0); + if (epr & USB_EP_SETUP) { + handle_setup0(); + } else { /* CTR_RX */ + handle_out0(); + } + } + } + + set_rx_tx_status0(SaveRState, SaveTState); + return 1; +} + +static inline void dispatch_endpt(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + /* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle, + * then presumably at least one of CTR_RX and CTR_TX is set, but + * again, ST's control flow allows for the possibility of neither. + * + * TODO try to find out if neither being set is possible. */ + if (epr & USB_EP_CTR_RX) { + usb_clear_ctr_rx(ep); + (USBLIB->ep_int_out[ep - 1])(); + } + if (epr & USB_EP_CTR_TX) { + usb_clear_ctr_tx(ep); + (USBLIB->ep_int_in[ep - 1])(); + } +} + +static inline void set_rx_tx_status0(uint16 rx, uint16 tx) { + usb_set_ep_rx_stat(USB_EP0, rx); + usb_set_ep_tx_stat(USB_EP0, tx); +} + +/* TODO Rip out usb_lib/ dependency from the following functions: */ + +static void handle_setup0(void) { + Setup0_Process(); +} + +static void handle_in0(void) { + In0_Process(); +} + +static void handle_out0(void) { + Out0_Process(); +} diff --git a/libmaple/usb/stm32f1/usb_cdcacm.c b/libmaple/usb/stm32f1/usb_cdcacm.c new file mode 100644 index 0000000..d4d4262 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_cdcacm.c @@ -0,0 +1,709 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb_cdcacm.c + * @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM). + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include <libmaple/usb_cdcacm.h> + +#include <libmaple/usb.h> +#include <libmaple/nvic.h> +#include <libmaple/delay.h> + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +/****************************************************************************** + ****************************************************************************** + *** + *** HACK ALERT! FIXME FIXME FIXME FIXME! + *** + *** A bunch of LeafLabs-specific configuration lives in here for + *** now. This mess REALLY needs to get teased apart, with + *** appropriate pieces moved into Wirish. + *** + ****************************************************************************** + *****************************************************************************/ + +#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \ + defined(BOARD_maple_mini) || defined(BOARD_maple_native)) +#warning USB CDC ACM relies on LeafLabs board-specific configuration.\ + You may have problems on non-LeafLabs boards. +#endif + +static void vcomDataTxCb(void); +static void vcomDataRxCb(void); +static uint8* vcomGetSetLineCoding(uint16); + +static void usbInit(void); +static void usbReset(void); +static RESULT usbDataSetup(uint8 request); +static RESULT usbNoDataSetup(uint8 request); +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); +static uint8* usbGetDeviceDescriptor(uint16 length); +static uint8* usbGetConfigDescriptor(uint16 length); +static uint8* usbGetStringDescriptor(uint16 length); +static void usbSetConfiguration(void); +static void usbSetDeviceAddress(void); + +/* + * Descriptors + */ + +/* FIXME move to Wirish */ +#define LEAFLABS_ID_VENDOR 0x1EAF +#define MAPLE_ID_PRODUCT 0x0004 +static const usb_descriptor_device usbVcomDescriptor_Device = + USB_CDCACM_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT); + +typedef struct { + usb_descriptor_config_header Config_Header; + usb_descriptor_interface CCI_Interface; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; + CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; + usb_descriptor_endpoint ManagementEndpoint; + usb_descriptor_interface DCI_Interface; + usb_descriptor_endpoint DataOutEndpoint; + usb_descriptor_endpoint DataInEndpoint; +} __packed usb_descriptor_config; + +#define MAX_POWER (100 >> 1) +static const usb_descriptor_config usbVcomDescriptor_Config = { + .Config_Header = { + .bLength = sizeof(usb_descriptor_config_header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = sizeof(usb_descriptor_config), + .bNumInterfaces = 0x02, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, + }, + + .CCI_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x01, + .bInterfaceClass = USB_INTERFACE_CLASS_CDC, + .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM, + .bInterfaceProtocol = 0x01, /* Common AT Commands */ + .iInterface = 0x00, + }, + + .CDC_Functional_IntHeader = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x00, + .Data = {0x01, 0x10}, + }, + + .CDC_Functional_CallManagement = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x01, + .Data = {0x03, 0x01}, + }, + + .CDC_Functional_ACM = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1), + .bDescriptorType = 0x24, + .SubType = 0x02, + .Data = {0x06}, + }, + + .CDC_Functional_Union = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x06, + .Data = {0x00, 0x01}, + }, + + .ManagementEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | + USB_CDCACM_MANAGEMENT_ENDP), + .bmAttributes = USB_EP_TYPE_INTERRUPT, + .wMaxPacketSize = USB_CDCACM_MANAGEMENT_EPSIZE, + .bInterval = 0xFF, + }, + + .DCI_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x01, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = USB_INTERFACE_CLASS_DIC, + .bInterfaceSubClass = 0x00, /* None */ + .bInterfaceProtocol = 0x00, /* None */ + .iInterface = 0x00, + }, + + .DataOutEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | + USB_CDCACM_RX_ENDP), + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_CDCACM_RX_EPSIZE, + .bInterval = 0x00, + }, + + .DataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_CDCACM_TX_ENDP), + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_CDCACM_TX_EPSIZE, + .bInterval = 0x00, + }, +}; + +/* + String Descriptors: + + we may choose to specify any or none of the following string + identifiers: + + iManufacturer: LeafLabs + iProduct: Maple + iSerialNumber: NONE + iConfiguration: NONE + iInterface(CCI): NONE + iInterface(DCI): NONE + +*/ + +/* Unicode language identifier: 0x0409 is US English */ +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_LangID = { + .bLength = USB_DESCRIPTOR_STRING_LEN(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {0x09, 0x04}, +}; + +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_iManufacturer = { + .bLength = USB_DESCRIPTOR_STRING_LEN(8), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0, + 'L', 0, 'a', 0, 'b', 0, 's', 0}, +}; + +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_iProduct = { + .bLength = USB_DESCRIPTOR_STRING_LEN(5), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0}, +}; + +static ONE_DESCRIPTOR Device_Descriptor = { + (uint8*)&usbVcomDescriptor_Device, + sizeof(usb_descriptor_device) +}; + +static ONE_DESCRIPTOR Config_Descriptor = { + (uint8*)&usbVcomDescriptor_Config, + sizeof(usb_descriptor_config) +}; + +#define N_STRING_DESCRIPTORS 3 +static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = { + {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, + {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)}, + {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)} +}; + +/* + * Etc. + */ + +/* I/O state */ + +/* Received data */ +static volatile uint8 vcomBufferRx[USB_CDCACM_RX_EPSIZE]; +/* Read index into vcomBufferRx */ +static volatile uint32 rx_offset = 0; +/* Number of bytes left to transmit */ +static volatile uint32 n_unsent_bytes = 0; +/* Are we currently sending an IN packet? */ +static volatile uint8 transmitting = 0; +/* Number of unread bytes */ +static volatile uint32 n_unread_bytes = 0; + +/* Other state (line coding, DTR/RTS) */ + +static volatile usb_cdcacm_line_coding line_coding = { + /* This default is 115200 baud, 8N1. */ + .dwDTERate = 115200, + .bCharFormat = USB_CDCACM_STOP_BITS_1, + .bParityType = USB_CDCACM_PARITY_NONE, + .bDataBits = 8, +}; + +/* DTR in bit 0, RTS in bit 1. */ +static volatile uint8 line_dtr_rts = 0; + +/* + * Endpoint callbacks + */ + +static void (*ep_int_in[7])(void) = + {vcomDataTxCb, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process}; + +static void (*ep_int_out[7])(void) = + {NOP_Process, + NOP_Process, + vcomDataRxCb, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process}; + +/* + * Globals required by usb_lib/ + * + * Mark these weak so they can be overriden to implement other USB + * functionality. + */ + +#define NUM_ENDPTS 0x04 +__weak DEVICE Device_Table = { + .Total_Endpoint = NUM_ENDPTS, + .Total_Configuration = 1 +}; + +#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ +__weak DEVICE_PROP Device_Property = { + .Init = usbInit, + .Reset = usbReset, + .Process_Status_IN = NOP_Process, + .Process_Status_OUT = NOP_Process, + .Class_Data_Setup = usbDataSetup, + .Class_NoData_Setup = usbNoDataSetup, + .Class_Get_Interface_Setting = usbGetInterfaceSetting, + .GetDeviceDescriptor = usbGetDeviceDescriptor, + .GetConfigDescriptor = usbGetConfigDescriptor, + .GetStringDescriptor = usbGetStringDescriptor, + .RxEP_buffer = NULL, + .MaxPacketSize = MAX_PACKET_SIZE +}; + +__weak USER_STANDARD_REQUESTS User_Standard_Requests = { + .User_GetConfiguration = NOP_Process, + .User_SetConfiguration = usbSetConfiguration, + .User_GetInterface = NOP_Process, + .User_SetInterface = NOP_Process, + .User_GetStatus = NOP_Process, + .User_ClearFeature = NOP_Process, + .User_SetEndPointFeature = NOP_Process, + .User_SetDeviceFeature = NOP_Process, + .User_SetDeviceAddress = usbSetDeviceAddress +}; + +/* + * User hooks + */ + +static void (*rx_hook)(unsigned, void*) = 0; +static void (*iface_setup_hook)(unsigned, void*) = 0; + +void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) { + if (hook_flags & USB_CDCACM_HOOK_RX) { + rx_hook = hook; + } + if (hook_flags & USB_CDCACM_HOOK_IFACE_SETUP) { + iface_setup_hook = hook; + } +} + +/* + * CDC ACM interface + */ + +void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { + /* Present ourselves to the host. Writing 0 to "disc" pin must + * pull USB_DP pin up while leaving USB_DM pulled down by the + * transceiver. See USB 2.0 spec, section 7.1.7.3. */ + gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); + gpio_write_bit(disc_dev, disc_bit, 0); + + /* Initialize the USB peripheral. */ + usb_init_usblib(USBLIB, ep_int_in, ep_int_out); +} + +void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { + /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 + * spec, section 7.1.7.3). */ + nvic_irq_disable(NVIC_USB_LP_CAN_RX0); + gpio_write_bit(disc_dev, disc_bit, 1); +} + +void usb_cdcacm_putc(char ch) { + while (!usb_cdcacm_tx((uint8*)&ch, 1)) + ; +} + +/* This function is non-blocking. + * + * It copies data from a usercode buffer into the USB peripheral TX + * buffer, and returns the number of bytes copied. */ +uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { + /* Last transmission hasn't finished, so abort. */ + if (usb_cdcacm_is_transmitting()) { + return 0; + } + + /* We can only put USB_CDCACM_TX_EPSIZE bytes in the buffer. */ + if (len > USB_CDCACM_TX_EPSIZE) { + len = USB_CDCACM_TX_EPSIZE; + } + + /* Queue bytes for sending. */ + if (len) { + usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR); + } + // We still need to wait for the interrupt, even if we're sending + // zero bytes. (Sending zero-size packets is useful for flushing + // host-side buffers.) + usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len); + n_unsent_bytes = len; + transmitting = 1; + usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); + + return len; +} + +uint32 usb_cdcacm_data_available(void) { + return n_unread_bytes; +} + +uint8 usb_cdcacm_is_transmitting(void) { + return transmitting; +} + +uint16 usb_cdcacm_get_pending(void) { + return n_unsent_bytes; +} + +/* Nonblocking byte receive. + * + * Copies up to len bytes from our private data buffer (*NOT* the PMA) + * into buf and deq's the FIFO. */ +uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { + /* Copy bytes to buffer. */ + uint32 n_copied = usb_cdcacm_peek(buf, len); + + /* Mark bytes as read. */ + n_unread_bytes -= n_copied; + rx_offset += n_copied; + + /* If all bytes have been read, re-enable the RX endpoint, which + * was set to NAK when the current batch of bytes was received. */ + if (n_unread_bytes == 0) { + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + + return n_copied; +} + +/* Nonblocking byte lookahead. + * + * Looks at unread bytes without marking them as read. */ +uint32 usb_cdcacm_peek(uint8* buf, uint32 len) { + int i; + + if (len > n_unread_bytes) { + len = n_unread_bytes; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[i + rx_offset]; + } + + return len; +} + +uint8 usb_cdcacm_get_dtr() { + return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_DTR) != 0); +} + +uint8 usb_cdcacm_get_rts() { + return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_RTS) != 0); +} + +void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding *ret) { + ret->dwDTERate = line_coding.dwDTERate; + ret->bCharFormat = line_coding.bCharFormat; + ret->bParityType = line_coding.bParityType; + ret->bDataBits = line_coding.bDataBits; +} + +int usb_cdcacm_get_baud(void) { + return line_coding.dwDTERate; +} + +int usb_cdcacm_get_stop_bits(void) { + return line_coding.bCharFormat; +} + +int usb_cdcacm_get_parity(void) { + return line_coding.bParityType; +} + +int usb_cdcacm_get_n_data_bits(void) { + return line_coding.bDataBits; +} + + +/* + * Callbacks + */ + +static void vcomDataTxCb(void) { + n_unsent_bytes = 0; + transmitting = 0; +} + +static void vcomDataRxCb(void) { + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_NAK); + n_unread_bytes = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP); + /* This copy won't overwrite unread bytes, since we've set the RX + * endpoint to NAK, and will only set it to VALID when all bytes + * have been read. */ + usb_copy_from_pma((uint8*)vcomBufferRx, n_unread_bytes, + USB_CDCACM_RX_ADDR); + + + if (n_unread_bytes == 0) { + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + + if (rx_hook) { + rx_hook(USB_CDCACM_HOOK_RX, 0); + } +} + +static uint8* vcomGetSetLineCoding(uint16 length) { + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = sizeof(struct usb_cdcacm_line_coding); + } + return (uint8*)&line_coding; +} + +static void usbInit(void) { + pInformation->Current_Configuration = 0; + + USB_BASE->CNTR = USB_CNTR_FRES; + + USBLIB->irq_mask = 0; + USB_BASE->CNTR = USBLIB->irq_mask; + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + USB_BASE->CNTR = USBLIB->irq_mask; + + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_ISR_MSK; + USB_BASE->CNTR = USBLIB->irq_mask; + + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + USBLIB->state = USB_UNCONNECTED; +} + +#define BTABLE_ADDRESS 0x00 +static void usbReset(void) { + pInformation->Current_Configuration = 0; + + /* current feature is current bmAttributes */ + pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED); + + USB_BASE->BTABLE = BTABLE_ADDRESS; + + /* setup control endpoint 0 */ + usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL); + usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL); + usb_set_ep_rx_addr(USB_EP0, USB_CDCACM_CTRL_RX_ADDR); + usb_set_ep_tx_addr(USB_EP0, USB_CDCACM_CTRL_TX_ADDR); + usb_clear_status_out(USB_EP0); + + usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize); + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + + /* setup management endpoint 1 */ + usb_set_ep_type(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_EP_TYPE_INTERRUPT); + usb_set_ep_tx_addr(USB_CDCACM_MANAGEMENT_ENDP, + USB_CDCACM_MANAGEMENT_ADDR); + usb_set_ep_tx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_RX_DISABLED); + + /* TODO figure out differences in style between RX/TX EP setup */ + + /* set up data endpoint OUT (RX) */ + usb_set_ep_type(USB_CDCACM_RX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_rx_addr(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_ADDR); + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + + /* set up data endpoint IN (TX) */ + usb_set_ep_type(USB_CDCACM_TX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_tx_addr(USB_CDCACM_TX_ENDP, USB_CDCACM_TX_ADDR); + usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_RX_DISABLED); + + USBLIB->state = USB_ATTACHED; + SetDeviceAddress(0); + + /* Reset the RX/TX state */ + n_unread_bytes = 0; + n_unsent_bytes = 0; + rx_offset = 0; + transmitting = 0; +} + +static RESULT usbDataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case USB_CDCACM_GET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + case USB_CDCACM_SET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + default: + break; + } + + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + + if (CopyRoutine == NULL) { + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT usbNoDataSetup(uint8 request) { + RESULT ret = USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case USB_CDCACM_SET_COMM_FEATURE: + /* We support set comm. feature, but don't handle it. */ + ret = USB_SUCCESS; + break; + case USB_CDCACM_SET_CONTROL_LINE_STATE: + /* Track changes to DTR and RTS. */ + line_dtr_rts = (pInformation->USBwValues.bw.bb0 & + (USB_CDCACM_CONTROL_LINE_DTR | + USB_CDCACM_CONTROL_LINE_RTS)); + ret = USB_SUCCESS; + break; + } + + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + return ret; +} + +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { + if (alt_setting > 0) { + return USB_UNSUPPORT; + } else if (interface > 1) { + return USB_UNSUPPORT; + } + + return USB_SUCCESS; +} + +static uint8* usbGetDeviceDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Device_Descriptor); +} + +static uint8* usbGetConfigDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Config_Descriptor); +} + +static uint8* usbGetStringDescriptor(uint16 length) { + uint8 wValue0 = pInformation->USBwValue0; + + if (wValue0 > N_STRING_DESCRIPTORS) { + return NULL; + } + return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); +} + +static void usbSetConfiguration(void) { + if (pInformation->Current_Configuration != 0) { + USBLIB->state = USB_CONFIGURED; + } +} + +static void usbSetDeviceAddress(void) { + USBLIB->state = USB_ADDRESSED; +} diff --git a/libmaple/usb/stm32f1/usb_lib_globals.h b/libmaple/usb/stm32f1/usb_lib_globals.h new file mode 100644 index 0000000..1cd2754 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_lib_globals.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#ifndef _USB_LIB_GLOBALS_H_ +#define _USB_LIB_GLOBALS_H_ + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +extern DEVICE_PROP Device_Property; +extern DEVICE_PROP *pProperty; + +extern DEVICE_INFO Device_Info; +extern DEVICE_INFO *pInformation; + +extern DEVICE Device_Table; +extern u16 SaveRState; +extern u16 SaveTState; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/usb/stm32f1/usb_reg_map.c b/libmaple/usb/stm32f1/usb_reg_map.c new file mode 100644 index 0000000..ea60cb3 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_reg_map.c @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#include "usb_reg_map.h" + +/* TODO these could use some improvement; they're fairly + * straightforward ports of the analogous ST code. The PMA blit + * routines in particular are obvious targets for performance + * measurement and tuning. */ + +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { + uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst = (uint16)(*buf) | *(buf + 1) << 8; + buf += 2; + dst += 2; + } + if (len & 1) { + *dst = *buf; + } +} + +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { + uint32 *src = (uint32*)usb_pma_ptr(pma_offset); + uint16 *dst = (uint16*)buf; + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst++ = *src++; + } + if (len & 1) { + *dst = *src & 0xFF; + } +} + +static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) { + uint16 nblocks; + if (count > 62) { + /* use 32-byte memory block size */ + nblocks = count >> 5; + if ((count & 0x1F) == 0) { + nblocks--; + } + *rxc = (nblocks << 10) | 0x8000; + } else { + /* use 2-byte memory block size */ + nblocks = count >> 1; + if ((count & 0x1) != 0) { + nblocks++; + } + *rxc = nblocks << 10; + } +} + +void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} + +void usb_set_ep_rx_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} diff --git a/libmaple/usb/stm32f1/usb_reg_map.h b/libmaple/usb/stm32f1/usb_reg_map.h new file mode 100644 index 0000000..2e3f6bc --- /dev/null +++ b/libmaple/usb/stm32f1/usb_reg_map.h @@ -0,0 +1,617 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#include <libmaple/libmaple_types.h> +#include <libmaple/util.h> + +#ifndef _USB_REG_MAP_H_ +#define _USB_REG_MAP_H_ + +/* TODO: + * - Pick one of "endp", "ep" "endpt" + */ + +/* + * Register map and base pointer + */ + +#define USB_NR_EP_REGS 8 + +/** USB register map type */ +typedef struct usb_reg_map { + __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ + const uint32 RESERVED[8]; /**< Reserved */ + __io uint32 CNTR; /**< Control register */ + __io uint32 ISTR; /**< Interrupt status register */ + __io uint32 FNR; /**< Frame number register */ + __io uint32 DADDR; /**< Device address */ + __io uint32 BTABLE; /**< @brief Buffer table address + * + * Address offset within the USB + * packet memory area which points + * to the base of the buffer + * descriptor table. Must be + * aligned to an 8 byte boundary. + */ +} usb_reg_map; + +/** USB register map base pointer */ +#define USB_BASE ((struct usb_reg_map*)0x40005C00) + +/* + * Register bit definitions + */ + +/* Endpoint registers (USB_EPnR) */ + +#define USB_EP_CTR_RX_BIT 15 +#define USB_EP_DTOG_RX_BIT 14 +#define USB_EP_SETUP_BIT 11 +#define USB_EP_EP_KIND_BIT 8 +#define USB_EP_CTR_TX_BIT 7 +#define USB_EP_DTOG_TX_BIT 6 + +#define USB_EP_CTR_RX BIT(USB_EP_CTR_RX_BIT) +#define USB_EP_DTOG_RX BIT(USB_EP_DTOG_RX_BIT) +#define USB_EP_STAT_RX (0x3 << 12) +#define USB_EP_STAT_RX_DISABLED (0x0 << 12) +#define USB_EP_STAT_RX_STALL (0x1 << 12) +#define USB_EP_STAT_RX_NAK (0x2 << 12) +#define USB_EP_STAT_RX_VALID (0x3 << 12) +#define USB_EP_SETUP BIT(USB_EP_SETUP_BIT) +#define USB_EP_EP_TYPE (0x3 << 9) +#define USB_EP_EP_TYPE_BULK (0x0 << 9) +#define USB_EP_EP_TYPE_CONTROL (0x1 << 9) +#define USB_EP_EP_TYPE_ISO (0x2 << 9) +#define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9) +#define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT) +#define USB_EP_EP_KIND_DBL_BUF (0x1 << USB_EP_EP_KIND_BIT) +#define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT) +#define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT) +#define USB_EP_STAT_TX (0x3 << 4) +#define USB_EP_STAT_TX_DISABLED (0x0 << 4) +#define USB_EP_STAT_TX_STALL (0x1 << 4) +#define USB_EP_STAT_TX_NAK (0x2 << 4) +#define USB_EP_STAT_TX_VALID (0x3 << 4) +#define USB_EP_EA 0xF + +/* Control register (USB_CNTR) */ + +#define USB_CNTR_CTRM_BIT 15 +#define USB_CNTR_PMAOVERM_BIT 14 +#define USB_CNTR_ERRM_BIT 13 +#define USB_CNTR_WKUPM_BIT 12 +#define USB_CNTR_SUSPM_BIT 11 +#define USB_CNTR_RESETM_BIT 10 +#define USB_CNTR_SOFM_BIT 9 +#define USB_CNTR_ESOFM_BIT 8 +#define USB_CNTR_RESUME_BIT 4 +#define USB_CNTR_FSUSP_BIT 3 +#define USB_CNTR_LP_MODE_BIT 2 +#define USB_CNTR_PDWN_BIT 1 +#define USB_CNTR_FRES_BIT 0 + +#define USB_CNTR_CTRM BIT(USB_CNTR_CTRM_BIT) +#define USB_CNTR_PMAOVERM BIT(USB_CNTR_PMAOVERM_BIT) +#define USB_CNTR_ERRM BIT(USB_CNTR_ERRM_BIT) +#define USB_CNTR_WKUPM BIT(USB_CNTR_WKUPM_BIT) +#define USB_CNTR_SUSPM BIT(USB_CNTR_SUSPM_BIT) +#define USB_CNTR_RESETM BIT(USB_CNTR_RESETM_BIT) +#define USB_CNTR_SOFM BIT(USB_CNTR_SOFM_BIT) +#define USB_CNTR_ESOFM BIT(USB_CNTR_ESOFM_BIT) +#define USB_CNTR_RESUME BIT(USB_CNTR_RESUME_BIT) +#define USB_CNTR_FSUSP BIT(USB_CNTR_FSUSP_BIT) +#define USB_CNTR_LP_MODE BIT(USB_CNTR_LP_MODE_BIT) +#define USB_CNTR_PDWN BIT(USB_CNTR_PDWN_BIT) +#define USB_CNTR_FRES BIT(USB_CNTR_FRES_BIT) + +/* Interrupt status register (USB_ISTR) */ + +#define USB_ISTR_CTR_BIT 15 +#define USB_ISTR_PMAOVR_BIT 14 +#define USB_ISTR_ERR_BIT 13 +#define USB_ISTR_WKUP_BIT 12 +#define USB_ISTR_SUSP_BIT 11 +#define USB_ISTR_RESET_BIT 10 +#define USB_ISTR_SOF_BIT 9 +#define USB_ISTR_ESOF_BIT 8 +#define USB_ISTR_DIR_BIT 4 + +#define USB_ISTR_CTR BIT(USB_ISTR_CTR_BIT) +#define USB_ISTR_PMAOVR BIT(USB_ISTR_PMAOVR_BIT) +#define USB_ISTR_ERR BIT(USB_ISTR_ERR_BIT) +#define USB_ISTR_WKUP BIT(USB_ISTR_WKUP_BIT) +#define USB_ISTR_SUSP BIT(USB_ISTR_SUSP_BIT) +#define USB_ISTR_RESET BIT(USB_ISTR_RESET_BIT) +#define USB_ISTR_SOF BIT(USB_ISTR_SOF_BIT) +#define USB_ISTR_ESOF BIT(USB_ISTR_ESOF_BIT) +#define USB_ISTR_DIR BIT(USB_ISTR_DIR_BIT) +#define USB_ISTR_EP_ID 0xF + +/* Frame number register (USB_FNR) */ + +#define USB_FNR_RXDP_BIT 15 +#define USB_FNR_RXDM_BIT 14 +#define USB_FNR_LCK_BIT 13 + +#define USB_FNR_RXDP BIT(USB_FNR_RXDP_BIT) +#define USB_FNR_RXDM BIT(USB_FNR_RXDM_BIT) +#define USB_FNR_LCK BIT(USB_FNR_LCK_BIT) +#define USB_FNR_LSOF (0x3 << 11) +#define USB_FNR_FN 0x7FF + +/* Device address (USB_DADDR) */ + +#define USB_DADDR_EF_BIT 7 +#define USB_DADDR_ADD6_BIT 6 +#define USB_DADDR_ADD5_BIT 5 +#define USB_DADDR_ADD4_BIT 4 +#define USB_DADDR_ADD3_BIT 3 +#define USB_DADDR_ADD2_BIT 2 +#define USB_DADDR_ADD1_BIT 1 +#define USB_DADDR_ADD0_BIT 0 + +#define USB_DADDR_EF BIT(USB_DADDR_EF_BIT) +#define USB_DADDR_ADD6 BIT(USB_DADDR_ADD6_BIT) +#define USB_DADDR_ADD5 BIT(USB_DADDR_ADD5_BIT) +#define USB_DADDR_ADD4 BIT(USB_DADDR_ADD4_BIT) +#define USB_DADDR_ADD3 BIT(USB_DADDR_ADD3_BIT) +#define USB_DADDR_ADD2 BIT(USB_DADDR_ADD2_BIT) +#define USB_DADDR_ADD1 BIT(USB_DADDR_ADD1_BIT) +#define USB_DADDR_ADD0 BIT(USB_DADDR_ADD0_BIT) + +/* Buffer table address (USB_BTABLE) */ + +#define USB_BTABLE_BTABLE (0x1FFF << 3) + +/* + * Register convenience routines + */ + +#define __EP_CTR_NOP (USB_EP_CTR_RX | USB_EP_CTR_TX) +#define __EP_NONTOGGLE (USB_EP_CTR_RX | USB_EP_SETUP | \ + USB_EP_EP_TYPE | USB_EP_EP_KIND | \ + USB_EP_CTR_TX | USB_EP_EA) + +static inline void usb_clear_ctr_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + USB_BASE->EP[ep] = epr & ~USB_EP_CTR_RX & __EP_NONTOGGLE; +} + +static inline void usb_clear_ctr_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE; +} + +static inline uint32 usb_get_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_TX; +} + +static inline uint32 usb_get_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_RX; +} + +static inline uint32 usb_get_ep_tx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_rx(ep); +} + +static inline uint32 usb_get_ep_rx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_TX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_toggle_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_RX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_clear_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) != 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_clear_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) != 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_set_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) == 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_set_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) == 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_toggle_ep_rx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_tx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_rx(ep); +} + +static inline void usb_clear_ep_rx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_tx(ep); +} + +static inline void usb_clear_ep_tx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_rx(ep); +} + +static inline void usb_set_ep_rx_sw_buf(uint8 ep) { + usb_set_ep_dtog_tx(ep); +} + +static inline void usb_set_ep_tx_sw_buf(uint8 ep) { + usb_set_ep_dtog_rx(ep); +} + +static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); + epr |= __EP_CTR_NOP; + epr ^= status; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_tx_stat(uint8 ep, uint32 status) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~(USB_EP_STAT_RX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); + epr |= __EP_CTR_NOP; + epr ^= status; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_type(uint8 ep, uint32 type) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~USB_EP_EP_TYPE & __EP_NONTOGGLE; + epr |= type; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_kind(uint8 ep, uint32 kind) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~USB_EP_EP_KIND & __EP_NONTOGGLE; + epr |= kind; + USB_BASE->EP[ep] = epr; +} + +static inline uint32 usb_get_ep_type(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + +static inline uint32 usb_get_ep_kind(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + + +static inline void usb_clear_status_out(uint8 ep) { + usb_set_ep_kind(ep, 0); +} + +/* + * Packet memory area (PMA) base pointer + */ + +/** + * @brief USB packet memory area (PMA) base pointer. + * + * The USB PMA is SRAM shared between USB and CAN. The USB peripheral + * accesses this memory directly via the packet buffer interface. */ +#define USB_PMA_BASE ((__io void*)0x40006000) + +/* + * PMA conveniences + */ + +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); + +static inline void* usb_pma_ptr(uint32 offset) { + return (void*)(USB_PMA_BASE + 2 * offset); +} + +/* + * BTABLE + */ + +/* (Forward-declared) BTABLE entry. + * + * The BTABLE can be viewed as an array of usb_btable_ent values; + * these vary in structure according to the configuration of the + * endpoint. + */ +union usb_btable_ent; + +/* Bidirectional endpoint BTABLE entry */ +typedef struct usb_btable_bidi { + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; +} usb_btable_bidi; + +/* Unidirectional receive-only endpoint BTABLE entry */ +typedef struct usb_btable_uni_rx { + __io uint16 empty1; const uint16 PAD1; + __io uint16 empty2; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; +} usb_btable_uni_rx; + +/* Unidirectional transmit-only endpoint BTABLE entry */ +typedef struct usb_btable_uni_tx { + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 empty1; const uint16 PAD3; + __io uint16 empty2; const uint16 PAD4; +} usb_btable_uni_tx; + +/* Double-buffered transmission endpoint BTABLE entry */ +typedef struct usb_btable_dbl_tx { + __io uint16 addr_tx0; const uint16 PAD1; + __io uint16 count_tx0; const uint16 PAD2; + __io uint16 addr_tx1; const uint16 PAD3; + __io uint16 count_tx1; const uint16 PAD4; +} usb_btable_dbl_tx; + +/* Double-buffered reception endpoint BTABLE entry */ +typedef struct usb_btable_dbl_rx { + __io uint16 addr_rx0; const uint16 PAD1; + __io uint16 count_rx0; const uint16 PAD2; + __io uint16 addr_rx1; const uint16 PAD3; + __io uint16 count_rx1; const uint16 PAD4; +} usb_btable_dbl_rx; + +/* TODO isochronous endpoint entries */ + +/* Definition for above forward-declared BTABLE entry. */ +typedef union usb_btable_ent { + usb_btable_bidi bidi; + usb_btable_uni_rx u_rx; + usb_btable_uni_tx u_tx; + usb_btable_dbl_tx d_tx; + usb_btable_dbl_rx d_rx; +} usb_btable_ent; + +/* + * BTABLE conveniences + */ + +/* TODO (?) Convert usages of the many (and lengthily-named) + * accessors/mutators below to just manipulating usb_btable_entry + * values. */ + +static inline uint32* usb_btable_ptr(uint32 offset) { + return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset); +} + +/* TX address */ + +static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8); +} + +static inline uint16 usb_get_ep_tx_addr(uint8 ep) { + return (uint16)*usb_ep_tx_addr_ptr(ep); +} + +static inline void usb_set_ep_tx_addr(uint8 ep, uint16 addr) { + uint32 *tx_addr = usb_ep_tx_addr_ptr(ep); + *tx_addr = addr & ~0x1; +} + +/* RX address */ + +static inline uint32* usb_ep_rx_addr_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 4); +} + +static inline uint16 usb_get_ep_rx_addr(uint8 ep) { + return (uint16)*usb_ep_rx_addr_ptr(ep); +} + +static inline void usb_set_ep_rx_addr(uint8 ep, uint16 addr) { + uint32 *rx_addr = usb_ep_rx_addr_ptr(ep); + *rx_addr = addr & ~0x1; +} + +/* TX count (doesn't cover double-buffered and isochronous in) */ + +static inline uint32* usb_ep_tx_count_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 2); +} + +static inline uint16 usb_get_ep_tx_count(uint8 ep) { + /* FIXME: this is broken somehow; calling it seems to + * confuse/crash the chip. */ + return (uint16)(*usb_ep_tx_count_ptr(ep) & 0x3FF); +} + +static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) { + uint32 *txc = usb_ep_tx_count_ptr(ep); + *txc = count; +} + +/* RX count */ + +static inline uint32* usb_ep_rx_count_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 6); +} + +static inline uint16 usb_get_ep_rx_count(uint8 ep) { + return (uint16)*usb_ep_rx_count_ptr(ep) & 0x3FF; +} + +void usb_set_ep_rx_count(uint8 ep, uint16 count); + +/* double buffer definitions */ +static inline uint32* usb_get_ep_tx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_tx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_tx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_tx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_tx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +static inline void usb_set_ep_tx_buf0_count(uint8 ep, uint16 count) { + usb_set_ep_tx_count(ep, count); +} + +static inline uint32* usb_ep_tx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_tx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, count); +} +static inline uint32* usb_get_ep_rx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_rx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_rx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_rx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_rx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count); + +static inline uint32* usb_ep_rx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_rx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, count); +} + +/* + * Misc. types + */ + +typedef enum usb_ep { + USB_EP0, + USB_EP1, + USB_EP2, + USB_EP3, + USB_EP4, + USB_EP5, + USB_EP6, + USB_EP7, +} usb_ep; + +typedef enum usb_ep_type { + USB_EP_T_CTL = USB_EP_EP_TYPE_CONTROL, + USB_EP_T_BULK = USB_EP_EP_TYPE_BULK, + USB_EP_T_INT = USB_EP_EP_TYPE_INTERRUPT, + USB_EP_T_ISO = USB_EP_EP_TYPE_ISO +} usb_ep_type; + +typedef enum usb_ep_stat { + USB_EP_ST_RX_DIS = USB_EP_STAT_RX_DISABLED, + USB_EP_ST_RX_STL = USB_EP_STAT_RX_STALL, + USB_EP_ST_RX_NAK = USB_EP_STAT_RX_NAK, + USB_EP_ST_RX_VAL = USB_EP_STAT_RX_VALID, + USB_EP_ST_TX_DIS = USB_EP_STAT_TX_DISABLED, + USB_EP_ST_TX_STL = USB_EP_STAT_TX_STALL, + USB_EP_ST_TX_NAK = USB_EP_STAT_TX_NAK, + USB_EP_ST_TX_VAL = USB_EP_STAT_TX_VALID +} usb_ep_stat; + +#endif diff --git a/libmaple/usb/usb_lib/usb_core.c b/libmaple/usb/usb_lib/usb_core.c new file mode 100644 index 0000000..5cf9e87 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_core.c @@ -0,0 +1,1013 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_core.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Standard protocol processing (USB v2.0) +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define ValBit(VAR,Place) (VAR & (1 << Place)) +#define SetBit(VAR,Place) (VAR |= (1 << Place)) +#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255)) + +#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \ + vSetEPTxStatus(EP_TX_VALID); \ + } + +#define vSetEPRxStatus(st) (SaveRState = st) +#define vSetEPTxStatus(st) (SaveTState = st) + +#define USB_StatusIn() Send0LengthData() +#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) + +#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */ +#define StatusInfo1 StatusInfo.bw.bb0 + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +u16_u8 StatusInfo; +USB_Bool Data_Mul_MaxPacketSize = FALSE; +/* Private function prototypes -----------------------------------------------*/ +static void DataStageOut(void); +static void DataStageIn(void); +static void NoData_Setup0(void); +static void Data_Setup0(void); +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : Standard_GetConfiguration. +* Description : Return the current configuration variable address. +* Input : Length - How many bytes are needed. +* Output : None. +* Return : Return 1 , if the request is invalid when "Length" is 0. +* Return "Buffer" if the "Length" is not 0. +*******************************************************************************/ +u8 *Standard_GetConfiguration(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = + sizeof(pInformation->Current_Configuration); + return 0; + } + pUser_Standard_Requests->User_GetConfiguration(); + return (u8 *)&pInformation->Current_Configuration; +} + +/******************************************************************************* +* Function Name : Standard_SetConfiguration. +* Description : This routine is called to set the configuration value +* Then each class should configure device themself. +* Input : None. +* Output : None. +* Return : Return USB_SUCCESS, if the request is performed. +* Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetConfiguration(void) +{ + + if ((pInformation->USBwValue0 <= + Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0) + && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/ + { + pInformation->Current_Configuration = pInformation->USBwValue0; + pUser_Standard_Requests->User_SetConfiguration(); + return USB_SUCCESS; + } + else + { + return USB_UNSUPPORT; + } +} + +/******************************************************************************* +* Function Name : Standard_GetInterface. +* Description : Return the Alternate Setting of the current interface. +* Input : Length - How many bytes are needed. +* Output : None. +* Return : Return 0, if the request is invalid when "Length" is 0. +* Return "Buffer" if the "Length" is not 0. +*******************************************************************************/ +u8 *Standard_GetInterface(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = + sizeof(pInformation->Current_AlternateSetting); + return 0; + } + pUser_Standard_Requests->User_GetInterface(); + return (u8 *)&pInformation->Current_AlternateSetting; +} + +/******************************************************************************* +* Function Name : Standard_SetInterface. +* Description : This routine is called to set the interface. +* Then each class should configure the interface them self. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetInterface(void) +{ + RESULT Re; + /*Test if the specified Interface and Alternate Setting are supported by + the application Firmware*/ + Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); + + if (pInformation->Current_Configuration != 0) + { + if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0) + || (pInformation->USBwValue1 != 0)) + { + return USB_UNSUPPORT; + } + else if (Re == USB_SUCCESS) + { + pUser_Standard_Requests->User_SetInterface(); + pInformation->Current_Interface = pInformation->USBwIndex0; + pInformation->Current_AlternateSetting = pInformation->USBwValue0; + return USB_SUCCESS; + } + + } + + return USB_UNSUPPORT; +} + +/******************************************************************************* +* Function Name : Standard_GetStatus. +* Description : Copy the device request data to "StatusInfo buffer". +* Input : - Length - How many bytes are needed. +* Output : None. +* Return : Return 0, if the request is at end of data block, +* or is invalid when "Length" is 0. +*******************************************************************************/ +u8 *Standard_GetStatus(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = 2; + return 0; + } + + StatusInfo.w = 0; + /* Reset Status Information */ + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /*Get Device Status */ + u8 Feature = pInformation->Current_Feature; + + /* Remote Wakeup enabled */ + if (ValBit(Feature, 5)) + { + SetBit(StatusInfo0, 1); + } + + /* Bus-powered */ + if (ValBit(Feature, 6)) + { + ClrBit(StatusInfo0, 0); + } + else /* Self-powered */ + { + SetBit(StatusInfo0, 0); + } + } + /*Interface Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + return (u8 *)&StatusInfo; + } + /*Get EndPoint Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + u8 Related_Endpoint; + u8 wIndex0 = pInformation->USBwIndex0; + + Related_Endpoint = (wIndex0 & 0x0f); + if (ValBit(wIndex0, 7)) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* IN Endpoint stalled */ + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */ + } + } + + } + else + { + return NULL; + } + pUser_Standard_Requests->User_GetStatus(); + return (u8 *)&StatusInfo; +} + +/******************************************************************************* +* Function Name : Standard_ClearFeature. +* Description : Clear or disable a specific feature. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_ClearFeature(void) +{ + u32 Type_Rec = Type_Recipient; + u32 Status; + + + if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + {/*Device Clear Feature*/ + ClrBit(pInformation->Current_Feature, 5); + return USB_SUCCESS; + } + else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + {/*EndPoint Clear Feature*/ + DEVICE* pDev; + u32 Related_Endpoint; + u32 wIndex0; + u32 rEP; + + if ((pInformation->USBwValue != ENDPOINT_STALL) + || (pInformation->USBwIndex1 != 0)) + { + return USB_UNSUPPORT; + } + + pDev = &Device_Table; + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((rEP >= pDev->Total_Endpoint) || (Status == 0) + || (pInformation->Current_Configuration == 0)) + { + return USB_UNSUPPORT; + } + + + if (wIndex0 & 0x80) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint )) + { + ClearDTOG_TX(Related_Endpoint); + SetEPTxStatus(Related_Endpoint, EP_TX_VALID); + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + if (Related_Endpoint == ENDP0) + { + /* After clear the STALL, enable the default endpoint receiver */ + SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + else + { + ClearDTOG_RX(Related_Endpoint); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + } + } + pUser_Standard_Requests->User_ClearFeature(); + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +/******************************************************************************* +* Function Name : Standard_SetEndPointFeature +* Description : Set or enable a specific feature of EndPoint +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetEndPointFeature(void) +{ + u32 wIndex0; + u32 Related_Endpoint; + u32 rEP; + u32 Status; + + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /* get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if (Related_Endpoint >= Device_Table.Total_Endpoint + || pInformation->USBwValue != 0 || Status == 0 + || pInformation->Current_Configuration == 0) + { + return USB_UNSUPPORT; + } + else + { + if (wIndex0 & 0x80) + { + /* IN endpoint */ + _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); + } + + else + { + /* OUT endpoint */ + _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); + } + } + pUser_Standard_Requests->User_SetEndPointFeature(); + return USB_SUCCESS; +} + +/******************************************************************************* +* Function Name : Standard_SetDeviceFeature. +* Description : Set or enable a specific feature of Device. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetDeviceFeature(void) +{ + SetBit(pInformation->Current_Feature, 5); + pUser_Standard_Requests->User_SetDeviceFeature(); + return USB_SUCCESS; +} + +/******************************************************************************* +* Function Name : Standard_GetDescriptorData. +* Description : Standard_GetDescriptorData is used for descriptors transfer. +* : This routine is used for the descriptors resident in Flash +* or RAM +* pDesc can be in either Flash or RAM +* The purpose of this routine is to have a versatile way to +* response descriptors request. It allows user to generate +* certain descriptors with software or read descriptors from +* external storage part by part. +* Input : - Length - Length of the data in this transfer. +* - pDesc - A pointer points to descriptor struct. +* The structure gives the initial address of the descriptor and +* its original size. +* Output : None. +* Return : Address of a part of the descriptor pointed by the Usb_ +* wOffset The buffer pointed by this address contains at least +* Length bytes. +*******************************************************************************/ +u8 *Standard_GetDescriptorData(u16 Length, ONE_DESCRIPTOR *pDesc) +{ + u32 wOffset; + + wOffset = pInformation->Ctrl_Info.Usb_wOffset; + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; + return 0; + } + + return pDesc->Descriptor + wOffset; +} + +/******************************************************************************* +* Function Name : DataStageOut. +* Description : Data stage of a Control Write Transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void DataStageOut(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + u32 save_rLength; + + save_rLength = pEPinfo->Usb_rLength; + + if (pEPinfo->CopyData && save_rLength) + { + u8 *Buffer; + u32 Length; + + Length = pEPinfo->PacketSize; + if (Length > save_rLength) + { + Length = save_rLength; + } + + Buffer = (*pEPinfo->CopyData)(Length); + pEPinfo->Usb_rLength -= Length; + pEPinfo->Usb_rOffset += Length; + + PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); + } + + if (pEPinfo->Usb_rLength != 0) + { + vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */ + SetEPTxCount(ENDP0, 0); + vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage */ + } + /* Set the next State*/ + if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) + { + pInformation->ControlState = OUT_DATA; + } + else + { + if (pEPinfo->Usb_rLength > 0) + { + pInformation->ControlState = LAST_OUT_DATA; + } + else if (pEPinfo->Usb_rLength == 0) + { + pInformation->ControlState = WAIT_STATUS_IN; + USB_StatusIn(); + } + } +} + +/******************************************************************************* +* Function Name : DataStageIn. +* Description : Data stage of a Control Read Transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void DataStageIn(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + u32 save_wLength = pEPinfo->Usb_wLength; + u32 ControlState = pInformation->ControlState; + + u8 *DataBuffer; + u32 Length; + + if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) + { + if(Data_Mul_MaxPacketSize == TRUE) + { + /* No more data to send and empty packet */ + Send0LengthData(); + ControlState = LAST_IN_DATA; + Data_Mul_MaxPacketSize = FALSE; + } + else + { + /* No more data to send so STALL the TX Status*/ + ControlState = WAIT_STATUS_OUT; + vSetEPTxStatus(EP_TX_STALL); + } + + goto Expect_Status_Out; + } + + Length = pEPinfo->PacketSize; + ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA; + + if (Length > save_wLength) + { + Length = save_wLength; + } + + DataBuffer = (*pEPinfo->CopyData)(Length); + + UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); + + SetEPTxCount(ENDP0, Length); + + pEPinfo->Usb_wLength -= Length; + pEPinfo->Usb_wOffset += Length; + vSetEPTxStatus(EP_TX_VALID); + + USB_StatusOut();/* Expect the host to abort the data IN stage */ + +Expect_Status_Out: + pInformation->ControlState = ControlState; +} + +/******************************************************************************* +* Function Name : NoData_Setup0. +* Description : Proceed the processing of setup request without data stage. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void NoData_Setup0(void) +{ + RESULT Result = USB_UNSUPPORT; + u32 RequestNo = pInformation->USBbRequest; + u32 ControlState; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /* Device Request*/ + /* SET_CONFIGURATION*/ + if (RequestNo == SET_CONFIGURATION) + { + Result = Standard_SetConfiguration(); + } + + /*SET ADDRESS*/ + else if (RequestNo == SET_ADDRESS) + { + if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) + || (pInformation->USBwIndex != 0) + || (pInformation->Current_Configuration != 0)) + /* Device Address should be 127 or less*/ + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + else + { + Result = USB_SUCCESS; + } + } + /*SET FEATURE for Device*/ + else if (RequestNo == SET_FEATURE) + { + if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) + && (pInformation->USBwIndex == 0) + && (ValBit(pInformation->Current_Feature, 5))) + { + Result = Standard_SetDeviceFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + /*Clear FEATURE for Device */ + else if (RequestNo == CLEAR_FEATURE) + { + if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP + && pInformation->USBwIndex == 0 + && ValBit(pInformation->Current_Feature, 5)) + { + Result = Standard_ClearFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + + } + + /* Interface Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + /*SET INTERFACE*/ + if (RequestNo == SET_INTERFACE) + { + Result = Standard_SetInterface(); + } + } + + /* EndPoint Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + /*CLEAR FEATURE for EndPoint*/ + if (RequestNo == CLEAR_FEATURE) + { + Result = Standard_ClearFeature(); + } + /* SET FEATURE for EndPoint*/ + else if (RequestNo == SET_FEATURE) + { + Result = Standard_SetEndPointFeature(); + } + } + else + { + Result = USB_UNSUPPORT; + } + + + if (Result != USB_SUCCESS) + { + Result = (*pProperty->Class_NoData_Setup)(RequestNo); + if (Result == USB_NOT_READY) + { + ControlState = PAUSE; + goto exit_NoData_Setup0; + } + } + + if (Result != USB_SUCCESS) + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + + ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */ + + USB_StatusIn(); + +exit_NoData_Setup0: + pInformation->ControlState = ControlState; + return; +} + +/******************************************************************************* +* Function Name : Data_Setup0. +* Description : Proceed the processing of setup request with data stage. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void Data_Setup0(void) +{ + u8 *(*CopyRoutine)(u16); + RESULT Result; + u32 Request_No = pInformation->USBbRequest; + + u32 Related_Endpoint, Reserved; + u32 wOffset, Status; + + + + CopyRoutine = NULL; + wOffset = 0; + + if (Request_No == GET_DESCRIPTOR) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + u8 wValue1 = pInformation->USBwValue1; + if (wValue1 == DEVICE_DESCRIPTOR) + { + CopyRoutine = pProperty->GetDeviceDescriptor; + } + else if (wValue1 == CONFIG_DESCRIPTOR) + { + CopyRoutine = pProperty->GetConfigDescriptor; + } + else if (wValue1 == STRING_DESCRIPTOR) + { + CopyRoutine = pProperty->GetStringDescriptor; + } /* End of GET_DESCRIPTOR */ + } + } + + /*GET STATUS*/ + else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) + && (pInformation->USBwLength == 0x0002) + && (pInformation->USBwIndex1 == 0)) + { + /* GET STATUS for Device*/ + if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + && (pInformation->USBwIndex == 0)) + { + CopyRoutine = Standard_GetStatus; + } + + /* GET STATUS for Interface*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS) + && (pInformation->Current_Configuration != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + /* GET STATUS for EndPoint*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); + Reserved = pInformation->USBwIndex0 & 0x70; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0) + && (Status != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + } + + /*GET CONFIGURATION*/ + else if (Request_No == GET_CONFIGURATION) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + CopyRoutine = Standard_GetConfiguration; + } + } + /*GET INTERFACE*/ + else if (Request_No == GET_INTERFACE) + { + if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) + && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) + { + CopyRoutine = Standard_GetInterface; + } + + } + + if (CopyRoutine) + { + pInformation->Ctrl_Info.Usb_wOffset = wOffset; + pInformation->Ctrl_Info.CopyData = CopyRoutine; + /* sb in the original the cast to word was directly */ + /* now the cast is made step by step */ + (*CopyRoutine)(0); + Result = USB_SUCCESS; + } + else + { + Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest); + if (Result == USB_NOT_READY) + { + pInformation->ControlState = PAUSE; + return; + } + } + + if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) + { + /* Data is not ready, wait it */ + pInformation->ControlState = PAUSE; + return; + } + if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) + { + /* Unsupported request */ + pInformation->ControlState = STALLED; + return; + } + + + if (ValBit(pInformation->USBbmRequestType, 7)) + { + /* Device ==> Host */ + vu32 wLength = pInformation->USBwLength; + + /* Restrict the data length to be the one host asks */ + if (pInformation->Ctrl_Info.Usb_wLength > wLength) + { + pInformation->Ctrl_Info.Usb_wLength = wLength; + } + + else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) + { + if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) + { + Data_Mul_MaxPacketSize = FALSE; + } + else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) + { + Data_Mul_MaxPacketSize = TRUE; + } + } + + pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; + DataStageIn(); + } + else + { + pInformation->ControlState = OUT_DATA; + vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */ + } + + return; +} + +/******************************************************************************* +* Function Name : Setup0_Process +* Description : Get the device request data and dispatch to individual process. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 Setup0_Process(void) +{ + + union + { + u8* b; + u16* w; + } pBuf; + + pBuf.b = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ + + if (pInformation->ControlState != PAUSE) + { + pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ + pInformation->USBbRequest = *pBuf.b++; /* bRequest */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwLength = *pBuf.w; /* wLength */ + } + + pInformation->ControlState = SETTING_UP; + if (pInformation->USBwLength == 0) + { + /* Setup with no data stage */ + NoData_Setup0(); + } + else + { + /* Setup with data stage */ + Data_Setup0(); + } + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : In0_Process +* Description : Process the IN token on all default endpoint. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 In0_Process(void) +{ + u32 ControlState = pInformation->ControlState; + + if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + DataStageIn(); + /* ControlState may be changed outside the function */ + ControlState = pInformation->ControlState; + } + + else if (ControlState == WAIT_STATUS_IN) + { + if ((pInformation->USBbRequest == SET_ADDRESS) && + (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) + { + SetDeviceAddress(pInformation->USBwValue0); + pUser_Standard_Requests->User_SetDeviceAddress(); + } + (*pProperty->Process_Status_IN)(); + ControlState = STALLED; + } + + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : Out0_Process +* Description : Process the OUT token on all default endpoint. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 Out0_Process(void) +{ + u32 ControlState = pInformation->ControlState; + + if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) + { + DataStageOut(); + ControlState = pInformation->ControlState; /* may be changed outside the function */ + } + + else if (ControlState == WAIT_STATUS_OUT) + { + (*pProperty->Process_Status_OUT)(); + ControlState = STALLED; + } + + else if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + /* host aborts the transfer before finish */ + ControlState = STALLED; + } + + /* Unexpect state, STALL the endpoint */ + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : Post0_Process +* Description : Stall the Endpoint 0 in case of error. +* Input : None. +* Output : None. +* Return : - 0 if the control State is in PAUSE +* - 1 if not. +*******************************************************************************/ +u8 Post0_Process(void) +{ + SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); + + if (pInformation->ControlState == STALLED) + { + vSetEPRxStatus(EP_RX_STALL); + vSetEPTxStatus(EP_TX_STALL); + } + + return (pInformation->ControlState == PAUSE); +} + +/******************************************************************************* +* Function Name : SetDeviceAddress. +* Description : Set the device and all the used Endpoints addresses. +* Input : - Val: device adress. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDeviceAddress(u8 Val) +{ + u32 i; + u32 nEP = Device_Table.Total_Endpoint; + + /* set address in every used endpoint */ + for (i = 0; i < nEP; i++) + { + _SetEPAddress((u8)i, (u8)i); + } /* for */ + _SetDADDR(Val | DADDR_EF); /* set device address and enable function */ +} + +/******************************************************************************* +* Function Name : NOP_Process +* Description : No operation function. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void NOP_Process(void) +{ +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_core.h b/libmaple/usb/usb_lib/usb_core.h new file mode 100644 index 0000000..fa29a18 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_core.h @@ -0,0 +1,251 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_core.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Standard protocol processing functions prototypes +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CORE_H +#define __USB_CORE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +typedef enum _CONTROL_STATE +{ + WAIT_SETUP, /* 0 */ + SETTING_UP, /* 1 */ + IN_DATA, /* 2 */ + OUT_DATA, /* 3 */ + LAST_IN_DATA, /* 4 */ + LAST_OUT_DATA, /* 5 */ + WAIT_STATUS_IN, /* 7 */ + WAIT_STATUS_OUT, /* 8 */ + STALLED, /* 9 */ + PAUSE /* 10 */ +} CONTROL_STATE; /* The state machine states of a control pipe */ + +typedef struct OneDescriptor +{ + u8 *Descriptor; + u16 Descriptor_Size; +} +ONE_DESCRIPTOR, *PONE_DESCRIPTOR; +/* All the request process routines return a value of this type + If the return value is not SUCCESS or NOT_READY, + the software will STALL the correspond endpoint */ +typedef enum _RESULT +{ + USB_SUCCESS = 0, /* Process sucessfully */ + USB_ERROR, + USB_UNSUPPORT, + USB_NOT_READY /* The process has not been finished, endpoint will be + NAK to further rquest */ +} RESULT; + + +/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/ +typedef struct _ENDPOINT_INFO +{ + /* When send data out of the device, + CopyData() is used to get data buffer 'Length' bytes data + if Length is 0, + CopyData() returns the total length of the data + if the request is not supported, returns 0 + (NEW Feature ) + if CopyData() returns -1, the calling routine should not proceed + further and will resume the SETUP process by the class device + if Length is not 0, + CopyData() returns a pointer to indicate the data location + Usb_wLength is the data remain to be sent, + Usb_wOffset is the Offset of original data + When receive data from the host, + CopyData() is used to get user data buffer which is capable + of Length bytes data to copy data from the endpoint buffer. + if Length is 0, + CopyData() returns the available data length, + if Length is not 0, + CopyData() returns user buffer address + Usb_rLength is the data remain to be received, + Usb_rPointer is the Offset of data buffer + */ + u16 Usb_wLength; + u16 Usb_wOffset; + u16 PacketSize; + u8 *(*CopyData)(u16 Length); +}ENDPOINT_INFO; + +/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ + +typedef struct _DEVICE +{ + u8 Total_Endpoint; /* Number of endpoints that are used */ + u8 Total_Configuration;/* Number of configuration available */ +} +DEVICE; + +typedef union +{ + u16 w; + struct BW + { + u8 bb1; + u8 bb0; + } + bw; +} u16_u8; + +typedef struct _DEVICE_INFO +{ + u8 USBbmRequestType; /* bmRequestType */ + u8 USBbRequest; /* bRequest */ + u16_u8 USBwValues; /* wValue */ + u16_u8 USBwIndexs; /* wIndex */ + u16_u8 USBwLengths; /* wLength */ + + u8 ControlState; /* of type CONTROL_STATE */ + u8 Current_Feature; + u8 Current_Configuration; /* Selected configuration */ + u8 Current_Interface; /* Selected interface of current configuration */ + u8 Current_AlternateSetting;/* Selected Alternate Setting of current + interface*/ + + ENDPOINT_INFO Ctrl_Info; +}DEVICE_INFO; + +typedef struct _DEVICE_PROP +{ + void (*Init)(void); /* Initialize the device */ + void (*Reset)(void); /* Reset routine of this device */ + + /* Device dependent process after the status stage */ + void (*Process_Status_IN)(void); + void (*Process_Status_OUT)(void); + + /* Procedure of process on setup stage of a class specified request with data stage */ + /* All class specified requests with data stage are processed in Class_Data_Setup + Class_Data_Setup() + responses to check all special requests and fills ENDPOINT_INFO + according to the request + If IN tokens are expected, then wLength & wOffset will be filled + with the total transferring bytes and the starting position + If OUT tokens are expected, then rLength & rOffset will be filled + with the total expected bytes and the starting position in the buffer + + If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT + + CAUTION: + Since GET_CONFIGURATION & GET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + RESULT (*Class_Data_Setup)(u8 RequestNo); + + /* Procedure of process on setup stage of a class specified request without data stage */ + /* All class specified requests without data stage are processed in Class_NoData_Setup + Class_NoData_Setup + responses to check all special requests and perform the request + + CAUTION: + Since SET_CONFIGURATION & SET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + RESULT (*Class_NoData_Setup)(u8 RequestNo); + + /*Class_Get_Interface_Setting + This function is used by the file usb_core.c to test if the selected Interface + and Alternate Setting (u8 Interface, u8 AlternateSetting) are supported by + the application. + This function is writing by user. It should return "SUCCESS" if the Interface + and Alternate Setting are supported by the application or "UNSUPPORT" if they + are not supported. */ + + RESULT (*Class_Get_Interface_Setting)(u8 Interface, u8 AlternateSetting); + + u8* (*GetDeviceDescriptor)(u16 Length); + u8* (*GetConfigDescriptor)(u16 Length); + u8* (*GetStringDescriptor)(u16 Length); + + u8* RxEP_buffer; + u8 MaxPacketSize; + +}DEVICE_PROP; + +typedef struct _USER_STANDARD_REQUESTS +{ + void (*User_GetConfiguration)(void); /* Get Configuration */ + void (*User_SetConfiguration)(void); /* Set Configuration */ + void (*User_GetInterface)(void); /* Get Interface */ + void (*User_SetInterface)(void); /* Set Interface */ + void (*User_GetStatus)(void); /* Get Status */ + void (*User_ClearFeature)(void); /* Clear Feature */ + void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ + void (*User_SetDeviceFeature)(void); /* Set Device Feature */ + void (*User_SetDeviceAddress)(void); /* Set Device Address */ +} +USER_STANDARD_REQUESTS; + +/* Exported constants --------------------------------------------------------*/ +#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT)) + +#define Usb_rLength Usb_wLength +#define Usb_rOffset Usb_wOffset + +#define USBwValue USBwValues.w +#define USBwValue0 USBwValues.bw.bb0 +#define USBwValue1 USBwValues.bw.bb1 +#define USBwIndex USBwIndexs.w +#define USBwIndex0 USBwIndexs.bw.bb0 +#define USBwIndex1 USBwIndexs.bw.bb1 +#define USBwLength USBwLengths.w +#define USBwLength0 USBwLengths.bw.bb0 +#define USBwLength1 USBwLengths.bw.bb1 + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +u8 Setup0_Process(void); +u8 Post0_Process(void); +u8 Out0_Process(void); +u8 In0_Process(void); + +RESULT Standard_SetEndPointFeature(void); +RESULT Standard_SetDeviceFeature(void); + +u8 *Standard_GetConfiguration(u16 Length); +RESULT Standard_SetConfiguration(void); +u8 *Standard_GetInterface(u16 Length); +RESULT Standard_SetInterface(void); +u8 *Standard_GetDescriptorData(u16 Length, PONE_DESCRIPTOR pDesc); + +u8 *Standard_GetStatus(u16 Length); +RESULT Standard_ClearFeature(void); +void SetDeviceAddress(u8); +void NOP_Process(void); + +extern DEVICE_PROP Device_Property; +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern DEVICE Device_Table; +extern DEVICE_INFO Device_Info; + +/* cells saving status during interrupt servicing */ +extern u16 SaveRState; +extern u16 SaveTState; + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_CORE_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_def.h b/libmaple/usb/usb_lib/usb_def.h new file mode 100644 index 0000000..80aa303 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_def.h @@ -0,0 +1,88 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_def.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Definitions related to USB Core +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DEF_H +#define __USB_DEF_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +typedef enum _RECIPIENT_TYPE +{ + DEVICE_RECIPIENT, /* Recipient device */ + INTERFACE_RECIPIENT, /* Recipient interface */ + ENDPOINT_RECIPIENT, /* Recipient endpoint */ + OTHER_RECIPIENT +} RECIPIENT_TYPE; + + +typedef enum _STANDARD_REQUESTS +{ + GET_STATUS = 0, + CLEAR_FEATURE, + RESERVED1, + SET_FEATURE, + RESERVED2, + SET_ADDRESS, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + TOTAL_sREQUEST, /* Total number of Standard request */ + SYNCH_FRAME = 12 +} STANDARD_REQUESTS; + +/* Definition of "USBwValue" */ +typedef enum _DESCRIPTOR_TYPE +{ + DEVICE_DESCRIPTOR = 1, + CONFIG_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR +} DESCRIPTOR_TYPE; + +/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */ +typedef enum _FEATURE_SELECTOR +{ + ENDPOINT_STALL, + DEVICE_REMOTE_WAKEUP +} FEATURE_SELECTOR; + +/* Exported constants --------------------------------------------------------*/ +/* Definition of "USBbmRequestType" */ +#define REQUEST_TYPE 0x60 /* Mask to get request type */ +#define STANDARD_REQUEST 0x00 /* Standard request */ +#define CLASS_REQUEST 0x20 /* Class request */ +#define VENDOR_REQUEST 0x40 /* Vendor request */ + +#define RECIPIENT 0x1F /* Mask to get recipient */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_DEF_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_init.c b/libmaple/usb/usb_lib/usb_init.c new file mode 100644 index 0000000..94f3a83 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_init.c @@ -0,0 +1,64 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_init.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Initialization routines & global variables +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* The number of current endpoint, it will be used to specify an endpoint */ + u8 EPindex; +/* The number of current device, it is an index to the Device_Table */ +/* u8 Device_no; */ +/* Points to the DEVICE_INFO structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_INFO *pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_PROP *pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +u16 SaveState ; +u16 wInterrupt_Mask; +DEVICE_INFO Device_Info; +USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : USB_Init +* Description : USB system initialization +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void USB_Init(void) +{ + pInformation = &Device_Info; + pInformation->ControlState = 2; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + /* Initialize devices one by one */ + + pProperty->Init(); +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_init.h b/libmaple/usb/usb_lib/usb_init.h new file mode 100644 index 0000000..80ee2fb --- /dev/null +++ b/libmaple/usb/usb_lib/usb_init.h @@ -0,0 +1,57 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_init.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Initialization routines & global variables +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_INIT_H +#define __USB_INIT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +void USB_Init(void); + +/* External variables --------------------------------------------------------*/ +/* The number of current endpoint, it will be used to specify an endpoint */ +extern u8 EPindex; +/* The number of current device, it is an index to the Device_Table */ +/*extern u8 Device_no; */ +/* Points to the DEVICE_INFO structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern DEVICE_INFO* pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern DEVICE_PROP* pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +extern u16 SaveState ; +extern u16 wInterrupt_Mask; + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_INIT_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_lib.h b/libmaple/usb/usb_lib/usb_lib.h new file mode 100644 index 0000000..85f94ab --- /dev/null +++ b/libmaple/usb/usb_lib/usb_lib.h @@ -0,0 +1,36 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_lib.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : USB library include files +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_LIB_H +#define __USB_LIB_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_type.h" +#include "usb_regs.h" +#include "usb_def.h" +#include "usb_core.h" +#include "usb_init.h" +#include "usb_mem.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +/* External variables --------------------------------------------------------*/ + +#endif /* __USB_LIB_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_mem.c b/libmaple/usb/usb_lib/usb_mem.c new file mode 100644 index 0000000..ad9740a --- /dev/null +++ b/libmaple/usb/usb_lib/usb_mem.c @@ -0,0 +1,73 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_mem.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Utility functions for memory transfers to/from PMA +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/******************************************************************************* +* Function Name : UserToPMABufferCopy +* Description : Copy a buffer from user memory area to packet memory area (PMA) +* Input : - pbUsrBuf: pointer to user memory area. +* - wPMABufAddr: address into PMA. +* - wNBytes: no. of bytes to be copied. +* Output : None. +* Return : None . +*******************************************************************************/ +void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ + u32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ + u32 i, temp1, temp2; + u16 *pdwVal; + pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + temp1 = (u16) * pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (u16) * pbUsrBuf << 8; + *pdwVal++ = temp2; + pdwVal++; + pbUsrBuf++; + } +} +/******************************************************************************* +* Function Name : PMAToUserBufferCopy +* Description : Copy a buffer from user memory area to packet memory area (PMA) +* Input : - pbUsrBuf = pointer to user memory area. +* - wPMABufAddr = address into PMA. +* - wNBytes = no. of bytes to be copied. +* Output : None. +* Return : None. +*******************************************************************************/ +void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ + u32 n = (wNBytes + 1) >> 1;/* /2*/ + u32 i; + u32 *pdwVal; + pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + *(u16*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + } +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_mem.h b/libmaple/usb/usb_lib/usb_mem.h new file mode 100644 index 0000000..b0e0474 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_mem.h @@ -0,0 +1,40 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_mem.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Utility prototypes functions for memory/PMA transfers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_MEM_H +#define __USB_MEM_H + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#if defined(__cplusplus) +extern "C" { +#endif + +void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); +void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); + +#if defined(__cplusplus) +} +#endif + +/* External variables --------------------------------------------------------*/ + +#endif /*__USB_MEM_H*/ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_regs.c b/libmaple/usb/usb_lib/usb_regs.c new file mode 100644 index 0000000..c7e0276 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_regs.c @@ -0,0 +1,748 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_regs.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Interface functions to USB cell registers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : SetCNTR. +* Description : Set the CNTR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetCNTR(u16 wRegValue) +{ + _SetCNTR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetCNTR. +* Description : returns the CNTR register value. +* Input : None. +* Output : None. +* Return : CNTR register Value. +*******************************************************************************/ +u16 GetCNTR(void) +{ + return(_GetCNTR()); +} + +/******************************************************************************* +* Function Name : SetISTR. +* Description : Set the ISTR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetISTR(u16 wRegValue) +{ + _SetISTR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetISTR +* Description : Returns the ISTR register value. +* Input : None. +* Output : None. +* Return : ISTR register Value +*******************************************************************************/ +u16 GetISTR(void) +{ + return(_GetISTR()); +} + +/******************************************************************************* +* Function Name : GetFNR +* Description : Returns the FNR register value. +* Input : None. +* Output : None. +* Return : FNR register Value +*******************************************************************************/ +u16 GetFNR(void) +{ + return(_GetFNR()); +} + +/******************************************************************************* +* Function Name : SetDADDR +* Description : Set the DADDR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDADDR(u16 wRegValue) +{ + _SetDADDR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetDADDR +* Description : Returns the DADDR register value. +* Input : None. +* Output : None. +* Return : DADDR register Value +*******************************************************************************/ +u16 GetDADDR(void) +{ + return(_GetDADDR()); +} + +/******************************************************************************* +* Function Name : SetBTABLE +* Description : Set the BTABLE. +* Input : wRegValue: New register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetBTABLE(u16 wRegValue) +{ + _SetBTABLE(wRegValue); +} + +/******************************************************************************* +* Function Name : GetBTABLE. +* Description : Returns the BTABLE register value. +* Input : None. +* Output : None. +* Return : BTABLE address. +*******************************************************************************/ +u16 GetBTABLE(void) +{ + return(_GetBTABLE()); +} + +/******************************************************************************* +* Function Name : SetENDPOINT +* Description : Setthe Endpoint register value. +* Input : bEpNum: Endpoint Number. +* wRegValue. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetENDPOINT(u8 bEpNum, u16 wRegValue) +{ + _SetENDPOINT(bEpNum, wRegValue); +} + +/******************************************************************************* +* Function Name : GetENDPOINT +* Description : Return the Endpoint register value. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint register value. +*******************************************************************************/ +u16 GetENDPOINT(u8 bEpNum) +{ + return(_GetENDPOINT(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPType +* Description : sets the type in the endpoint register. +* Input : bEpNum: Endpoint Number. +* wType: type definition. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPType(u8 bEpNum, u16 wType) +{ + _SetEPType(bEpNum, wType); +} + +/******************************************************************************* +* Function Name : GetEPType +* Description : Returns the endpoint type. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Type +*******************************************************************************/ +u16 GetEPType(u8 bEpNum) +{ + return(_GetEPType(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPTxStatus +* Description : Set the status of Tx endpoint. +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxStatus(u8 bEpNum, u16 wState) +{ + _SetEPTxStatus(bEpNum, wState); +} + +/******************************************************************************* +* Function Name : SetEPRxStatus +* Description : Set the status of Rx endpoint. +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxStatus(u8 bEpNum, u16 wState) +{ + _SetEPRxStatus(bEpNum, wState); +} + +/******************************************************************************* +* Function Name : SetDouBleBuffEPStall +* Description : sets the status for Double Buffer Endpoint to STALL +* Input : bEpNum: Endpoint Number. +* bDir: Endpoint direction. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDouBleBuffEPStall(u8 bEpNum, u8 bDir) +{ + u16 Endpoint_DTOG_Status; + Endpoint_DTOG_Status = GetENDPOINT(bEpNum); + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1); + } +} + +/******************************************************************************* +* Function Name : GetEPTxStatus +* Description : Returns the endpoint Tx status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint TX Status +*******************************************************************************/ +u16 GetEPTxStatus(u8 bEpNum) +{ + return(_GetEPTxStatus(bEpNum)); +} + +/******************************************************************************* +* Function Name : GetEPRxStatus +* Description : Returns the endpoint Rx status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint RX Status +*******************************************************************************/ +u16 GetEPRxStatus(u8 bEpNum) +{ + return(_GetEPRxStatus(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPTxValid +* Description : Valid the endpoint Tx Status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxValid(u8 bEpNum) +{ + _SetEPTxStatus(bEpNum, EP_TX_VALID); +} + +/******************************************************************************* +* Function Name : SetEPRxValid +* Description : Valid the endpoint Rx Status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxValid(u8 bEpNum) +{ + _SetEPRxStatus(bEpNum, EP_RX_VALID); +} + +/******************************************************************************* +* Function Name : SetEP_KIND +* Description : Clear the EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEP_KIND(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} + +/******************************************************************************* +* Function Name : ClearEP_KIND +* Description : set the EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_KIND(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : Clear_Status_Out +* Description : Clear the Status Out of the related Endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void Clear_Status_Out(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : Set_Status_Out +* Description : Set the Status Out of the related Endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void Set_Status_Out(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : SetEPDoubleBuff +* Description : Enable the double buffer feature for the endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDoubleBuff(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : ClearEPDoubleBuff +* Description : Disable the double buffer feature for the endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEPDoubleBuff(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : GetTxStallStatus +* Description : Returns the Stall status of the Tx endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Tx Stall status. +*******************************************************************************/ +u16 GetTxStallStatus(u8 bEpNum) +{ + return(_GetTxStallStatus(bEpNum)); +} +/******************************************************************************* +* Function Name : GetRxStallStatus +* Description : Returns the Stall status of the Rx endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx Stall status. +*******************************************************************************/ +u16 GetRxStallStatus(u8 bEpNum) +{ + return(_GetRxStallStatus(bEpNum)); +} +/******************************************************************************* +* Function Name : ClearEP_CTR_RX +* Description : Clear the CTR_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_CTR_RX(u8 bEpNum) +{ + _ClearEP_CTR_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearEP_CTR_TX +* Description : Clear the CTR_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_CTR_TX(u8 bEpNum) +{ + _ClearEP_CTR_TX(bEpNum); +} +/******************************************************************************* +* Function Name : ToggleDTOG_RX +* Description : Toggle the DTOG_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ToggleDTOG_RX(u8 bEpNum) +{ + _ToggleDTOG_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ToggleDTOG_TX +* Description : Toggle the DTOG_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ToggleDTOG_TX(u8 bEpNum) +{ + _ToggleDTOG_TX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearDTOG_RX. +* Description : Clear the DTOG_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearDTOG_RX(u8 bEpNum) +{ + _ClearDTOG_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearDTOG_TX. +* Description : Clear the DTOG_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearDTOG_TX(u8 bEpNum) +{ + _ClearDTOG_TX(bEpNum); +} +/******************************************************************************* +* Function Name : SetEPAddress +* Description : Set the endpoint address. +* Input : bEpNum: Endpoint Number. +* bAddr: New endpoint address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPAddress(u8 bEpNum, u8 bAddr) +{ + _SetEPAddress(bEpNum, bAddr); +} +/******************************************************************************* +* Function Name : GetEPAddress +* Description : Get the endpoint address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint address. +*******************************************************************************/ +u8 GetEPAddress(u8 bEpNum) +{ + return(_GetEPAddress(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPTxAddr +* Description : Set the endpoint Tx buffer address. +* Input : bEpNum: Endpoint Number. +* wAddr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxAddr(u8 bEpNum, u16 wAddr) +{ + _SetEPTxAddr(bEpNum, wAddr); +} +/******************************************************************************* +* Function Name : SetEPRxAddr +* Description : Set the endpoint Rx buffer address. +* Input : bEpNum: Endpoint Number. +* wAddr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxAddr(u8 bEpNum, u16 wAddr) +{ + _SetEPRxAddr(bEpNum, wAddr); +} +/******************************************************************************* +* Function Name : GetEPTxAddr +* Description : Returns the endpoint Tx buffer address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx buffer address. +*******************************************************************************/ +u16 GetEPTxAddr(u8 bEpNum) +{ + return(_GetEPTxAddr(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPRxAddr. +* Description : Returns the endpoint Rx buffer address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx buffer address. +*******************************************************************************/ +u16 GetEPRxAddr(u8 bEpNum) +{ + return(_GetEPRxAddr(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPTxCount. +* Description : Set the Tx count. +* Input : bEpNum: Endpoint Number. +* wCount: new count value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxCount(u8 bEpNum, u16 wCount) +{ + _SetEPTxCount(bEpNum, wCount); +} +/******************************************************************************* +* Function Name : SetEPCountRxReg. +* Description : Set the Count Rx Register value. +* Input : *pdwReg: point to the register. +* wCount: the new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPCountRxReg(u32 *pdwReg, u16 wCount) +{ + _SetEPCountRxReg(dwReg, wCount); +} +/******************************************************************************* +* Function Name : SetEPRxCount +* Description : Set the Rx count. +* Input : bEpNum: Endpoint Number. +* wCount: the new count value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxCount(u8 bEpNum, u16 wCount) +{ + _SetEPRxCount(bEpNum, wCount); +} +/******************************************************************************* +* Function Name : GetEPTxCount +* Description : Get the Tx count. +* Input : bEpNum: Endpoint Number. +* Output : None +* Return : Tx count value. +*******************************************************************************/ +u16 GetEPTxCount(u8 bEpNum) +{ + return(_GetEPTxCount(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPRxCount +* Description : Get the Rx count. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx count value. +*******************************************************************************/ +u16 GetEPRxCount(u8 bEpNum) +{ + return(_GetEPRxCount(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPDblBuffAddr +* Description : Set the addresses of the buffer 0 and 1. +* Input : bEpNum: Endpoint Number. +* wBuf0Addr: new address of buffer 0. +* wBuf1Addr: new address of buffer 1. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuffAddr(u8 bEpNum, u16 wBuf0Addr, u16 wBuf1Addr) +{ + _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); +} +/******************************************************************************* +* Function Name : SetEPDblBuf0Addr +* Description : Set the Buffer 1 address. +* Input : bEpNum: Endpoint Number +* wBuf0Addr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf0Addr(u8 bEpNum, u16 wBuf0Addr) +{ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); +} +/******************************************************************************* +* Function Name : SetEPDblBuf1Addr +* Description : Set the Buffer 1 address. +* Input : bEpNum: Endpoint Number +* wBuf1Addr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf1Addr(u8 bEpNum, u16 wBuf1Addr) +{ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); +} +/******************************************************************************* +* Function Name : GetEPDblBuf0Addr +* Description : Returns the address of the Buffer 0. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +u16 GetEPDblBuf0Addr(u8 bEpNum) +{ + return(_GetEPDblBuf0Addr(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBuf1Addr +* Description : Returns the address of the Buffer 1. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Address of the Buffer 1. +*******************************************************************************/ +u16 GetEPDblBuf1Addr(u8 bEpNum) +{ + return(_GetEPDblBuf1Addr(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPDblBuffCount +* Description : Set the number of bytes for a double Buffer +* endpoint. +* Input : bEpNum,bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuffCount(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuffCount(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : SetEPDblBuf0Count +* Description : Set the number of bytes in the buffer 0 of a double Buffer +* endpoint. +* Input : bEpNum, bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf0Count(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : SetEPDblBuf1Count +* Description : Set the number of bytes in the buffer 0 of a double Buffer +* endpoint. +* Input : bEpNum, bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf1Count(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : GetEPDblBuf0Count +* Description : Returns the number of byte received in the buffer 0 of a double +* Buffer endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Buffer 0 count +*******************************************************************************/ +u16 GetEPDblBuf0Count(u8 bEpNum) +{ + return(_GetEPDblBuf0Count(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBuf1Count +* Description : Returns the number of data received in the buffer 1 of a double +* Buffer endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Buffer 1 count. +*******************************************************************************/ +u16 GetEPDblBuf1Count(u8 bEpNum) +{ + return(_GetEPDblBuf1Count(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBufDir +* Description : gets direction of the double buffered endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : EP_DBUF_OUT, EP_DBUF_IN, +* EP_DBUF_ERR if the endpoint counter not yet programmed. +*******************************************************************************/ +EP_DBUF_DIR GetEPDblBufDir(u8 bEpNum) +{ + if ((u16)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) + return(EP_DBUF_OUT); + else if (((u16)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) + return(EP_DBUF_IN); + else + return(EP_DBUF_ERR); +} +/******************************************************************************* +* Function Name : FreeUserBuffer +* Description : free buffer used from the application realizing it to the line + toggles bit SW_BUF in the double buffered endpoint register +* Input : bEpNum, bDir +* Output : None. +* Return : None. +*******************************************************************************/ +void FreeUserBuffer(u8 bEpNum, u8 bDir) +{ + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _ToggleDTOG_TX(bEpNum); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _ToggleDTOG_RX(bEpNum); + } +} + +/******************************************************************************* +* Function Name : ToWord +* Description : merge two byte in a word. +* Input : bh: byte high, bl: bytes low. +* Output : None. +* Return : resulted word. +*******************************************************************************/ +u16 ToWord(u8 bh, u8 bl) +{ + u16 wRet; + wRet = (u16)bl | ((u16)bh << 8); + return(wRet); +} +/******************************************************************************* +* Function Name : ByteSwap +* Description : Swap two byte in a word. +* Input : wSwW: word to Swap. +* Output : None. +* Return : resulted word. +*******************************************************************************/ +u16 ByteSwap(u16 wSwW) +{ + u8 bTemp; + u16 wRet; + bTemp = (u8)(wSwW & 0xff); + wRet = (wSwW >> 8) | ((u16)bTemp << 8); + return(wRet); +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_regs.h b/libmaple/usb/usb_lib/usb_regs.h new file mode 100644 index 0000000..b63cc5f --- /dev/null +++ b/libmaple/usb/usb_lib/usb_regs.h @@ -0,0 +1,627 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_regs.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Interface prototype functions to USB cell registers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_REGS_H +#define __USB_REGS_H + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +#if defined(__cplusplus) +extern "C" { +#endif + +typedef enum _EP_DBUF_DIR +{ + /* double buffered endpoint direction */ + EP_DBUF_ERR, + EP_DBUF_OUT, + EP_DBUF_IN +}EP_DBUF_DIR; + +/* endpoint buffer number */ +enum EP_BUF_NUM +{ + EP_NOBUF, + EP_BUF0, + EP_BUF1 +}; + +/* Exported constants --------------------------------------------------------*/ +#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */ +#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */ + +/******************************************************************************/ +/* General registers */ +/******************************************************************************/ + +/* Control register */ +#define CNTR ((volatile unsigned *)(RegBase + 0x40)) +/* Interrupt status register */ +#define ISTR ((volatile unsigned *)(RegBase + 0x44)) +/* Frame number register */ +#define FNR ((volatile unsigned *)(RegBase + 0x48)) +/* Device address register */ +#define DADDR ((volatile unsigned *)(RegBase + 0x4C)) +/* Buffer Table address register */ +#define BTABLE ((volatile unsigned *)(RegBase + 0x50)) +/******************************************************************************/ +/* Endpoint registers */ +/******************************************************************************/ +#define EP0REG ((volatile unsigned *)(RegBase)) /* endpoint 0 register address */ + +/* endpoints enumeration */ +#define ENDP0 ((u8)0) +#define ENDP1 ((u8)1) +#define ENDP2 ((u8)2) +#define ENDP3 ((u8)3) +#define ENDP4 ((u8)4) +#define ENDP5 ((u8)5) +#define ENDP6 ((u8)6) +#define ENDP7 ((u8)7) +/******************************************************************************/ +/* ISTR interrupt events */ +/******************************************************************************/ +#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ +#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ +#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ +#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ +#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ +#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ +#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ +#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ + + +#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ +#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ + +#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ +#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ +#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ +#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ +#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ +#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ +#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ +#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ + +/******************************************************************************/ +/* CNTR control register bits definitions */ +/******************************************************************************/ +#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ +#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ +#define CNTR_ERRM (0x2000) /* ERRor Mask */ +#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ +#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ +#define CNTR_RESETM (0x0400) /* RESET Mask */ +#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ +#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ + + +#define CNTR_RESUME (0x0010) /* RESUME request */ +#define CNTR_FSUSP (0x0008) /* Force SUSPend */ +#define CNTR_LPMODE (0x0004) /* Low-power MODE */ +#define CNTR_PDWN (0x0002) /* Power DoWN */ +#define CNTR_FRES (0x0001) /* Force USB RESet */ + +/******************************************************************************/ +/* FNR Frame Number Register bit definitions */ +/******************************************************************************/ +#define FNR_RXDP (0x8000) /* status of D+ data line */ +#define FNR_RXDM (0x4000) /* status of D- data line */ +#define FNR_LCK (0x2000) /* LoCKed */ +#define FNR_LSOF (0x1800) /* Lost SOF */ +#define FNR_FN (0x07FF) /* Frame Number */ +/******************************************************************************/ +/* DADDR Device ADDRess bit definitions */ +/******************************************************************************/ +#define DADDR_EF (0x80) +#define DADDR_ADD (0x7F) +/******************************************************************************/ +/* Endpoint register */ +/******************************************************************************/ +/* bit positions */ +#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ +#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ +#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ +#define EP_SETUP (0x0800) /* EndPoint SETUP */ +#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ +#define EP_KIND (0x0100) /* EndPoint KIND */ +#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ +#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ +#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ +#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ + +/* EndPoint REGister MASK (no toggle fields) */ +#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) + +/* EP_TYPE[1:0] EndPoint TYPE */ +#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ +#define EP_BULK (0x0000) /* EndPoint BULK */ +#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ +#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ +#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) + + +/* EP_KIND EndPoint KIND */ +#define EPKIND_MASK (~EP_KIND & EPREG_MASK) + +/* STAT_TX[1:0] STATus for TX transfer */ +#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ +#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ +#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ +#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ +#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ +#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ +#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK) + +/* STAT_RX[1:0] STATus for RX transfer */ +#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ +#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ +#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ +#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ +#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK) +/* Exported macro ------------------------------------------------------------*/ +/* SetCNTR */ +#define _SetCNTR(wRegValue) (*CNTR = (u16)wRegValue) + +/* SetISTR */ +#define _SetISTR(wRegValue) (*ISTR = (u16)wRegValue) + +/* SetDADDR */ +#define _SetDADDR(wRegValue) (*DADDR = (u16)wRegValue) + +/* SetBTABLE */ +#define _SetBTABLE(wRegValue)(*BTABLE = (u16)(wRegValue & 0xFFF8)) + +/* GetCNTR */ +#define _GetCNTR() ((u16) *CNTR) + +/* GetISTR */ +#define _GetISTR() ((u16) *ISTR) + +/* GetFNR */ +#define _GetFNR() ((u16) *FNR) + +/* GetDADDR */ +#define _GetDADDR() ((u16) *DADDR) + +/* GetBTABLE */ +#define _GetBTABLE() ((u16) *BTABLE) + +/* SetENDPOINT */ +#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \ + (u16)wRegValue) + +/* GetENDPOINT */ +#define _GetENDPOINT(bEpNum) ((u16)(*(EP0REG + bEpNum))) + +/******************************************************************************* +* Macro Name : SetEPType +* Description : sets the type in the endpoint register(bits EP_TYPE[1:0]) +* Input : bEpNum: Endpoint Number. +* wType +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\ + ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType))) + +/******************************************************************************* +* Macro Name : GetEPType +* Description : gets the type in the endpoint register(bits EP_TYPE[1:0]) +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Type +*******************************************************************************/ +#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) + +/******************************************************************************* +* Macro Name : SetEPTxStatus +* Description : sets the status for tx transfer (bits STAT_TX[1:0]). +* Input : bEpNum: Endpoint Number. +* wState: new state +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxStatus(bEpNum,wState) {\ + register u16 _wRegVal; \ + _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPTX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPTX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal); \ + } /* _SetEPTxStatus */ + +/******************************************************************************* +* Macro Name : SetEPRxStatus +* Description : sets the status for rx transfer (bits STAT_TX[1:0]) +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPRxStatus(bEpNum,wState) {\ + register u16 _wRegVal; \ + \ + _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPRX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPRX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal); \ + } /* _SetEPRxStatus */ +/******************************************************************************* +* Macro Name : GetEPTxStatus / GetEPRxStatus +* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] +* /STAT_RX[1:0]) +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : status . +*******************************************************************************/ +#define _GetEPTxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPTX_STAT) + +#define _GetEPRxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPRX_STAT) + +/******************************************************************************* +* Macro Name : SetEPTxValid / SetEPRxValid +* Description : sets directly the VALID tx/rx-status into the enpoint register +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) + +#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) + +/******************************************************************************* +* Macro Name : GetTxStallStatus / GetRxStallStatus. +* Description : checks stall condition in an endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : TRUE = endpoint in stall condition. +*******************************************************************************/ +#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \ + == EP_TX_STALL) +#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \ + == EP_RX_STALL) + +/******************************************************************************* +* Macro Name : SetEP_KIND / ClearEP_KIND. +* Description : set & clear EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)) +#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (_GetENDPOINT(bEpNum) & EPKIND_MASK))) + +/******************************************************************************* +* Macro Name : Set_Status_Out / Clear_Status_Out. +* Description : Sets/clears directly STATUS_OUT bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) +#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff. +* Description : Sets/clears directly EP_KIND bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) +#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX. +* Description : Clears bit CTR_RX / CTR_TX in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) +#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) + +/******************************************************************************* +* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX . +* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) +#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) + +/******************************************************************************* +* Macro Name : ClearDTOG_RX / ClearDTOG_TX. +* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\ + _ToggleDTOG_RX(bEpNum) +#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\ + _ToggleDTOG_TX(bEpNum) +/******************************************************************************* +* Macro Name : SetEPAddress. +* Description : Sets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* bAddr: Address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\ + (_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) + +/******************************************************************************* +* Macro Name : GetEPAddress. +* Description : Gets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPAddress(bEpNum) ((u8)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) + +#define _pEPTxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr)) +#define _pEPTxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr)) +#define _pEPRxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr)) +#define _pEPRxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr)) + +/******************************************************************************* +* Macro Name : SetEPTxAddr / SetEPRxAddr. +* Description : sets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* wAddr: address to be set (must be word aligned). +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) +#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) + +/******************************************************************************* +* Macro Name : GetEPTxAddr / GetEPRxAddr. +* Description : Gets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : address of the buffer. +*******************************************************************************/ +#define _GetEPTxAddr(bEpNum) ((u16)*_pEPTxAddr(bEpNum)) +#define _GetEPRxAddr(bEpNum) ((u16)*_pEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPCountRxReg. +* Description : Sets counter of rx buffer with no. of blocks. +* Input : pdwReg: pointer to counter. +* wCount: Counter. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _BlocksOf32(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 5;\ + if((wCount & 0x1f) == 0)\ + wNBlocks--;\ + *pdwReg = (u32)((wNBlocks << 10) | 0x8000);\ + }/* _BlocksOf32 */ + +#define _BlocksOf2(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 1;\ + if((wCount & 0x1) != 0)\ + wNBlocks++;\ + *pdwReg = (u32)(wNBlocks << 10);\ + }/* _BlocksOf2 */ + +#define _SetEPCountRxReg(dwReg,wCount) {\ + u16 wNBlocks;\ + if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\ + else {_BlocksOf2(dwReg,wCount,wNBlocks);}\ + }/* _SetEPCountRxReg */ + + + +#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\ + u32 *pdwReg = _pEPTxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + } +/******************************************************************************* +* Macro Name : SetEPTxCount / SetEPRxCount. +* Description : sets counter for the tx/rx buffer. +* Input : bEpNum: endpoint number. +* wCount: Counter value. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount) +#define _SetEPRxCount(bEpNum,wCount) {\ + u32 *pdwReg = _pEPRxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + } +/******************************************************************************* +* Macro Name : GetEPTxCount / GetEPRxCount. +* Description : gets counter of the tx buffer. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : Counter value. +*******************************************************************************/ +#define _GetEPTxCount(bEpNum)((u16)(*_pEPTxCount(bEpNum)) & 0x3ff) +#define _GetEPRxCount(bEpNum)((u16)(*_pEPRxCount(bEpNum)) & 0x3ff) + +/******************************************************************************* +* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr. +* Description : Sets buffer 0/1 address in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);} +#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);} + +/******************************************************************************* +* Macro Name : SetEPDblBuffAddr. +* Description : Sets addresses in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* : wBuf1Addr = buffer 1 address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\ + } /* _SetEPDblBuffAddr */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) +#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : bDir: endpoint dir EP_DBUF_OUT = OUT +* EP_DBUF_IN = IN +* : wCount: Counter value +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxDblBuf0Count(bEpNum,wCount);} \ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */ \ + *_pEPTxCount(bEpNum) = (u32)wCount; \ + } /* SetEPDblBuf0Count*/ + +#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxCount(bEpNum,wCount);}\ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */\ + *_pEPRxCount(bEpNum) = (u32)wCount; \ + } /* SetEPDblBuf1Count */ + +#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ + } /* _SetEPDblBuffCount */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count. +* Description : Gets buffer 0/1 rx/tx counter for double buffering. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) +#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) + + +/* External variables --------------------------------------------------------*/ +extern volatile u16 wIstr; /* ISTR register last read value */ + +/* Exported functions ------------------------------------------------------- */ +void SetCNTR(u16 /*wRegValue*/); +void SetISTR(u16 /*wRegValue*/); +void SetDADDR(u16 /*wRegValue*/); +void SetBTABLE(u16 /*wRegValue*/); +u16 GetCNTR(void); +u16 GetISTR(void); +u16 GetFNR(void); +u16 GetDADDR(void); +u16 GetBTABLE(void); +void SetENDPOINT(u8 /*bEpNum*/, u16 /*wRegValue*/); +u16 GetENDPOINT(u8 /*bEpNum*/); +void SetEPType(u8 /*bEpNum*/, u16 /*wType*/); +u16 GetEPType(u8 /*bEpNum*/); +void SetEPTxStatus(u8 /*bEpNum*/, u16 /*wState*/); +void SetEPRxStatus(u8 /*bEpNum*/, u16 /*wState*/); +void SetDouBleBuffEPStall(u8 /*bEpNum*/, u8 bDir); +u16 GetEPTxStatus(u8 /*bEpNum*/); +u16 GetEPRxStatus(u8 /*bEpNum*/); +void SetEPTxValid(u8 /*bEpNum*/); +void SetEPRxValid(u8 /*bEpNum*/); +u16 GetTxStallStatus(u8 /*bEpNum*/); +u16 GetRxStallStatus(u8 /*bEpNum*/); +void SetEP_KIND(u8 /*bEpNum*/); +void ClearEP_KIND(u8 /*bEpNum*/); +void Set_Status_Out(u8 /*bEpNum*/); +void Clear_Status_Out(u8 /*bEpNum*/); +void SetEPDoubleBuff(u8 /*bEpNum*/); +void ClearEPDoubleBuff(u8 /*bEpNum*/); +void ClearEP_CTR_RX(u8 /*bEpNum*/); +void ClearEP_CTR_TX(u8 /*bEpNum*/); +void ToggleDTOG_RX(u8 /*bEpNum*/); +void ToggleDTOG_TX(u8 /*bEpNum*/); +void ClearDTOG_RX(u8 /*bEpNum*/); +void ClearDTOG_TX(u8 /*bEpNum*/); +void SetEPAddress(u8 /*bEpNum*/, u8 /*bAddr*/); +u8 GetEPAddress(u8 /*bEpNum*/); +void SetEPTxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); +void SetEPRxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); +u16 GetEPTxAddr(u8 /*bEpNum*/); +u16 GetEPRxAddr(u8 /*bEpNum*/); +void SetEPCountRxReg(u32 * /*pdwReg*/, u16 /*wCount*/); +void SetEPTxCount(u8 /*bEpNum*/, u16 /*wCount*/); +void SetEPRxCount(u8 /*bEpNum*/, u16 /*wCount*/); +u16 GetEPTxCount(u8 /*bEpNum*/); +u16 GetEPRxCount(u8 /*bEpNum*/); +void SetEPDblBuf0Addr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/); +void SetEPDblBuf1Addr(u8 /*bEpNum*/, u16 /*wBuf1Addr*/); +void SetEPDblBuffAddr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/, u16 /*wBuf1Addr*/); +u16 GetEPDblBuf0Addr(u8 /*bEpNum*/); +u16 GetEPDblBuf1Addr(u8 /*bEpNum*/); +void SetEPDblBuffCount(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +void SetEPDblBuf0Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +void SetEPDblBuf1Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +u16 GetEPDblBuf0Count(u8 /*bEpNum*/); +u16 GetEPDblBuf1Count(u8 /*bEpNum*/); +EP_DBUF_DIR GetEPDblBufDir(u8 /*bEpNum*/); +void FreeUserBuffer(u8 bEpNum/*bEpNum*/, u8 bDir); +u16 ToWord(u8, u8); +u16 ByteSwap(u16); + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_REGS_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/libmaple/usb/usb_lib/usb_type.h b/libmaple/usb/usb_lib/usb_type.h new file mode 100644 index 0000000..34b3bf5 --- /dev/null +++ b/libmaple/usb/usb_lib/usb_type.h @@ -0,0 +1,77 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_type.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Type definitions used by the USB Library +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_TYPE_H +#define __USB_TYPE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#ifndef NULL +#define NULL ((void *)0) +#endif + +typedef signed long s32; +typedef signed short s16; +typedef signed char s8; + +typedef volatile signed long vs32; +typedef volatile signed short vs16; +typedef volatile signed char vs8; + +typedef unsigned long u32; +typedef unsigned short u16; +typedef unsigned char u8; + +typedef unsigned long const uc32; /* Read Only */ +typedef unsigned short const uc16; /* Read Only */ +typedef unsigned char const uc8; /* Read Only */ + +typedef volatile unsigned long vu32; +typedef volatile unsigned short vu16; +typedef volatile unsigned char vu8; + +typedef volatile unsigned long const vuc32; /* Read Only */ +typedef volatile unsigned short const vuc16; /* Read Only */ +typedef volatile unsigned char const vuc8; /* Read Only */ + + +typedef enum +{ + FALSE = 0, TRUE = !FALSE +} +USB_Bool; + +typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; + +typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +/* External variables --------------------------------------------------------*/ + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_TYPE_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ |