stm32: Disable usb irqs in usbotg handlers
It appears the usbotg controller can get confused if the usb irq handler runs while processing a usb request. Disable usb irqs during usb processing to avoid this. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
361de30ad1
commit
60ae92d143
|
@ -14,6 +14,18 @@
|
||||||
#include "internal.h" // GPIO
|
#include "internal.h" // GPIO
|
||||||
#include "sched.h" // DECL_INIT
|
#include "sched.h" // DECL_INIT
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_irq_disable(void)
|
||||||
|
{
|
||||||
|
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_irq_enable(void)
|
||||||
|
{
|
||||||
|
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* USB transfer memory
|
* USB transfer memory
|
||||||
|
@ -64,6 +76,7 @@ fifo_write_packet(uint32_t ep, const uint8_t *src, uint32_t len)
|
||||||
{
|
{
|
||||||
void *fifo = EPFIFO(ep);
|
void *fifo = EPFIFO(ep);
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(ep);
|
USB_OTG_INEndpointTypeDef *epi = EPIN(ep);
|
||||||
|
epi->DIEPINT = USB_OTG_DIEPINT_XFRC;
|
||||||
epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
|
epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
|
||||||
epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
||||||
int32_t count = len;
|
int32_t count = len;
|
||||||
|
@ -153,53 +166,73 @@ peek_rx_queue(uint32_t ep)
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
usb_read_bulk_out(void *data, uint_fast8_t max_len)
|
usb_read_bulk_out(void *data, uint_fast8_t max_len)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
uint32_t grx = peek_rx_queue(USB_CDC_EP_BULK_OUT);
|
uint32_t grx = peek_rx_queue(USB_CDC_EP_BULK_OUT);
|
||||||
if (!grx) {
|
if (!grx) {
|
||||||
// Wait for packet
|
// Wait for packet
|
||||||
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||||
|
usb_irq_enable();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return fifo_read_packet(data, max_len);
|
int_fast8_t ret = fifo_read_packet(data, max_len);
|
||||||
|
usb_irq_enable();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
usb_send_bulk_in(void *data, uint_fast8_t len)
|
usb_send_bulk_in(void *data, uint_fast8_t len)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
uint32_t ctl = EPIN(USB_CDC_EP_BULK_IN)->DIEPCTL;
|
uint32_t ctl = EPIN(USB_CDC_EP_BULK_IN)->DIEPCTL;
|
||||||
if (!(ctl & USB_OTG_DIEPCTL_USBAEP))
|
if (!(ctl & USB_OTG_DIEPCTL_USBAEP)) {
|
||||||
// Controller not enabled - discard data
|
// Controller not enabled - discard data
|
||||||
|
usb_irq_enable();
|
||||||
return len;
|
return len;
|
||||||
if (ctl & USB_OTG_DIEPCTL_EPENA)
|
}
|
||||||
|
if (ctl & USB_OTG_DIEPCTL_EPENA) {
|
||||||
// Wait for space to transmit
|
// Wait for space to transmit
|
||||||
|
OTGD->DAINTMSK |= 1 << USB_CDC_EP_BULK_IN;
|
||||||
|
usb_irq_enable();
|
||||||
return -1;
|
return -1;
|
||||||
return fifo_write_packet(USB_CDC_EP_BULK_IN, data, len);
|
}
|
||||||
|
int_fast8_t ret = fifo_write_packet(USB_CDC_EP_BULK_IN, data, len);
|
||||||
|
usb_irq_enable();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
usb_read_ep0(void *data, uint_fast8_t max_len)
|
usb_read_ep0(void *data, uint_fast8_t max_len)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
uint32_t grx = peek_rx_queue(0);
|
uint32_t grx = peek_rx_queue(0);
|
||||||
if (!grx) {
|
if (!grx) {
|
||||||
// Wait for packet
|
// Wait for packet
|
||||||
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||||
|
usb_irq_enable();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
|
uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
|
||||||
>> USB_OTG_GRXSTSP_PKTSTS_Pos);
|
>> USB_OTG_GRXSTSP_PKTSTS_Pos);
|
||||||
if (pktsts != 2)
|
if (pktsts != 2) {
|
||||||
// Transfer interrupted
|
// Transfer interrupted
|
||||||
|
usb_irq_enable();
|
||||||
return -2;
|
return -2;
|
||||||
return fifo_read_packet(data, max_len);
|
}
|
||||||
|
int_fast8_t ret = fifo_read_packet(data, max_len);
|
||||||
|
usb_irq_enable();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
usb_read_ep0_setup(void *data, uint_fast8_t max_len)
|
usb_read_ep0_setup(void *data, uint_fast8_t max_len)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t grx = peek_rx_queue(0);
|
uint32_t grx = peek_rx_queue(0);
|
||||||
if (!grx) {
|
if (!grx) {
|
||||||
// Wait for packet
|
// Wait for packet
|
||||||
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||||
|
usb_irq_enable();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
|
uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
|
||||||
|
@ -220,30 +253,40 @@ usb_read_ep0_setup(void *data, uint_fast8_t max_len)
|
||||||
while (OTG->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH)
|
while (OTG->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
return fifo_read_packet(data, max_len);
|
int_fast8_t ret = fifo_read_packet(data, max_len);
|
||||||
|
usb_irq_enable();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
usb_send_ep0(const void *data, uint_fast8_t len)
|
usb_send_ep0(const void *data, uint_fast8_t len)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
uint32_t grx = peek_rx_queue(0);
|
uint32_t grx = peek_rx_queue(0);
|
||||||
if (grx) {
|
if (grx) {
|
||||||
// Transfer interrupted
|
// Transfer interrupted
|
||||||
|
usb_irq_enable();
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (EPIN(0)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
|
if (EPIN(0)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
|
||||||
// Wait for space to transmit
|
// Wait for space to transmit
|
||||||
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||||
|
OTGD->DAINTMSK |= 1 << 0;
|
||||||
|
usb_irq_enable();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return fifo_write_packet(0, data, len);
|
int_fast8_t ret = fifo_write_packet(0, data, len);
|
||||||
|
usb_irq_enable();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_stall_ep0(void)
|
usb_stall_ep0(void)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
EPIN(0)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
|
EPIN(0)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
|
||||||
usb_notify_ep0(); // XXX - wake from main usb_cdc.c code?
|
usb_notify_ep0(); // XXX - wake from main usb_cdc.c code?
|
||||||
|
usb_irq_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -258,6 +301,7 @@ usb_set_address(uint_fast8_t addr)
|
||||||
void
|
void
|
||||||
usb_set_configure(void)
|
usb_set_configure(void)
|
||||||
{
|
{
|
||||||
|
usb_irq_disable();
|
||||||
// Configure and enable USB_CDC_EP_ACM
|
// Configure and enable USB_CDC_EP_ACM
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(USB_CDC_EP_ACM);
|
USB_OTG_INEndpointTypeDef *epi = EPIN(USB_CDC_EP_ACM);
|
||||||
epi->DIEPTSIZ = (USB_CDC_EP_ACM_SIZE
|
epi->DIEPTSIZ = (USB_CDC_EP_ACM_SIZE
|
||||||
|
@ -291,6 +335,7 @@ usb_set_configure(void)
|
||||||
| USB_OTG_GRSTCTL_TXFFLSH);
|
| USB_OTG_GRSTCTL_TXFFLSH);
|
||||||
while (OTG->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH)
|
while (OTG->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH)
|
||||||
;
|
;
|
||||||
|
usb_irq_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -320,17 +365,12 @@ OTG_FS_IRQHandler(void)
|
||||||
if (sts & USB_OTG_GINTSTS_IEPINT) {
|
if (sts & USB_OTG_GINTSTS_IEPINT) {
|
||||||
// Can transmit data - disable irq and notify endpoint
|
// Can transmit data - disable irq and notify endpoint
|
||||||
uint32_t daint = OTGD->DAINT;
|
uint32_t daint = OTGD->DAINT;
|
||||||
if (daint & (1 << 0)) {
|
OTGD->DAINTMSK &= ~daint;
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(0);
|
if (daint & (1 << 0))
|
||||||
epi->DIEPINT = epi->DIEPINT;
|
|
||||||
usb_notify_ep0();
|
usb_notify_ep0();
|
||||||
}
|
if (daint & (1 << USB_CDC_EP_BULK_IN))
|
||||||
if (daint & (1 << USB_CDC_EP_BULK_IN)) {
|
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(USB_CDC_EP_BULK_IN);
|
|
||||||
epi->DIEPINT = epi->DIEPINT;
|
|
||||||
usb_notify_bulk_in();
|
usb_notify_bulk_in();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_CONSTANT_STR("RESERVE_PINS_USB", "PA11,PA12");
|
DECL_CONSTANT_STR("RESERVE_PINS_USB", "PA11,PA12");
|
||||||
|
@ -371,7 +411,6 @@ usb_init(void)
|
||||||
epo->DOEPCTL = mpsize_ep0 | USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
epo->DOEPCTL = mpsize_ep0 | USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||||
|
|
||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
OTGD->DAINTMSK = (1 << 0) | (1 << USB_CDC_EP_BULK_IN);
|
|
||||||
OTGD->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
|
OTGD->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
|
||||||
OTG->GINTMSK = USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_IEPINT;
|
OTG->GINTMSK = USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_IEPINT;
|
||||||
OTG->GAHBCFG = USB_OTG_GAHBCFG_GINT;
|
OTG->GAHBCFG = USB_OTG_GAHBCFG_GINT;
|
||||||
|
|
Loading…
Reference in New Issue