From 200f020df922ac84ffc0e0c98c97a193e3180b1f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 5 Feb 2011 09:27:20 +0000 Subject: USB rework, step 1. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2708 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/usb.h | 4 +-- os/hal/platforms/STM32/usb_lld.c | 59 ++++++++++++++++++++++++++++------------ os/hal/platforms/STM32/usb_lld.h | 52 +++++++++++++++++++++++++++++++++-- os/hal/src/usb.c | 49 +++++++++++++++++++-------------- testhal/STM32/USB_CDC/main.c | 21 ++++++++++++-- 5 files changed, 140 insertions(+), 45 deletions(-) diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h index e6fc8b868..9f0d95837 100644 --- a/os/hal/include/usb.h +++ b/os/hal/include/usb.h @@ -313,8 +313,8 @@ extern "C" { void usbObjectInit(USBDriver *usbp); void usbStart(USBDriver *usbp, const USBConfig *config); void usbStop(USBDriver *usbp); - void usbEnableEndpointI(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp); + void usbInitEndpointI(USBDriver *usbp, usbep_t ep, USBEndpointState *epp, + const USBEndpointConfig *epcp); void _usb_reset(USBDriver *usbp); void _usb_ep0in(USBDriver *usbp, usbep_t ep); void _usb_ep0out(USBDriver *usbp, usbep_t ep); diff --git a/os/hal/platforms/STM32/usb_lld.c b/os/hal/platforms/STM32/usb_lld.c index 91be0f625..3fe6771ea 100644 --- a/os/hal/platforms/STM32/usb_lld.c +++ b/os/hal/platforms/STM32/usb_lld.c @@ -25,6 +25,8 @@ * @{ */ +#include + #include "ch.h" #include "hal.h" #include "usb.h" @@ -42,10 +44,20 @@ USBDriver USBD1; #endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + */ +static USBEndpointState ep0state; + /** * @brief EP0 initialization structure. */ -const USBEndpointConfig usb_lld_ep0config = { +static const USBEndpointConfig ep0config = { _usb_ep0in, _usb_ep0out, 0x40, @@ -55,10 +67,6 @@ const USBEndpointConfig usb_lld_ep0config = { 0x80 }; -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -112,18 +120,19 @@ CH_IRQ_HANDLER(USB_LP_IRQHandler) { while (istr & ISTR_CTR) { uint32_t ep; uint32_t epr = STM32_USB->EPR[ep = istr & ISTR_EP_ID_MASK]; + const USBEndpointConfig *epcp = usbp->usb_ep[ep]->uep_config; if (epr & EPR_CTR_TX) { /* IN endpoint, transmission.*/ EPR_CLEAR_CTR_TX(ep); - if (usbp->usb_epc[ep]->uepc_in_cb) - usbp->usb_epc[ep]->uepc_in_cb(usbp, ep); + if (epcp->uepc_in_cb) + epcp->uepc_in_cb(usbp, ep); } if (epr & EPR_CTR_RX) { /* OUT endpoint, receive.*/ EPR_CLEAR_CTR_RX(ep); - if (usbp->usb_epc[ep]->uepc_out_cb) - usbp->usb_epc[ep]->uepc_out_cb(usbp, ep); + if (epcp->uepc_out_cb) + epcp->uepc_out_cb(usbp, ep); } istr = STM32_USB->ISTR; } @@ -228,6 +237,12 @@ void usb_lld_reset(USBDriver *usbp) { if (usbp->usb_config->uc_sof_cb != NULL) cntr |= CNTR_SOFM; STM32_USB->CNTR = cntr; + + /* EP0 initialization.*/ + memset(&ep0state, 0, sizeof ep0state); + ep0state.uep_config = &ep0config; + usbp->usb_ep[0] = &ep0state; + usb_lld_init_endpoint(usbp, 0); } /** @@ -240,6 +255,7 @@ void usb_lld_reset(USBDriver *usbp) { */ void usb_lld_set_address(USBDriver *usbp, uint8_t addr) { + (void)usbp; STM32_USB->DADDR = (uint32_t)addr | DADDR_EF; } @@ -248,14 +264,13 @@ void usb_lld_set_address(USBDriver *usbp, uint8_t addr) { * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number - * @param[in] epcp the endpoint configuration * * @notapi */ -void usb_lld_enable_endpoint(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp) { +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { uint16_t nblocks; stm32_usb_descriptor_t *dp; + const USBEndpointConfig *epcp = usbp->usb_ep[ep]->uep_config; /* EPxR register setup.*/ EPR_SET(ep, epcp->uepc_epr | ep); @@ -263,7 +278,8 @@ void usb_lld_enable_endpoint(USBDriver *usbp, usbep_t ep, /* Endpoint size and address initialization.*/ if (epcp->uepc_out_maxsize > 62) - nblocks = (((((epcp->uepc_out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | 0x8000; + nblocks = (((((epcp->uepc_out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | + 0x8000; else nblocks = ((((epcp->uepc_out_maxsize - 1) | 1) + 1) / 2) << 10; dp = USB_GET_DESCRIPTOR(ep); @@ -271,9 +287,6 @@ void usb_lld_enable_endpoint(USBDriver *usbp, usbep_t ep, dp->RXCOUNT = nblocks; dp->TXADDR = epcp->uepc_inaddr; dp->RXADDR = epcp->uepc_outaddr; - - /* Logically enabling the endpoint in the USBDriver structure.*/ - usbp->usb_epc[ep] = epcp; } /** @@ -286,6 +299,7 @@ void usb_lld_enable_endpoint(USBDriver *usbp, usbep_t ep, void usb_lld_disable_endpoints(USBDriver *usbp) { unsigned i; + (void)usbp; for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { EPR_TOGGLE(i, 0); EPR_SET(i, 0); @@ -306,6 +320,7 @@ void usb_lld_disable_endpoints(USBDriver *usbp) { */ size_t usb_lld_get_readable(USBDriver *usbp, usbep_t ep) { + (void)usbp; if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_NAK) return 0; return (size_t)(USB_GET_DESCRIPTOR(ep)->RXCOUNT & RXCOUNT_COUNT_MASK); @@ -331,6 +346,7 @@ size_t usb_lld_read(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { stm32_usb_descriptor_t *udp; size_t count; + (void)usbp; if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_NAK) return 0; @@ -363,7 +379,7 @@ size_t usb_lld_get_writeable(USBDriver *usbp, usbep_t ep) { if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_NAK) return 0; - return (size_t)usbp->usb_epc[ep]->uepc_in_maxsize; + return (size_t)usbp->usb_ep[ep]->uep_config->uepc_in_maxsize; } /** @@ -388,6 +404,7 @@ size_t usb_lld_write(USBDriver *usbp, usbep_t ep, stm32_usb_descriptor_t *udp; size_t count; + (void)usbp; if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_NAK) return 0; @@ -414,6 +431,7 @@ size_t usb_lld_write(USBDriver *usbp, usbep_t ep, */ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) { case EPR_STAT_TX_DIS: return EP_STATUS_DISABLED; @@ -434,6 +452,7 @@ 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)usbp; switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) { case EPR_STAT_RX_DIS: return EP_STATUS_DISABLED; @@ -454,6 +473,7 @@ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { */ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL); } @@ -467,6 +487,7 @@ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { */ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); } @@ -480,6 +501,8 @@ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { */ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + /* Makes sure to not put to NAK an endpoint that is already transferring.*/ if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID) @@ -496,6 +519,8 @@ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { */ void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + /* Makes sure to not put to NAK an endpoint that is already transferring.*/ if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID) diff --git a/os/hal/platforms/STM32/usb_lld.h b/os/hal/platforms/STM32/usb_lld.h index af306d8a5..e21bbecd2 100644 --- a/os/hal/platforms/STM32/usb_lld.h +++ b/os/hal/platforms/STM32/usb_lld.h @@ -125,6 +125,49 @@ typedef struct { uint16_t uepc_outaddr; } USBEndpointConfig; + +/** + * @brief Type of an endpoint state structure. + */ +typedef struct { + /** + * @brief Configuration associated to the endpoint. + */ + const USBEndpointConfig *uep_config; + /** + * @brief Pointer to the transmission buffer. + */ + const uint8_t *uep_txbuf; + /** + * @brief Pointer to the receive buffer. + */ + uint8_t *uep_rxbuf; + /** + * @brief Requested transmit transfer size. + */ + size_t uep_txsize; + /** + * @brief Requested receive transfer size. + */ + size_t uep_rxsize; + /** + * @brief Transmitted bytes so far. + */ + size_t uep_txcnt; + /** + * @brief Received bytes so far. + */ + size_t uep_rxcnt; + /** + * @brief @p TRUE if transmitting else @p FALSE. + */ + uint8_t uep_transmitting; + /** + * @brief @p TRUE if receiving else @p FALSE. + */ + uint8_t uep_receiving; +} USBEndpointState; + /** * @brief Type of an USB driver configuration structure. */ @@ -172,7 +215,7 @@ struct USBDriver { /** * @brief Active endpoints configurations. */ - const USBEndpointConfig *usb_epc[USB_MAX_ENDPOINTS + 1]; + USBEndpointState *usb_ep[USB_MAX_ENDPOINTS + 1]; /** * @brief Endpoint 0 state. */ @@ -251,6 +294,10 @@ extern USBDriver USBD1; extern const USBEndpointConfig usb_lld_ep0config; #endif +#if !defined(__DOXYGEN__) +extern USBEndpointState usb_lld_ep0state; +#endif + #ifdef __cplusplus extern "C" { #endif @@ -259,8 +306,7 @@ extern "C" { void usb_lld_stop(USBDriver *usbp); void usb_lld_reset(USBDriver *usbp); void usb_lld_set_address(USBDriver *usbp, uint8_t addr); - void usb_lld_enable_endpoint(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); void usb_lld_disable_endpoints(USBDriver *usbp); size_t usb_lld_get_readable(USBDriver *usbp, usbep_t ep); size_t usb_lld_read(USBDriver *usbp, usbep_t ep, diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index c89d5a8e9..3cc076443 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -25,6 +25,8 @@ * @{ */ +#include + #include "ch.h" #include "hal.h" #include "usb.h" @@ -75,8 +77,8 @@ static void start_rx_ep0(USBDriver *usbp) { /* Determines the maximum amount that can be received using a single packet.*/ - if (usbp->usb_ep0n > usb_lld_ep0config.uepc_out_maxsize) - usbp->usb_ep0lastsize = usb_lld_ep0config.uepc_out_maxsize; + if (usbp->usb_ep0n > usbp->usb_ep[0]->uep_config->uepc_out_maxsize) + usbp->usb_ep0lastsize = usbp->usb_ep[0]->uep_config->uepc_out_maxsize; else usbp->usb_ep0lastsize = usbp->usb_ep0n; usbp->usb_ep0state = USB_EP0_RX; @@ -102,8 +104,8 @@ static void start_tx_ep0(USBDriver *usbp) { /* Determines the maximum amount that can be transmitted using a single packet.*/ - if (usbp->usb_ep0n > usb_lld_ep0config.uepc_in_maxsize) - usbp->usb_ep0lastsize = usb_lld_ep0config.uepc_in_maxsize; + if (usbp->usb_ep0n > usbp->usb_ep[0]->uep_config->uepc_in_maxsize) + usbp->usb_ep0lastsize = usbp->usb_ep[0]->uep_config->uepc_in_maxsize; else usbp->usb_ep0lastsize = usbp->usb_ep0n; @@ -294,14 +296,16 @@ void usbObjectInit(USBDriver *usbp) { * @api */ void usbStart(USBDriver *usbp, const USBConfig *config) { + unsigned i; chDbgCheck((usbp != NULL) && (config != NULL), "usbStart"); chSysLock(); chDbgAssert((usbp->usb_state == USB_STOP) || (usbp->usb_state == USB_READY), - "usbStart(), #1", - "invalid state"); + "usbStart(), #1", "invalid state"); usbp->usb_config = config; + for (i = 0; i <= USB_MAX_ENDPOINTS; i++) + usbp->usb_ep[i] = NULL; usb_lld_start(usbp); usbp->usb_state = USB_READY; chSysUnlock(); @@ -336,23 +340,26 @@ void usbStop(USBDriver *usbp) { * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number + * @param[out] epp pointer to an endpoint state descriptor structure * @param[in] epcp the endpoint configuration * * @iclass */ -void usbEnableEndpointI(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp) { +void usbInitEndpointI(USBDriver *usbp, usbep_t ep, USBEndpointState *epp, + const USBEndpointConfig *epcp) { chDbgAssert(usbp->usb_state == USB_ACTIVE, "usbEnableEndpointI(), #1", "invalid state"); - chDbgAssert(usbp->usb_epc[ep] != NULL, - "usbEnableEndpointI(), #2", "already enabled"); + chDbgAssert(usbp->usb_ep[ep] != NULL, + "usbEnableEndpointI(), #2", "already initialized"); /* Logically enabling the endpoint in the USBDriver structure.*/ - usbp->usb_epc[ep] = epcp; + memset(epp, 0, sizeof(USBEndpointState)); + epp->uep_config = epcp; + usbp->usb_ep[ep] = epp; /* Low level endpoint activation.*/ - usb_lld_enable_endpoint(usbp, ep, epcp); + usb_lld_init_endpoint(usbp, ep); } /** @@ -373,7 +380,7 @@ void usbDisableEndpointsI(USBDriver *usbp) { "usbDisableEndpointsI(), #1", "invalid state"); for (i = 1; i <= USB_MAX_ENDPOINTS; i++) - usbp->usb_epc[i] = NULL; + usbp->usb_ep[i] = NULL; /* Low level endpoints deactivation.*/ usb_lld_disable_endpoints(usbp); @@ -396,7 +403,7 @@ void _usb_reset(USBDriver *usbp) { /* Invalidates all endpoints into the USBDriver structure.*/ for (i = 0; i <= USB_MAX_ENDPOINTS; i++) - usbp->usb_epc[i] = NULL; + usbp->usb_ep[i] = NULL; /* EP0 state machine initialization.*/ usbp->usb_ep0state = USB_EP0_WAITING_SETUP; @@ -404,9 +411,9 @@ void _usb_reset(USBDriver *usbp) { /* Low level reset.*/ usb_lld_reset(usbp); - /* Low level endpoint zero activation.*/ - usbp->usb_epc[0] = &usb_lld_ep0config; - usb_lld_enable_endpoint(usbp, 0, &usb_lld_ep0config); + /* Endpoint zero initialization.*/ +/* usbp->usb_ep[0].uep_config = &usb_lld_ep0config; + usb_lld_init_endpoint(usbp, 0, &usb_lld_ep0config);*/ } /** @@ -432,11 +439,13 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { when a packet has been sent with size less than the maximum packet size.*/ if ((usbp->usb_ep0max == 0) || - (usbp->usb_ep0lastsize < usb_lld_ep0config.uepc_in_maxsize)) + (usbp->usb_ep0lastsize < usbp->usb_ep[0]->uep_config->uepc_in_maxsize)) usbp->usb_ep0state = USB_EP0_WAITING_STS; else { - usbp->usb_ep0lastsize = usbp->usb_ep0n > usb_lld_ep0config.uepc_in_maxsize ? - usb_lld_ep0config.uepc_in_maxsize : usbp->usb_ep0n; + usbp->usb_ep0lastsize = + usbp->usb_ep0n > usbp->usb_ep[0]->uep_config->uepc_in_maxsize ? + usbp->usb_ep[0]->uep_config->uepc_in_maxsize : + usbp->usb_ep0n; usb_lld_write(usbp, 0, usbp->usb_ep0next, usbp->usb_ep0lastsize); } return; diff --git a/testhal/STM32/USB_CDC/main.c b/testhal/STM32/USB_CDC/main.c index 943edbb05..70a27a8f2 100644 --- a/testhal/STM32/USB_CDC/main.c +++ b/testhal/STM32/USB_CDC/main.c @@ -232,6 +232,21 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, return NULL; } +/** + * @brief EP1 state. + */ +USBEndpointState ep1state; + +/** + * @brief EP2 state. + */ +USBEndpointState ep2state; + +/** + * @brief EP3 state. + */ +USBEndpointState ep3state; + /** * @brief EP1 initialization structure (IN only). */ @@ -284,9 +299,9 @@ static void usb_event(USBDriver *usbp, usbevent_t event) { case USB_EVENT_CONFIGURED: /* Enables the endpoints specified into the configuration.*/ chSysLock(); - usbEnableEndpointI(usbp, DATA_REQUEST_EP, &ep1config); - usbEnableEndpointI(usbp, INTERRUPT_REQUEST_EP, &ep2config); - usbEnableEndpointI(usbp, DATA_AVAILABLE_EP, &ep3config); + usbInitEndpointI(usbp, DATA_REQUEST_EP, &ep1state, &ep1config); + usbInitEndpointI(usbp, INTERRUPT_REQUEST_EP, &ep2state, &ep2config); + usbInitEndpointI(usbp, DATA_AVAILABLE_EP, &ep3state, &ep3config); chSysUnlock(); return; case USB_EVENT_SUSPEND: -- cgit v1.2.3