From f153a37e010fb829291766a1add5ca6e2ba06c52 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 26 Mar 2012 13:45:36 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4057 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/OTGv1/usb_lld.c | 444 +++++++++++++++++++++++++++++++++ os/hal/platforms/STM32/OTGv1/usb_lld.h | 358 ++++++++++++++++++++++++++ 2 files changed, 802 insertions(+) create mode 100644 os/hal/platforms/STM32/OTGv1/usb_lld.c create mode 100644 os/hal/platforms/STM32/OTGv1/usb_lld.h (limited to 'os/hal/platforms') diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c new file mode 100644 index 000000000..177f80e14 --- /dev/null +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c @@ -0,0 +1,444 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file STM32/OTGv1/usb_lld.c + * @brief STM32 USB subsystem low level driver source. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief OTG1 driver identifier.*/ +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note It is an union because IN and OUT endpoints are never used at the + * same time for EP0. + */ +static union { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL | USB_EP_MODE_TRANSACTION, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 0x40, + 0x40, + &ep0_state.in, + &ep0_state.out +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Resets the RX FIFO memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + */ +static void rxfifo_reset(USBDriver *usbp) { + +} + +/** + * @brief Resets the RX FIFO memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size size of the packet buffer to allocate + */ +static uint32_t rxfifo_alloc(USBDriver *usbp, size_t size) { + + return 0; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +/** + * @brief OTG1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(OTG_FS_IRQHandler) { + + CH_IRQ_PROLOGUE(); + + CH_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + + /* Driver initialization.*/ + usbObjectInit(&USBD1); +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + + if (usbp->state == USB_STOP) { + /* Clock activation.*/ +#if STM32_USB_USE_OTG1 + if (&USBD1 == usbp) { + /* USB clock enabled.*/ + rccEnableOTG1(FALSE); + /* Enables IRQ vector.*/ + nvicEnableVector(OTG_FS_IRQn, + CORTEX_PRIORITY_MASK(STM32_USB_OTG1_IRQ_PRIORITY)); + } +#endif + /* Reset procedure enforced on driver start.*/ + _usb_reset(usbp); + } + /* Configuration.*/ +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + + /* If in ready state then disables the USB clock.*/ + if (usbp->state == USB_STOP) { +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { + nvicDisableVector(OTG_FS_IRQn); + rccDisableOTG1(FALSE); + } +#endif + } +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + uint32_t cntr; + + /* Post reset initialization.*/ + + /* Resets the packet memory allocator.*/ + rxfifo_reset(usbp); + + /* EP0 initialization.*/ + usbp->epc[0] = &ep0config; + usb_lld_init_endpoint(usbp, 0); +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + +} + +/** + * @brief Reads from a dedicated packet buffer. + * @pre In order to use this function he endpoint must have been + * initialized in packet mode. + * @note This function can be invoked both in thread and IRQ context. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * @return The received packet size regardless the specified + * @p n parameter. + * @retval 0 Zero size packet received. + * + * @notapi + */ +size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { + + return 0; +} + +/** + * @brief Writes to a dedicated packet buffer. + * @pre In order to use this function he endpoint must have been + * initialized in packet mode. + * @note This function can be invoked both in thread and IRQ context. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { + +} + +/** + * @brief Prepares for a receive operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the received data + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { + +} + +/** + * @brief Prepares for a transmit operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the data to be transmitted + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { + +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h new file mode 100644 index 000000000..cf5c0c628 --- /dev/null +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h @@ -0,0 +1,358 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file STM32/OTGv1/usb_lld.h + * @brief STM32 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef _USB_LLD_H_ +#define _USB_LLD_H_ + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "stm32_usb.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#define USB_MAX_ENDPOINTS 3 + +/** + * @brief The address can be changed immediately upon packet reception. + */ +#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief OTG1 driver enable switch. + * @details If set to @p TRUE the support for USB1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__) +#define STM32_USB_USE_OTG1 TRUE +#endif + +/** + * @brief OTG1 interrupt priority level setting. + */ +#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_OTG1_IRQ_PRIORITY 6 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1 +#error "OTG1 not present in the selected device" +#endif + +#if !STM32_USB_USE_OTG1 +#error "USB driver activated but no USB peripheral assigned" +#endif + +//#if STM32_USBCLK != 48000000 +//#error "the USB driver requires a 48MHz clock" +//#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an endpoint state structure. + */ +typedef struct { + /** + * @brief Pointer to the transmission buffer. + */ + const uint8_t *txbuf; + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; +} USBInEndpointState; + +/** + * @brief Type of an endpoint state structure. + */ +typedef struct { + /** + * @brief Number of packets to receive. + */ + uint16_t rxpkts; + /** + * @brief Pointer to the receive buffer. + */ + uint8_t *rxbuf; + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not + * used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not + * used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This structure maintains the state of the IN endpoint when + * the endpoint is not in packet mode. Endpoints configured in + * packet mode must set this field to @p NULL. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This structure maintains the state of the OUT endpoint when + * the endpoint is not in packet mode. Endpoints configured in + * packet mode must set this field to @p NULL. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Field available to user, it can be used to associate an + * application-defined handler to the USB driver. + */ + void *param; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Fetches a 16 bits word value from an USB message. + * + * @param[in] p pointer to the 16 bits word + * + * @notapi + */ +#define usb_lld_fetch_word(p) (*(uint16_t *)(p)) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); + void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* _USB_LLD_H_ */ + +/** @} */ -- cgit v1.2.3