aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth McMullin2012-05-26 20:57:47 +1200
committerGareth McMullin2012-05-26 20:57:47 +1200
commit3dcdc5b26f769ce9131b8a476d8dbe8992f1284e (patch)
tree367e23f7d301fd9e4eec9ae93a41c1546a63489f
parentb98d01dff89918a6fbab06127b30f47ee7827780 (diff)
Improve USB UART handling. Fix interrupt priorities.
-rw-r--r--src/stm32/cdcacm.c6
-rw-r--r--src/stm32/platform.c26
-rw-r--r--src/stm32/platform.h12
-rw-r--r--src/stm32/traceswo.c2
4 files changed, 40 insertions, 6 deletions
diff --git a/src/stm32/cdcacm.c b/src/stm32/cdcacm.c
index 6a70acc..99efaf8 100644
--- a/src/stm32/cdcacm.c
+++ b/src/stm32/cdcacm.c
@@ -521,7 +521,7 @@ static void cdcacm_set_config(u16 wValue)
/* Serial interface */
usbd_ep_setup(0x03, USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, cdcacm_data_rx_cb);
- usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL);
+ usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, uart_usb_buf_drain);
usbd_ep_setup(0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
/* Trace interface */
@@ -563,9 +563,9 @@ void cdcacm_init(void)
usbd_set_control_buffer_size(sizeof(usbd_control_buffer));
usbd_register_set_config_callback(cdcacm_set_config);
- nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
+ nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, IRQ_PRI_USB);
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
- nvic_set_priority(USB_VBUS_IRQ, 14);
+ nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS);
nvic_enable_irq(USB_VBUS_IRQ);
gpio_set(USB_VBUS_PORT, USB_VBUS_PIN);
diff --git a/src/stm32/platform.c b/src/stm32/platform.c
index 522e920..8218894 100644
--- a/src/stm32/platform.c
+++ b/src/stm32/platform.c
@@ -238,15 +238,37 @@ static void uart_init(void)
/* Enable interrupts */
USART1_CR1 |= USART_CR1_RXNEIE;
- nvic_set_priority(NVIC_USART1_IRQ, 14);
+ nvic_set_priority(NVIC_USART1_IRQ, IRQ_PRI_USART1);
nvic_enable_irq(NVIC_USART1_IRQ);
}
+static uint8_t uart_usb_buf[CDCACM_PACKET_SIZE];
+static uint8_t uart_usb_buf_size;
+
+void uart_usb_buf_drain(uint8_t ep)
+{
+ if (!uart_usb_buf_size)
+ return;
+
+ usbd_ep_write_packet(ep, uart_usb_buf, uart_usb_buf_size);
+ uart_usb_buf_size = 0;
+}
+
void usart1_isr(void)
{
char c = usart_recv(USART1);
- usbd_ep_write_packet(0x83, &c, 1);
+ /* Try to send now */
+ if (usbd_ep_write_packet(0x83, &c, 1) == 1)
+ return;
+
+ /* We failed, so queue for later */
+ if (uart_usb_buf_size == CDCACM_PACKET_SIZE) {
+ /* Drop if the buffer's full: we have no flow control */
+ return;
+ }
+
+ uart_usb_buf[uart_usb_buf_size++] = c;
}
#endif
diff --git a/src/stm32/platform.h b/src/stm32/platform.h
index ab292d9..5b546ca 100644
--- a/src/stm32/platform.h
+++ b/src/stm32/platform.h
@@ -80,6 +80,15 @@
#define LED_IDLE GPIO10
#define LED_ERROR GPIO11
+/* Interrupt priorities. Low numbers are high priority.
+ * For now USART1 preempts USB which may spin while buffer is drained.
+ * TIM3 is used for traceswo capture and must be highest priority.
+ */
+#define IRQ_PRI_USB (2 << 4)
+#define IRQ_PRI_USART1 (1 << 4)
+#define IRQ_PRI_USB_VBUS (14 << 4)
+#define IRQ_PRI_TIM3 (0 << 4)
+
#define DEBUG(...)
extern uint8_t running_status;
@@ -121,6 +130,9 @@ void cdcacm_init(void);
int cdcacm_get_config(void);
int cdcacm_get_dtr(void);
+/* <platform.h> */
+void uart_usb_buf_drain(uint8_t ep);
+
/* Use newlib provided integer only stdio functions */
#define sscanf siscanf
#define sprintf siprintf
diff --git a/src/stm32/traceswo.c b/src/stm32/traceswo.c
index 0451210..926a057 100644
--- a/src/stm32/traceswo.c
+++ b/src/stm32/traceswo.c
@@ -68,7 +68,7 @@ void traceswo_init(void)
timer_slave_set_mode(TIM3, TIM_SMCR_SMS_RM);
/* Enable capture interrupt */
- nvic_set_priority(NVIC_TIM3_IRQ, 0);
+ nvic_set_priority(NVIC_TIM3_IRQ, IRQ_PRI_TIM3);
nvic_enable_irq(NVIC_TIM3_IRQ);
timer_enable_irq(TIM3, TIM_DIER_CC1IE);