From 67f8176c5bcaed5cddbd84c46984d2f94e78ba3e Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 21:49:55 +0100 Subject: stlink: Add the UART --- src/platforms/stlink/Makefile.inc | 3 +- src/platforms/stlink/cdcacm.c | 132 ++++++++++++++++++++++++++++++++++++-- src/platforms/stlink/platform.c | 8 +++ src/platforms/stlink/platform.h | 25 ++++++++ 4 files changed, 162 insertions(+), 6 deletions(-) (limited to 'src/platforms') 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 #include "platform.h" +#include 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 #include @@ -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); +/* */ +void uart_usb_buf_drain(uint8_t ep); + /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf -- cgit v1.2.3