From 39877047bb484d673ac56cce77fa5214df0aa939 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 2 May 2015 06:30:19 -0600 Subject: [PATCH 1/4] LPC17 GPIO: Reorder steps when an output GPIO is configured in order to avoid transient bad values from being output. From Hal Glenn. --- arch/arm/src/lpc17xx/lpc176x_gpio.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/lpc17xx/lpc176x_gpio.c b/arch/arm/src/lpc17xx/lpc176x_gpio.c index 545b146449..f3231691d6 100644 --- a/arch/arm/src/lpc17xx/lpc176x_gpio.c +++ b/arch/arm/src/lpc17xx/lpc176x_gpio.c @@ -479,13 +479,6 @@ static inline int lpc17_configoutput(lpc17_pinset_t cfgset, unsigned int port, (void)lpc17_configinput(DEFAULT_INPUT, port, pin); - /* Now, reconfigure the pin as an output */ - - fiobase = g_fiobase[port]; - regval = getreg32(fiobase + LPC17_FIO_DIR_OFFSET); - regval |= (1 << pin); - putreg32(regval, fiobase + LPC17_FIO_DIR_OFFSET); - /* Check for open drain output */ if ((cfgset & GPIO_OPEN_DRAIN) != 0) @@ -505,6 +498,14 @@ static inline int lpc17_configoutput(lpc17_pinset_t cfgset, unsigned int port, lpc17_gpiowrite(cfgset, ((cfgset & GPIO_VALUE) != GPIO_VALUE_ZERO)); + /* Now, reconfigure the pin as an output */ + + fiobase = g_fiobase[port]; + regval = getreg32(fiobase + LPC17_FIO_DIR_OFFSET); + regval |= (1 << pin); + putreg32(regval, fiobase + LPC17_FIO_DIR_OFFSET); + + return OK; } From 0577a54d1891dd83007b18158c0fe753d4bb130b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 2 May 2015 06:32:22 -0600 Subject: [PATCH 2/4] Update ChangeLog --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 39f9fde997..9498912f4e 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10269,3 +10269,6 @@ stm32f37xxx_memorymap.h: Added missing EXTI definitions for the STM32 F3; Correct an error the port D base address in the STM32 F30x and F37x memory maps. From Greg Meiste (2015-05-01). + * arch/arm/src/lpc17xx/lpc176x_gpio.c: Reorder steps when an output + GPIO is configured in order to avoid transient bad values from being + output. From Hal Glenn (2015-05-02). From def19bad484806b67c34b10f0d55cc23792c20c3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 2 May 2015 10:58:27 -0600 Subject: [PATCH 3/4] STM32 USB device. Add protection in the event that out-of-bound enpoint numbers are received. From David Sidrane. --- arch/arm/src/stm32/stm32_otgfsdev.c | 246 ++++++++++++++-------------- arch/arm/src/stm32/stm32_otghsdev.c | 246 ++++++++++++++-------------- 2 files changed, 250 insertions(+), 242 deletions(-) diff --git a/arch/arm/src/stm32/stm32_otgfsdev.c b/arch/arm/src/stm32/stm32_otgfsdev.c index 35c8ab821c..e5e9946fb6 100644 --- a/arch/arm/src/stm32/stm32_otgfsdev.c +++ b/arch/arm/src/stm32/stm32_otgfsdev.c @@ -3124,132 +3124,136 @@ static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv) /* Decode status fields */ epphy = (regval & OTGFS_GRXSTSD_EPNUM_MASK) >> OTGFS_GRXSTSD_EPNUM_SHIFT; - privep = &priv->epout[epphy]; - /* Handle the RX event according to the packet status field */ - - switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK) + if (epphy < STM32_NENDPOINTS) { - /* Global OUT NAK. This indicate that the global OUT NAK bit has taken - * effect. - * - * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't - * Care. - */ + privep = &priv->epout[epphy]; - case OTGFS_GRXSTSD_PKTSTS_OUTNAK: + /* Handle the RX event according to the packet status field */ + + switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK) { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0); + /* Global OUT NAK. This indicate that the global OUT NAK bit has taken + * effect. + * + * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't + * Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTNAK: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0); + } + break; + + /* OUT data packet received. + * + * PKTSTS = DataOUT, BCNT = size of the received data OUT packet, + * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTRECVD: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy); + bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT; + if (bcnt > 0) + { + stm32_epout_receive(privep, bcnt); + } + } + break; + + /* OUT transfer completed. This indicates that an OUT data transfer for + * the specified OUT endpoint has completed. After this entry is popped + * from the receive FIFO, the core asserts a Transfer Completed interrupt + * on the specified OUT endpoint. + * + * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on + * which the data transfer is complete, DPID = Don't Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_OUTDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy); + } + break; + + /* SETUP transaction completed. This indicates that the Setup stage for + * the specified endpoint has completed and the Data stage has started. + * After this entry is popped from the receive FIFO, the core asserts a + * Setup interrupt on the specified control OUT endpoint (triggers an + * interrupt). + * + * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num, + * DPID = Don't Care. + */ + + case OTGFS_GRXSTSD_PKTSTS_SETUPDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy); + } + break; + + /* SETUP data packet received. This indicates that a SETUP packet for the + * specified endpoint is now available for reading from the receive FIFO. + * + * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0. + */ + + case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD: + { + uint16_t datlen; + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy); + + /* Read EP0 setup data. NOTE: If multiple SETUP packets are received, + * the last one overwrites the previous setup packets and only that + * last SETUP packet will be processed. + */ + + stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq, + USB_SIZEOF_CTRLREQ); + + /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP, + * then we need to wait for the completion of the data phase to + * process the setup command. If it is an IN SETUP packet, then + * we must processing the command BEFORE we enter the DATA phase. + * + * If the data associated with the OUT SETUP packet is zero length, + * then, of course, we don't need to wait. + */ + + datlen = GETUINT16(priv->ctrlreq.len); + if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0) + { + /* Clear NAKSTS so that we can receive the data */ + + regval = stm32_getreg(STM32_OTGFS_DOEPCTL0); + regval |= OTGFS_DOEPCTL0_CNAK; + stm32_putreg(regval, STM32_OTGFS_DOEPCTL0); + + /* Wait for the data phase. */ + + priv->ep0state = EP0STATE_SETUP_OUT; + } + else + { + /* We can process the setup data as soon as SETUP done word is + * popped of the RxFIFO. + */ + + priv->ep0state = EP0STATE_SETUP_READY; + } + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), + (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT); + } + break; } - break; - - /* OUT data packet received. - * - * PKTSTS = DataOUT, BCNT = size of the received data OUT packet, - * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID. - */ - - case OTGFS_GRXSTSD_PKTSTS_OUTRECVD: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy); - bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT; - if (bcnt > 0) - { - stm32_epout_receive(privep, bcnt); - } - } - break; - - /* OUT transfer completed. This indicates that an OUT data transfer for - * the specified OUT endpoint has completed. After this entry is popped - * from the receive FIFO, the core asserts a Transfer Completed interrupt - * on the specified OUT endpoint. - * - * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on - * which the data transfer is complete, DPID = Don't Care. - */ - - case OTGFS_GRXSTSD_PKTSTS_OUTDONE: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy); - } - break; - - /* SETUP transaction completed. This indicates that the Setup stage for - * the specified endpoint has completed and the Data stage has started. - * After this entry is popped from the receive FIFO, the core asserts a - * Setup interrupt on the specified control OUT endpoint (triggers an - * interrupt). - * - * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num, - * DPID = Don't Care. - */ - - case OTGFS_GRXSTSD_PKTSTS_SETUPDONE: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy); - } - break; - - /* SETUP data packet received. This indicates that a SETUP packet for the - * specified endpoint is now available for reading from the receive FIFO. - * - * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0. - */ - - case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD: - { - uint16_t datlen; - - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy); - - /* Read EP0 setup data. NOTE: If multiple SETUP packets are received, - * the last one overwrites the previous setup packets and only that - * last SETUP packet will be processed. - */ - - stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq, - USB_SIZEOF_CTRLREQ); - - /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP, - * then we need to wait for the completion of the data phase to - * process the setup command. If it is an IN SETUP packet, then - * we must processing the command BEFORE we enter the DATA phase. - * - * If the data associated with the OUT SETUP packet is zero length, - * then, of course, we don't need to wait. - */ - - datlen = GETUINT16(priv->ctrlreq.len); - if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0) - { - /* Clear NAKSTS so that we can receive the data */ - - regval = stm32_getreg(STM32_OTGFS_DOEPCTL0); - regval |= OTGFS_DOEPCTL0_CNAK; - stm32_putreg(regval, STM32_OTGFS_DOEPCTL0); - - /* Wait for the data phase. */ - - priv->ep0state = EP0STATE_SETUP_OUT; - } - else - { - /* We can process the setup data as soon as SETUP done word is - * popped of the RxFIFO. - */ - - priv->ep0state = EP0STATE_SETUP_READY; - } - } - break; - - default: - { - usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), - (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT); - } - break; } /* Enable the Rx Status Queue Level interrupt */ diff --git a/arch/arm/src/stm32/stm32_otghsdev.c b/arch/arm/src/stm32/stm32_otghsdev.c index ecf304bdaf..a87b173982 100644 --- a/arch/arm/src/stm32/stm32_otghsdev.c +++ b/arch/arm/src/stm32/stm32_otghsdev.c @@ -3124,132 +3124,136 @@ static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv) /* Decode status fields */ epphy = (regval & OTGHS_GRXSTSD_EPNUM_MASK) >> OTGHS_GRXSTSD_EPNUM_SHIFT; - privep = &priv->epout[epphy]; - /* Handle the RX event according to the packet status field */ - - switch (regval & OTGHS_GRXSTSD_PKTSTS_MASK) + if (epphy < STM32_NENDPOINTS) { - /* Global OUT NAK. This indicate that the global OUT NAK bit has taken - * effect. - * - * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't - * Care. - */ + privep = &priv->epout[epphy]; - case OTGHS_GRXSTSD_PKTSTS_OUTNAK: + /* Handle the RX event according to the packet status field */ + + switch (regval & OTGHS_GRXSTSD_PKTSTS_MASK) { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0); + /* Global OUT NAK. This indicate that the global OUT NAK bit has taken + * effect. + * + * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't + * Care. + */ + + case OTGHS_GRXSTSD_PKTSTS_OUTNAK: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0); + } + break; + + /* OUT data packet received. + * + * PKTSTS = DataOUT, BCNT = size of the received data OUT packet, + * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID. + */ + + case OTGHS_GRXSTSD_PKTSTS_OUTRECVD: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy); + bcnt = (regval & OTGHS_GRXSTSD_BCNT_MASK) >> OTGHS_GRXSTSD_BCNT_SHIFT; + if (bcnt > 0) + { + stm32_epout_receive(privep, bcnt); + } + } + break; + + /* OUT transfer completed. This indicates that an OUT data transfer for + * the specified OUT endpoint has completed. After this entry is popped + * from the receive FIFO, the core asserts a Transfer Completed interrupt + * on the specified OUT endpoint. + * + * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on + * which the data transfer is complete, DPID = Don't Care. + */ + + case OTGHS_GRXSTSD_PKTSTS_OUTDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy); + } + break; + + /* SETUP transaction completed. This indicates that the Setup stage for + * the specified endpoint has completed and the Data stage has started. + * After this entry is popped from the receive FIFO, the core asserts a + * Setup interrupt on the specified control OUT endpoint (triggers an + * interrupt). + * + * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num, + * DPID = Don't Care. + */ + + case OTGHS_GRXSTSD_PKTSTS_SETUPDONE: + { + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy); + } + break; + + /* SETUP data packet received. This indicates that a SETUP packet for the + * specified endpoint is now available for reading from the receive FIFO. + * + * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0. + */ + + case OTGHS_GRXSTSD_PKTSTS_SETUPRECVD: + { + uint16_t datlen; + + usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy); + + /* Read EP0 setup data. NOTE: If multiple SETUP packets are received, + * the last one overwrites the previous setup packets and only that + * last SETUP packet will be processed. + */ + + stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq, + USB_SIZEOF_CTRLREQ); + + /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP, + * then we need to wait for the completion of the data phase to + * process the setup command. If it is an IN SETUP packet, then + * we must processing the command BEFORE we enter the DATA phase. + * + * If the data associated with the OUT SETUP packet is zero length, + * then, of course, we don't need to wait. + */ + + datlen = GETUINT16(priv->ctrlreq.len); + if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0) + { + /* Clear NAKSTS so that we can receive the data */ + + regval = stm32_getreg(STM32_OTGHS_DOEPCTL0); + regval |= OTGHS_DOEPCTL0_CNAK; + stm32_putreg(regval, STM32_OTGHS_DOEPCTL0); + + /* Wait for the data phase. */ + + priv->ep0state = EP0STATE_SETUP_OUT; + } + else + { + /* We can process the setup data as soon as SETUP done word is + * popped of the RxFIFO. + */ + + priv->ep0state = EP0STATE_SETUP_READY; + } + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), + (regval & OTGHS_GRXSTSD_PKTSTS_MASK) >> OTGHS_GRXSTSD_PKTSTS_SHIFT); + } + break; } - break; - - /* OUT data packet received. - * - * PKTSTS = DataOUT, BCNT = size of the received data OUT packet, - * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID. - */ - - case OTGHS_GRXSTSD_PKTSTS_OUTRECVD: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy); - bcnt = (regval & OTGHS_GRXSTSD_BCNT_MASK) >> OTGHS_GRXSTSD_BCNT_SHIFT; - if (bcnt > 0) - { - stm32_epout_receive(privep, bcnt); - } - } - break; - - /* OUT transfer completed. This indicates that an OUT data transfer for - * the specified OUT endpoint has completed. After this entry is popped - * from the receive FIFO, the core asserts a Transfer Completed interrupt - * on the specified OUT endpoint. - * - * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on - * which the data transfer is complete, DPID = Don't Care. - */ - - case OTGHS_GRXSTSD_PKTSTS_OUTDONE: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy); - } - break; - - /* SETUP transaction completed. This indicates that the Setup stage for - * the specified endpoint has completed and the Data stage has started. - * After this entry is popped from the receive FIFO, the core asserts a - * Setup interrupt on the specified control OUT endpoint (triggers an - * interrupt). - * - * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num, - * DPID = Don't Care. - */ - - case OTGHS_GRXSTSD_PKTSTS_SETUPDONE: - { - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy); - } - break; - - /* SETUP data packet received. This indicates that a SETUP packet for the - * specified endpoint is now available for reading from the receive FIFO. - * - * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0. - */ - - case OTGHS_GRXSTSD_PKTSTS_SETUPRECVD: - { - uint16_t datlen; - - usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy); - - /* Read EP0 setup data. NOTE: If multiple SETUP packets are received, - * the last one overwrites the previous setup packets and only that - * last SETUP packet will be processed. - */ - - stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq, - USB_SIZEOF_CTRLREQ); - - /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP, - * then we need to wait for the completion of the data phase to - * process the setup command. If it is an IN SETUP packet, then - * we must processing the command BEFORE we enter the DATA phase. - * - * If the data associated with the OUT SETUP packet is zero length, - * then, of course, we don't need to wait. - */ - - datlen = GETUINT16(priv->ctrlreq.len); - if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0) - { - /* Clear NAKSTS so that we can receive the data */ - - regval = stm32_getreg(STM32_OTGHS_DOEPCTL0); - regval |= OTGHS_DOEPCTL0_CNAK; - stm32_putreg(regval, STM32_OTGHS_DOEPCTL0); - - /* Wait for the data phase. */ - - priv->ep0state = EP0STATE_SETUP_OUT; - } - else - { - /* We can process the setup data as soon as SETUP done word is - * popped of the RxFIFO. - */ - - priv->ep0state = EP0STATE_SETUP_READY; - } - } - break; - - default: - { - usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), - (regval & OTGHS_GRXSTSD_PKTSTS_MASK) >> OTGHS_GRXSTSD_PKTSTS_SHIFT); - } - break; } /* Enable the Rx Status Queue Level interrupt */ From af68a2d48408c19864ab953082a6adfac4c7fef4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 2 May 2015 11:02:08 -0600 Subject: [PATCH 4/4] Update ChangeLog --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9498912f4e..6d0024adc4 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10272,3 +10272,6 @@ * arch/arm/src/lpc17xx/lpc176x_gpio.c: Reorder steps when an output GPIO is configured in order to avoid transient bad values from being output. From Hal Glenn (2015-05-02). + * arch/arm/src/stm32/stm32_otgfsdev.c and stm32_otghsdev.c: Add + protection in the event that out-of-bound enpoint numbers are + received. From David Sidrane (2015-05-02).