diff options
Diffstat (limited to 'os/hal')
-rw-r--r-- | os/hal/platforms/STM32/OTGv1/stm32_otg.h | 21 | ||||
-rw-r--r-- | os/hal/platforms/STM32/OTGv1/usb_lld.c | 129 | ||||
-rw-r--r-- | os/hal/platforms/STM32/OTGv1/usb_lld.h | 4 |
3 files changed, 126 insertions, 28 deletions
diff --git a/os/hal/platforms/STM32/OTGv1/stm32_otg.h b/os/hal/platforms/STM32/OTGv1/stm32_otg.h index fec44c9ad..083f868a5 100644 --- a/os/hal/platforms/STM32/OTGv1/stm32_otg.h +++ b/os/hal/platforms/STM32/OTGv1/stm32_otg.h @@ -36,6 +36,11 @@ #define STM32_OTG_ENDOPOINTS_NUMBER 3
/**
+ * @brief FIFO memory size in words.
+ */
+#define STM32_OTG_FIFO_MEM_SIZE 384
+
+/**
* @brief Host channel registers group.
*/
typedef struct {
@@ -387,6 +392,20 @@ typedef struct { /** @} */
/**
+ * @name DIEPTXFx register bit definitions
+ * @{
+ */
+#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth
+ mask. */
+#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth
+ value. */
+#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit
+ RAM start address mask. */
+#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit
+ RAM start address value. */
+/** @} */
+
+/**
* @name GCCFG register bit definitions
* @{
*/
@@ -746,7 +765,7 @@ typedef struct { #define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */
#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
-#define DIEPCTL_EPType_BULK (2U<<18) /**< Bulk. */
+#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */
#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c index be2bccee9..36ef53298 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.c +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c @@ -69,6 +69,11 @@ static union { } ep0_state;
/**
+ * @brief Buffer for the EP0 setup packets.
+ */
+static uint8_t ep8setup_buffer[8];
+
+/**
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
@@ -79,7 +84,8 @@ static const USBEndpointConfig ep0config = { 0x40,
0x40,
&ep0_state.in,
- &ep0_state.out
+ &ep0_state.out,
+ ep8setup_buffer
};
/*===========================================================================*/
@@ -114,9 +120,7 @@ static void otg_disable_ep(void) { else
OTG->ie[i].DIEPCTL = 0;
OTG->ie[i].DIEPTSIZ = 0;
- OTG->ie[i].DIEPINT = DIEPINT_INEPNE | DIEPINT_ITTXFE |
- DIEPINT_TOC | DIEPINT_EPDISD |
- DIEPINT_XFRC;
+ OTG->ie[i].DIEPINT = 0xFFFFFFFF;
/* Disable only if enabled because this sentence in the manual:
"The application must set this bit only if Endpoint Enable is
already set for this endpoint".
@@ -131,38 +135,52 @@ static void otg_disable_ep(void) { else
OTG->oe[i].DOEPCTL = 0;
OTG->oe[i].DOEPTSIZ = 0;
- OTG->oe[i].DOEPINT = DOEPINT_B2BSTUP | DOEPINT_OTEPDIS |
- DOEPINT_STUP | DOEPINT_EPDISD |
- DOEPINT_XFRC;
+ OTG->oe[i].DOEPINT = 0xFFFFFFFF;
}
}
+static void otg_rxfifo_flush(void) {
+
+ OTG->GRSTCTL = GRSTCTL_RXFFLSH;
+ while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
+ ;
+}
+
+static void otg_txfifo_flush(uint32_t fifo) {
+
+ OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
+ while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
+ ;
+}
+
/**
- * @brief Resets the packet memory allocator.
+ * @brief Resets the FIFO RAM memory allocator.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
-static void otg_pm_reset(USBDriver *usbp) {
+static void otg_ram_reset(USBDriver *usbp) {
- (void)usbp;
+ usbp->pmnext = STM32_USB_OTG1_RX_FIFO_SIZE / 4;
}
/**
- * @brief Allocates a block from the packet memory allocator.
+ * @brief Allocates a block from the FIFO RAM memory.
*
* @param[in] usbp pointer to the @p USBDriver object
- * @param[in] size size of the packet buffer to allocate
+ * @param[in] size size of the packet buffer to allocate in words
*
* @notapi
*/
-static uint32_t otg_pm_alloc(USBDriver *usbp, size_t size) {
-
- (void)usbp;
- (void)size;
+static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
+ uint32_t next;
- return 0;
+ next = usbp->pmnext;
+ usbp->pmnext += size;
+ chDbgAssert(usbp->pmnext <= STM32_OTG_FIFO_MEM_SIZE,
+ "otg_fifo_alloc(), #1", "FIFO memory overflow");
+ return next;
}
/**
@@ -475,9 +493,6 @@ void usb_lld_start(USBDriver *usbp) { /* PHY enabled.*/
OTG->PCGCCTL = 0;
- /* Receive FIFO size initialization, the address is always zero.*/
- OTG->GRXFSIZ = STM32_USB_OTG1_RX_FIFO_SIZE / 4;
-
/* Endpoints re-initialization.*/
otg_disable_ep();
@@ -537,8 +552,13 @@ void usb_lld_reset(USBDriver *usbp) { OTG->oe[i].DOEPINT = 0xFFFFFFFF;
}
- /* Resets the packet memory allocator.*/
- otg_pm_reset(usbp);
+ /* Resets the FIFO memory allocator.*/
+ otg_ram_reset(usbp);
+
+
+ /* Receive FIFO size initialization, the address is always zero.*/
+ OTG->GRXFSIZ = STM32_USB_OTG1_RX_FIFO_SIZE / 4;
+ otg_rxfifo_flush();
/* Enables also EP-related interrupt sources.*/
OTG->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM;
@@ -546,9 +566,18 @@ void usb_lld_reset(USBDriver *usbp) { OTG->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM;
// OTG->DAINTMSK = DAINTMSK_OutEpMsk(0) | DAINTMSK_InEpMsk(0);
- /* EP0 initialization.*/
+ /* EP0 initialization, it is a special case.*/
usbp->epc[0] = &ep0config;
- usb_lld_init_endpoint(usbp, 0);
+ OTG->oe[0].DOEPTSIZ = 0;
+ OTG->oe[0].DOEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL |
+ DOEPCTL_MPSIZ(ep0config.out_maxsize);
+ OTG->ie[0].DIEPTSIZ = 0;
+ OTG->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL |
+ DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize);
+ OTG->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) |
+ DIEPTXF_INEPTXSA(otg_ram_alloc(usbp,
+ ep0config.in_maxsize / 4));
+ otg_txfifo_flush(0);
}
/**
@@ -572,9 +601,51 @@ void usb_lld_set_address(USBDriver *usbp) { * @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
+ uint32_t ctl, fsize;
- (void)usbp;
- (void)ep;
+ /* IN and OUT common parameters.*/
+ switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) {
+ case USB_EP_MODE_TYPE_CTRL:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL;
+ break;
+ case USB_EP_MODE_TYPE_ISOC:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO;
+ break;
+ case USB_EP_MODE_TYPE_BULK:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK;
+ break;
+ case USB_EP_MODE_TYPE_INTR:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR;
+ break;
+ default:
+ return;
+ }
+
+ /* OUT endpoint activation or deactivation.*/
+ OTG->oe[ep].DOEPTSIZ = 0;
+ if (usbp->epc[ep]->out_cb != NULL)
+ OTG->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
+ else
+ OTG->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP;
+
+ /* IN endpoint activation or deactivation.*/
+ OTG->ie[ep].DIEPTSIZ = 0;
+ if (usbp->epc[ep]->in_cb != NULL) {
+ /* FIFO allocation for the IN endpoint.*/
+ fsize = usbp->epc[ep]->in_maxsize / 4;
+ OTG->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) |
+ DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize));
+ otg_txfifo_flush(ep);
+
+ OTG->ie[ep].DIEPCTL = ctl |
+ DIEPCTL_TXFNUM(ep) |
+ DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize);
+ }
+ else {
+ OTG->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/
+ otg_txfifo_flush(ep);
+ OTG->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP;
+ }
}
/**
@@ -586,7 +657,11 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { */
void usb_lld_disable_endpoints(USBDriver *usbp) {
- (void)usbp;
+ /* Resets the FIFO memory allocator.*/
+ otg_ram_reset(usbp);
+
+ /* Disabling all endpoints.*/
+ otg_disable_ep();
}
/**
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h index 752adbfcd..4cc18a05b 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.h +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h @@ -306,6 +306,10 @@ struct USBDriver { USB_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the next address in the packet memory.
+ */
+ uint32_t pmnext;
};
/*===========================================================================*/
|