/** * @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) { unsigned i; /* Resets the packet memory allocator.*/ usb_pm_reset(usbp); /* Disabling all endpoints.*/ for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { EPR_TOGGLE(i, 0); EPR_SET(i, 0); } }
/** * @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) { uint16_t nblocks, epr; stm32_usb_descriptor_t *dp; const USBEndpointConfig *epcp = usbp->epc[ep]; /* Setting the endpoint type.*/ switch (epcp->ep_mode & USB_EP_MODE_TYPE) { case USB_EP_MODE_TYPE_ISOC: epr = EPR_EP_TYPE_ISO; break; case USB_EP_MODE_TYPE_BULK: epr = EPR_EP_TYPE_BULK; break; case USB_EP_MODE_TYPE_INTR: epr = EPR_EP_TYPE_INTERRUPT; break; default: epr = EPR_EP_TYPE_CONTROL; } /* IN endpoint settings, always in NAK mode initially.*/ if (epcp->in_cb != NULL) epr |= EPR_STAT_TX_NAK; /* OUT endpoint settings. If the endpoint is in packet mode then it must start ready to accept data else it must start in NAK mode.*/ if (epcp->out_cb != NULL) { if (epcp->ep_mode & USB_EP_MODE_PACKET) { usbp->receiving |= (1 << ep); epr |= EPR_STAT_RX_VALID; } else epr |= EPR_STAT_RX_NAK; } /* EPxR register setup.*/ EPR_SET(ep, epr | ep); EPR_TOGGLE(ep, epr); /* Endpoint size and address initialization.*/ if (epcp->out_maxsize > 62) nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | 0x8000; else nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; dp = USB_GET_DESCRIPTOR(ep); dp->TXCOUNT = 0; dp->RXCOUNT = nblocks; dp->TXADDR = pm_alloc(usbp, epcp->in_maxsize); dp->RXADDR = pm_alloc(usbp, epcp->out_maxsize); }
/** * @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) { uint16_t nblocks, epr; stm32_usb_descriptor_t *dp; const USBEndpointConfig *epcp = usbp->epc[ep]; /* Setting the endpoint type.*/ switch (epcp->ep_mode & USB_EP_MODE_TYPE) { case USB_EP_MODE_TYPE_ISOC: epr = EPR_EP_TYPE_ISO; break; case USB_EP_MODE_TYPE_BULK: epr = EPR_EP_TYPE_BULK; break; case USB_EP_MODE_TYPE_INTR: epr = EPR_EP_TYPE_INTERRUPT; break; default: epr = EPR_EP_TYPE_CONTROL; } /* IN endpoint initially in NAK mode.*/ if (epcp->in_cb != NULL) epr |= EPR_STAT_TX_NAK; /* OUT endpoint initially in NAK mode.*/ if (epcp->out_cb != NULL) epr |= EPR_STAT_RX_NAK; /* EPxR register setup.*/ EPR_SET(ep, epr | ep); EPR_TOGGLE(ep, epr); /* Endpoint size and address initialization.*/ if (epcp->out_maxsize > 62) nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | 0x8000; else nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; dp = USB_GET_DESCRIPTOR(ep); dp->TXCOUNT0 = 0; dp->RXCOUNT0 = nblocks; dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); }
/** * @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) { uint16_t epr; stm32_usb_descriptor_t *dp; const USBEndpointConfig *epcp = usbp->epc[ep]; /* Setting the endpoint type. Note that isochronous endpoints cannot be bidirectional because it uses double buffering and both transmit and receive descriptor fields are used for either direction.*/ switch (epcp->ep_mode & USB_EP_MODE_TYPE) { case USB_EP_MODE_TYPE_ISOC: #if STM32_USB_USE_ISOCHRONOUS osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL), "isochronous EP cannot be IN and OUT"); epr = EPR_EP_TYPE_ISO; break; #else osalDbgAssert(false, "isochronous support disabled"); #endif /* Falls through.*/ case USB_EP_MODE_TYPE_BULK: epr = EPR_EP_TYPE_BULK; break; case USB_EP_MODE_TYPE_INTR: epr = EPR_EP_TYPE_INTERRUPT; break; default: epr = EPR_EP_TYPE_CONTROL; } dp = USB_GET_DESCRIPTOR(ep); /* IN endpoint handling.*/ if (epcp->in_state != NULL) { dp->TXCOUNT0 = 0; dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); #if STM32_USB_USE_ISOCHRONOUS if (epr == EPR_EP_TYPE_ISO) { epr |= EPR_STAT_TX_VALID; dp->TXCOUNT1 = dp->TXCOUNT0; dp->TXADDR1 = dp->TXADDR0; /* Both buffers overlapped.*/ } else { epr |= EPR_STAT_TX_NAK; } #else epr |= EPR_STAT_TX_NAK; #endif } /* OUT endpoint handling.*/ if (epcp->out_state != NULL) { uint16_t nblocks; /* Endpoint size and address initialization.*/ if (epcp->out_maxsize > 62) nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | 0x8000; else nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; dp->RXCOUNT0 = nblocks; dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); #if STM32_USB_USE_ISOCHRONOUS if (epr == EPR_EP_TYPE_ISO) { epr |= EPR_STAT_RX_VALID; dp->RXCOUNT1 = dp->RXCOUNT0; dp->RXADDR1 = dp->RXADDR0; /* Both buffers overlapped.*/ } else { epr |= EPR_STAT_RX_NAK; } #else epr |= EPR_STAT_RX_NAK; #endif } /* EPxR register setup.*/ EPR_SET(ep, epr | ep); EPR_TOGGLE(ep, epr); }
/** * @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) { uint16_t nblocks, epr; stm32_usb_descriptor_t *dp; const USBEndpointConfig *epcp = usbp->epc[ep]; /* Setting the endpoint type. Note that isochronous endpoints cannot be bidirectional because it uses double buffering and both transmit and receive descriptor fields are used for either direction.*/ switch (epcp->ep_mode & USB_EP_MODE_TYPE) { case USB_EP_MODE_TYPE_ISOC: osalDbgAssert((epcp->in_cb == NULL) || (epcp->out_cb == NULL), "isochronous EP cannot be IN and OUT"); epr = EPR_EP_TYPE_ISO; break; case USB_EP_MODE_TYPE_BULK: epr = EPR_EP_TYPE_BULK; break; case USB_EP_MODE_TYPE_INTR: epr = EPR_EP_TYPE_INTERRUPT; break; default: epr = EPR_EP_TYPE_CONTROL; } /* Endpoint size and address initialization.*/ if (epcp->out_maxsize > 62) nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | 0x8000; else nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; dp = USB_GET_DESCRIPTOR(ep); dp->TXCOUNT0 = 0; dp->RXCOUNT0 = nblocks; dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); /* Initial status for isochronous enpoints is valid because disabled and valid are the only legal values. Also since double buffering is used we need to initialize both count/address sets depending on the direction, but since we are not taking advantage of the double buffering, we set both addresses to point to the same PMA.*/ if ((epcp->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { if (epcp->in_cb != NULL) { epr |= EPR_STAT_TX_VALID; dp->TXCOUNT1 = dp->TXCOUNT0; dp->TXADDR1 = dp->TXADDR0; /* Both buffers overlapped.*/ } if (epcp->out_cb != NULL) { epr |= EPR_STAT_RX_VALID; dp->RXCOUNT1 = dp->RXCOUNT0; dp->RXADDR1 = dp->RXADDR0; /* Both buffers overlapped.*/ } } else { /* Initial status for other endpoint types is NAK.*/ if (epcp->in_cb != NULL) epr |= EPR_STAT_TX_NAK; if (epcp->out_cb != NULL) epr |= EPR_STAT_RX_NAK; } /* EPxR register setup.*/ EPR_SET(ep, epr | ep); EPR_TOGGLE(ep, epr); }