aboutsummaryrefslogtreecommitdiff
path: root/src/platforms
diff options
context:
space:
mode:
authorUwe Bonnes2013-01-12 21:49:55 +0100
committerUwe Bonnes2013-01-21 11:02:43 +0100
commit67f8176c5bcaed5cddbd84c46984d2f94e78ba3e (patch)
tree925b0c33553618841d169026ac81e61f365b6483 /src/platforms
parent35d6adc236f54e94231b1959eb2d16b785c7733a (diff)
stlink: Add the UART
Diffstat (limited to 'src/platforms')
-rw-r--r--src/platforms/stlink/Makefile.inc3
-rw-r--r--src/platforms/stlink/cdcacm.c132
-rw-r--r--src/platforms/stlink/platform.c8
-rw-r--r--src/platforms/stlink/platform.h25
4 files changed, 162 insertions, 6 deletions
diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc
index d298e78..9e72e56 100644
--- a/src/platforms/stlink/Makefile.inc
+++ b/src/platforms/stlink/Makefile.inc
@@ -3,7 +3,7 @@ CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
CFLAGS += -mcpu=cortex-m3 -mthumb \
- -DSTM32F1 -I../libopencm3/include
+ -DSTM32F1 -I../libopencm3/include -Iplatforms/stlink -Iplatforms/stm32
LDFLAGS = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \
-Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \
@@ -13,6 +13,7 @@ VPATH += platforms/stm32
SRC += cdcacm.c \
platform.c \
+ platforms/native/usbuart.c \
all: blackmagic.bin
diff --git a/src/platforms/stlink/cdcacm.c b/src/platforms/stlink/cdcacm.c
index a2a4510..1cad4d7 100644
--- a/src/platforms/stlink/cdcacm.c
+++ b/src/platforms/stlink/cdcacm.c
@@ -37,6 +37,7 @@
#include <stdlib.h>
#include "platform.h"
+#include <usbuart.h>
usbd_device * usbdev;
@@ -167,6 +168,109 @@ static const struct usb_iface_assoc_descriptor gdb_assoc = {
.iFunction = 0,
};
+/* Serial ACM interface */
+static const struct usb_endpoint_descriptor uart_comm_endp[] = {{
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x84,
+ .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
+ .wMaxPacketSize = 16,
+ .bInterval = 255,
+}};
+
+static const struct usb_endpoint_descriptor uart_data_endp[] = {{
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x03,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = CDCACM_PACKET_SIZE,
+ .bInterval = 1,
+}, {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x83,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = CDCACM_PACKET_SIZE,
+ .bInterval = 1,
+}};
+
+static const struct {
+ struct usb_cdc_header_descriptor header;
+ struct usb_cdc_call_management_descriptor call_mgmt;
+ struct usb_cdc_acm_descriptor acm;
+ struct usb_cdc_union_descriptor cdc_union;
+} __attribute__((packed)) uart_cdcacm_functional_descriptors = {
+ .header = {
+ .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
+ .bcdCDC = 0x0110,
+ },
+ .call_mgmt = {
+ .bFunctionLength =
+ sizeof(struct usb_cdc_call_management_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
+ .bmCapabilities = 0,
+ .bDataInterface = 3,
+ },
+ .acm = {
+ .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_ACM,
+ .bmCapabilities = 2, /* SET_LINE_CODING supported*/
+ },
+ .cdc_union = {
+ .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_UNION,
+ .bControlInterface = 2,
+ .bSubordinateInterface0 = 3,
+ }
+};
+
+static const struct usb_interface_descriptor uart_comm_iface[] = {{
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 2,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_CDC,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
+ .iInterface = 5,
+
+ .endpoint = uart_comm_endp,
+
+ .extra = &uart_cdcacm_functional_descriptors,
+ .extralen = sizeof(uart_cdcacm_functional_descriptors)
+}};
+
+static const struct usb_interface_descriptor uart_data_iface[] = {{
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 3,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0,
+
+ .endpoint = uart_data_endp,
+}};
+
+static const struct usb_iface_assoc_descriptor uart_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 2,
+ .bInterfaceCount = 2,
+ .bFunctionClass = USB_CLASS_CDC,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
+ .bFunctionProtocol = USB_CDC_PROTOCOL_AT,
+ .iFunction = 0,
+};
+
static const struct usb_interface ifaces[] = {{
.num_altsetting = 1,
.iface_assoc = &gdb_assoc,
@@ -174,13 +278,20 @@ static const struct usb_interface ifaces[] = {{
}, {
.num_altsetting = 1,
.altsetting = gdb_data_iface,
+}, {
+ .num_altsetting = 1,
+ .iface_assoc = &uart_assoc,
+ .altsetting = uart_comm_iface,
+}, {
+ .num_altsetting = 1,
+ .altsetting = uart_data_iface,
}};
static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
- .bNumInterfaces = 2,
+ .bNumInterfaces = 4,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
@@ -192,15 +303,14 @@ static const struct usb_config_descriptor config = {
char serial_no[9];
static const char *usb_strings[] = {
- "x",
"Black Sphere Technologies",
"Black Magic Probe",
serial_no,
"Black Magic GDB Server",
+ "Black Magic UART Port",
};
-static int cdcacm_control_request(
- usbd_device *dev,
+static int cdcacm_control_request(usbd_device *dev,
struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
void (**complete)(usbd_device *dev, struct usb_setup_data *req))
{
@@ -223,6 +333,8 @@ static int cdcacm_control_request(
return 0;
switch(req->wIndex) {
+ case 2:
+ usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf);
case 0:
return 1; /* Ignore on GDB Port */
default:
@@ -253,6 +365,13 @@ static void cdcacm_set_config(usbd_device *dev, u16 wValue)
CDCACM_PACKET_SIZE, NULL);
usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
+ /* Serial interface */
+ usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK,
+ CDCACM_PACKET_SIZE, usbuart_usb_out_cb);
+ usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK,
+ CDCACM_PACKET_SIZE, usbuart_usb_in_cb);
+ usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
+
usbd_register_control_callback(dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
@@ -272,6 +391,8 @@ static void cdcacm_set_config(usbd_device *dev, u16 wValue)
buf[8] = 3; /* DCD | DSR */
buf[9] = 0;
usbd_ep_write_packet(dev, 0x82, buf, 10);
+ notif->wIndex = 2;
+ usbd_ep_write_packet(dev, 0x84, buf, 10);
}
/* We need a special large control buffer for this device: */
@@ -284,10 +405,11 @@ void cdcacm_init(void)
get_dev_unique_id(serial_no);
usbdev = usbd_init(&stm32f103_usb_driver,
- &dev, &config, usb_strings, 7);
+ &dev, &config, usb_strings, 5);
usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer));
usbd_register_set_config_callback(usbdev, cdcacm_set_config);
+ nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, IRQ_PRI_USB);
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
}
diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c
index f28764f..26e1ad2 100644
--- a/src/platforms/stlink/platform.c
+++ b/src/platforms/stlink/platform.c
@@ -32,6 +32,7 @@
#include "platform.h"
#include "jtag_scan.h"
+#include <usbuart.h>
#include <ctype.h>
@@ -48,6 +49,7 @@ int platform_init(void)
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
/* Setup GPIO ports */
gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ,
@@ -63,9 +65,15 @@ int platform_init(void)
/* Setup heartbeat timer */
systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000); /* Interrupt us at 10 Hz */
+ SCB_SHPR(11) &= ~((15 << 4) & 0xff);
+ SCB_SHPR(11) |= ((14 << 4) & 0xff);
systick_interrupt_enable();
systick_counter_enable();
+ usbuart_init();
+
+ SCB_VTOR = 0x2000; // Relocate interrupt vector table here
+
cdcacm_init();
jtag_scan(NULL);
diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h
index d804abc..8f9e58e 100644
--- a/src/platforms/stlink/platform.h
+++ b/src/platforms/stlink/platform.h
@@ -37,6 +37,7 @@
extern usbd_device *usbdev;
#define CDCACM_GDB_ENDPOINT 1
+#define CDCACM_UART_ENDPOINT 3
/* Important pin mappings for STM32 implementation:
*
@@ -75,8 +76,29 @@ extern usbd_device *usbdev;
#define SWCLK_PIN TCK_PIN
#define LED_PORT GPIOA
+/* Use PC14 for a "dummy" uart led. So we can observere at least with scope*/
+#define LED_PORT_UART GPIOC
+#define LED_UART GPIO14
#define LED_IDLE_RUN GPIO8
+/* Interrupt priorities. Low numbers are high priority.
+ * For now USART2 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_USBUSART (1 << 4)
+#define IRQ_PRI_USB_VBUS (14 << 4)
+#define IRQ_PRI_TIM3 (0 << 4)
+
+#define USBUSART USART2
+#define USBUSART_CR1 USART2_CR1
+#define USBUSART_IRQ NVIC_USART2_IRQ
+#define USBUSART_APB_ENR RCC_APB1ENR
+#define USBUSART_CLK_ENABLE RCC_APB1ENR_USART2EN
+#define USBUSART_PORT GPIOA
+#define USBUSART_TX_PIN GPIO2
+#define USBUSART_ISR usart2_isr
+
#define DEBUG(...)
extern uint8_t running_status;
@@ -116,6 +138,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