From b07ffffcee53e18051b324eb59a2794044ce6f95 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 10:16:33 -0800 Subject: Factor out common cdcacm.c from stm32 and tm4c. Cleaned up interface to enter bootloader and read serial number.--- src/platforms/common/cdcacm.c | 554 ++++++++++++++++++++++++++++++ src/platforms/common/serialno.h | 26 ++ src/platforms/f4discovery/Makefile.inc | 1 + src/platforms/f4discovery/platform.c | 8 +- src/platforms/f4discovery/platform.h | 4 - src/platforms/launchpad-icdi/platform.c | 46 +++ src/platforms/launchpad-icdi/platform.h | 22 +- src/platforms/native/Makefile.inc | 1 + src/platforms/native/platform.c | 10 +- src/platforms/native/platform.h | 4 - src/platforms/stlink/Makefile.inc | 3 +- src/platforms/stlink/platform.c | 10 +- src/platforms/stlink/platform.h | 4 - src/platforms/stm32/cdcacm.c | 583 -------------------------------- src/platforms/stm32/serialno.c | 45 +++ src/platforms/swlink/Makefile.inc | 3 +- src/platforms/swlink/platform.c | 8 +- src/platforms/swlink/platform.h | 3 - src/platforms/tm4c/cdcacm.c | 577 ------------------------------- src/platforms/tm4c/traceswo.c | 1 + 20 files changed, 713 insertions(+), 1200 deletions(-) create mode 100644 src/platforms/common/cdcacm.c create mode 100644 src/platforms/common/serialno.h delete mode 100644 src/platforms/stm32/cdcacm.c create mode 100644 src/platforms/stm32/serialno.c delete mode 100644 src/platforms/tm4c/cdcacm.c (limited to 'src/platforms') diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c new file mode 100644 index 0000000..8e95a9a --- /dev/null +++ b/src/platforms/common/cdcacm.c @@ -0,0 +1,554 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* This file implements a the USB Communications Device Class - Abstract + * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. + * A Device Firmware Upgrade (DFU 1.1) class interface is provided for + * field firmware upgrade. + * + * The device's unique id is used as the USB serial number string. + */ + +#include "general.h" +#include "gdb_if.h" +#include "cdcacm.h" +#if defined(PLATFORM_HAS_TRACESWO) +# include "traceswo.h" +#endif +#include "usbuart.h" +#include "serialno.h" + +#include +#include +#include +#include +#include +#include + +#define DFU_IF_NO 4 + +usbd_device * usbdev; + +static int configured; +static int cdcacm_gdb_dtr = 1; + + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xEF, /* Miscellaneous Device */ + .bDeviceSubClass = 2, /* Common Class */ + .bDeviceProtocol = 1, /* Interface Association */ + .bMaxPacketSize0 = 64, + .idVendor = 0x1D50, + .idProduct = 0x6018, + .bcdDevice = 0x0100, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +/* This notification endpoint isn't implemented. According to CDC spec its + * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm + * driver. */ +static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .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)) gdb_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 = 1, + }, + .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 = 0, + .bSubordinateInterface0 = 1, + } +}; + +static const struct usb_interface_descriptor gdb_comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 4, + + .endpoint = gdb_comm_endp, + + .extra = &gdb_cdcacm_functional_descriptors, + .extralen = sizeof(gdb_cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor gdb_data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = gdb_data_endp, +}}; + +static const struct usb_iface_assoc_descriptor gdb_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .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, +}; + +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor dfu_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = DFU_IF_NO, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 6, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + +static const struct usb_iface_assoc_descriptor dfu_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 4, + .bInterfaceCount = 1, + .bFunctionClass = 0xFE, + .bFunctionSubClass = 1, + .bFunctionProtocol = 1, + .iFunction = 6, +}; + +#if defined(PLATFORM_HAS_TRACESWO) +static const struct usb_endpoint_descriptor trace_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x85, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}}; + +const struct usb_interface_descriptor trace_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 5, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xFF, + .bInterfaceSubClass = 0xFF, + .bInterfaceProtocol = 0xFF, + .iInterface = 7, + + .endpoint = trace_endp, +}; + +static const struct usb_iface_assoc_descriptor trace_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 5, + .bInterfaceCount = 1, + .bFunctionClass = 0xFF, + .bFunctionSubClass = 0xFF, + .bFunctionProtocol = 0xFF, + .iFunction = 7, +}; +#endif + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .iface_assoc = &gdb_assoc, + .altsetting = gdb_comm_iface, +}, { + .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, +}, { + .num_altsetting = 1, + .iface_assoc = &dfu_assoc, + .altsetting = &dfu_iface, +#if defined(PLATFORM_HAS_TRACESWO) +}, { + .num_altsetting = 1, + .iface_assoc = &trace_assoc, + .altsetting = &trace_iface, +#endif +}}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, +#if defined(PLATFORM_HAS_TRACESWO) + .bNumInterfaces = 6, +#else + .bNumInterfaces = 5, +#endif + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +char serial_no[9]; + +static const char *usb_strings[] = { + "Black Sphere Technologies", + BOARD_IDENT, + serial_no, + "Black Magic GDB Server", + "Black Magic UART Port", + DFU_IDENT, +#if defined(PLATFORM_HAS_TRACESWO) + "Black Magic Trace Capture", +#endif +}; + +static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) +{ + (void)dev; + (void)req; + + platform_request_boot(); + + /* Reset core to enter bootloader */ + scb_reset_core(); +} + +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)) +{ + (void)dev; + (void)complete; + (void)buf; + (void)len; + + switch(req->bRequest) { + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + /* Ignore if not for GDB interface */ + if(req->wIndex != 0) + return 1; + + cdcacm_gdb_dtr = req->wValue & 1; + + return 1; + case USB_CDC_REQ_SET_LINE_CODING: + if(*len < sizeof(struct usb_cdc_line_coding)) + 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: + return 0; + } + case DFU_GETSTATUS: + if(req->wIndex == DFU_IF_NO) { + (*buf)[0] = DFU_STATUS_OK; + (*buf)[1] = 0; + (*buf)[2] = 0; + (*buf)[3] = 0; + (*buf)[4] = STATE_APP_IDLE; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + return 1; + } + case DFU_DETACH: + if(req->wIndex == DFU_IF_NO) { + *complete = dfu_detach_complete; + return 1; + } + return 0; + } + return 0; +} + +int cdcacm_get_config(void) +{ + return configured; +} + +int cdcacm_get_dtr(void) +{ + return cdcacm_gdb_dtr; +} + +static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) +{ + configured = wValue; + + /* GDB interface */ +#ifdef STM32F4 + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, gdb_usb_out_cb); +#else + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); +#endif + usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, + 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); + +#if defined(PLATFORM_HAS_TRACESWO) + /* Trace interface */ + usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, + 64, trace_buf_drain); +#endif + + usbd_register_control_callback(dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + cdcacm_control_request); + + /* Notify the host that DCD is asserted. + * Allows the use of /dev/tty* devices on *BSD/MacOS + */ + char buf[10]; + struct usb_cdc_notification *notif = (void*)buf; + /* We echo signals back to host as notification */ + notif->bmRequestType = 0xA1; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wValue = 0; + notif->wIndex = 0; + notif->wLength = 2; + 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: */ +uint8_t usbd_control_buffer[256]; + +void cdcacm_init(void) +{ + void exti15_10_isr(void); + + serialno_read(serial_no); + + usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, + sizeof(usb_strings)/sizeof(char *), + usbd_control_buffer, sizeof(usbd_control_buffer)); + + usbd_register_set_config_callback(usbdev, cdcacm_set_config); + + nvic_set_priority(USB_IRQ, IRQ_PRI_USB); + nvic_enable_irq(USB_IRQ); +} + +void USB_ISR(void) +{ + usbd_poll(usbdev); +} + diff --git a/src/platforms/common/serialno.h b/src/platforms/common/serialno.h new file mode 100644 index 0000000..946dc20 --- /dev/null +++ b/src/platforms/common/serialno.h @@ -0,0 +1,26 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __SERIALNO_H +#define __SERIALNO_H + +char *serialno_read(char *s); + +#endif + diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 88575bb..21b4078 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -19,6 +19,7 @@ SRC += cdcacm.c \ platform.c \ traceswo.c \ usbuart.c \ + serialno.c \ all: blackmagic.bin diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index cf6cdf3..6e10ff4 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -46,7 +46,7 @@ void platform_init(void) /* Check the USER button*/ rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); if(gpio_get(GPIOA, GPIO0)) { - assert_boot_pin(); + platform_request_boot(); scb_reset_core(); } @@ -111,8 +111,12 @@ const char *platform_target_voltage(void) return "ABSENT!"; } -void assert_boot_pin(void) +void platform_request_boot(void) { + /* Disconnect USB cable */ + usbd_disconnect(usbdev, 1); + nvic_disable_irq(USB_IRQ); + /* Assert blue LED as indicator we are in the bootloader */ rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index f58205d..61753af 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -176,9 +176,5 @@ static inline int platform_hwversion(void) #define sprintf siprintf #define vasprintf vasiprintf -#define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) -void assert_boot_pin(void); -#define setup_vbus_irq() - #endif diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 0e3fb85..e689f0c 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -1,3 +1,19 @@ +/* + * This file is part of the Black Magic Debug project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "general.h" #include "gdb_if.h" #include "cdcacm.h" @@ -7,6 +23,7 @@ #include #include #include +#include #define SYSTICKHZ 100 #define SYSTICKMS (1000 / SYSTICKHZ) @@ -58,6 +75,13 @@ platform_init(void) nvic_enable_irq(NVIC_SYSTICK_IRQ); nvic_enable_irq(NVIC_UART0_IRQ); + periph_clock_enable(RCC_GPIOD); + __asm__("nop"); __asm__("nop"); __asm__("nop"); + gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); + usb_enable_interrupts(USB_INT_RESET | USB_INT_DISCON | + USB_INT_RESUME | USB_INT_SUSPEND, + 0xff, 0xff); + usbuart_init(); cdcacm_init(); } @@ -73,3 +97,25 @@ const char *platform_target_voltage(void) return "not supported"; } +char *serialno_read(char *s) +{ + /* FIXME: Store a unique serial number somewhere and retreive here */ + uint32_t unique_id = 1; + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; + s[8] = 0; + + return s; +} + +void platform_request_boot(void) +{ +} + diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 5f686f4..eb3ac6e 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -1,3 +1,19 @@ +/* + * This file is part of the Black Magic Debug project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef __PLATFORM_H #define __PLATFORM_H @@ -8,16 +24,11 @@ #include #include -#define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" #define DFU_IFACE_STRING "lolwut" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - extern jmp_buf fatal_error_jmpbuf; extern uint8_t running_status; extern volatile uint32_t timeout_counter; @@ -116,6 +127,5 @@ inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { } #define disconnect_usb() do { usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) -#define setup_vbus_irq() #endif diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index cc4da0b..2270ff5 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -18,6 +18,7 @@ SRC += cdcacm.c \ platform.c \ traceswo.c \ usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 9b39238..5c28747 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -42,6 +42,7 @@ volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; static void adc_init(void); +static void setup_vbus_irq(void); /* Pins PB[7:5] are used to detect hardware revision. * 000 - Original production build. @@ -134,6 +135,7 @@ void platform_init(void) cdcacm_init(); usbuart_init(); + setup_vbus_irq(); } void platform_srst_set_val(bool assert) @@ -221,8 +223,12 @@ const char *platform_target_voltage(void) return ret; } -void assert_boot_pin(void) +void platform_request_boot(void) { + /* Disconnect USB cable */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); + + /* Drive boot request pin */ gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); gpio_clear(GPIOB, GPIO12); @@ -243,7 +249,7 @@ void exti15_10_isr(void) exti_reset_request(USB_VBUS_PIN); } -void setup_vbus_irq(void) +static void setup_vbus_irq(void) { nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); nvic_enable_irq(USB_VBUS_IRQ); diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 5688e60..c0b4dba 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -170,9 +170,5 @@ extern jmp_buf fatal_error_jmpbuf; #define sprintf siprintf #define vasprintf vasiprintf -#define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); -void assert_boot_pin(void); -void setup_vbus_irq(void); - #endif diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 5cfe726..52ad33b 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -16,7 +16,8 @@ VPATH += platforms/stm32 SRC += cdcacm.c \ platform.c \ - usbuart.c \ + usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 6194d92..446fb47 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -149,7 +149,7 @@ const char *platform_target_voltage(void) return "unknown"; } -void disconnect_usb(void) +void platform_request_boot(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ rcc_periph_reset_pulse(RST_USB); @@ -158,10 +158,8 @@ void disconnect_usb(void) gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -} -void assert_boot_pin(void) -{ + /* Assert bootloader pin */ uint32_t crl = GPIOA_CRL; rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin @@ -173,7 +171,3 @@ void assert_boot_pin(void) GPIOA_CRL = crl; } -void setup_vbus_irq(void) -{ -} - diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 5768817..fcbe259 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -152,9 +152,5 @@ extern uint16_t led_idle_run; #define sprintf siprintf #define vasprintf vasiprintf -void disconnect_usb(void); -void assert_boot_pin(void); -void setup_vbus_irq(void); - #endif diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c deleted file mode 100644 index 577925a..0000000 --- a/src/platforms/stm32/cdcacm.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2011 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* This file implements a the USB Communications Device Class - Abstract - * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. - * A Device Firmware Upgrade (DFU 1.1) class interface is provided for - * field firmware upgrade. - * - * The device's unique id is used as the USB serial number string. - */ - -#include -#include -#include -#include -#include -#include - -#include "general.h" -#include "gdb_if.h" -#include "cdcacm.h" -#if defined(PLATFORM_HAS_TRACESWO) -#include "traceswo.h" -#endif -#include "usbuart.h" - -#define DFU_IF_NO 4 - -usbd_device * usbdev; - -static char *get_dev_unique_id(char *serial_no); - -static int configured; -static int cdcacm_gdb_dtr = 1; - - -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0xEF, /* Miscellaneous Device */ - .bDeviceSubClass = 2, /* Common Class */ - .bDeviceProtocol = 1, /* Interface Association */ - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6018, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -/* This notification endpoint isn't implemented. According to CDC spec its - * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm - * driver. */ -static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x81, - .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)) gdb_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 = 1, - }, - .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 = 0, - .bSubordinateInterface0 = 1, - } -}; - -static const struct usb_interface_descriptor gdb_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 4, - - .endpoint = gdb_comm_endp, - - .extra = &gdb_cdcacm_functional_descriptors, - .extralen = sizeof(gdb_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor gdb_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = gdb_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor gdb_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 0, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .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, -}; - -const struct usb_dfu_descriptor dfu_function = { - .bLength = sizeof(struct usb_dfu_descriptor), - .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, - .wDetachTimeout = 255, - .wTransferSize = 1024, - .bcdDFUVersion = 0x011A, -}; - -const struct usb_interface_descriptor dfu_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = DFU_IF_NO, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 6, - - .extra = &dfu_function, - .extralen = sizeof(dfu_function), -}; - -static const struct usb_iface_assoc_descriptor dfu_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 4, - .bInterfaceCount = 1, - .bFunctionClass = 0xFE, - .bFunctionSubClass = 1, - .bFunctionProtocol = 1, - .iFunction = 6, -}; - -#if defined(PLATFORM_HAS_TRACESWO) -static const struct usb_endpoint_descriptor trace_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x85, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, -}}; - -const struct usb_interface_descriptor trace_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 5, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = 0xFF, - .bInterfaceSubClass = 0xFF, - .bInterfaceProtocol = 0xFF, - .iInterface = 7, - - .endpoint = trace_endp, -}; - -static const struct usb_iface_assoc_descriptor trace_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 5, - .bInterfaceCount = 1, - .bFunctionClass = 0xFF, - .bFunctionSubClass = 0xFF, - .bFunctionProtocol = 0xFF, - .iFunction = 7, -}; -#endif - -static const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .iface_assoc = &gdb_assoc, - .altsetting = gdb_comm_iface, -}, { - .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, -}, { - .num_altsetting = 1, - .iface_assoc = &dfu_assoc, - .altsetting = &dfu_iface, -#if defined(PLATFORM_HAS_TRACESWO) -}, { - .num_altsetting = 1, - .iface_assoc = &trace_assoc, - .altsetting = &trace_iface, -#endif -}}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, -#if defined(PLATFORM_HAS_TRACESWO) - .bNumInterfaces = 6, -#else - .bNumInterfaces = 5, -#endif - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - - .interface = ifaces, -}; - -char serial_no[9]; - -static const char *usb_strings[] = { - "Black Sphere Technologies", - BOARD_IDENT, - serial_no, - "Black Magic GDB Server", - "Black Magic UART Port", - DFU_IDENT, -#if defined(PLATFORM_HAS_TRACESWO) - "Black Magic Trace Capture", -#endif -}; - -static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) -{ - (void)dev; - (void)req; - - /* Disconnect USB cable */ - disconnect_usb(); - - /* Assert boot-request pin */ - assert_boot_pin(); - - /* Reset core to enter bootloader */ - scb_reset_core(); -} - -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)) -{ - (void)dev; - (void)complete; - (void)buf; - (void)len; - - switch(req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - /* Ignore if not for GDB interface */ - if(req->wIndex != 0) - return 1; - - cdcacm_gdb_dtr = req->wValue & 1; - - return 1; - case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) - 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: - return 0; - } - case DFU_GETSTATUS: - if(req->wIndex == DFU_IF_NO) { - (*buf)[0] = DFU_STATUS_OK; - (*buf)[1] = 0; - (*buf)[2] = 0; - (*buf)[3] = 0; - (*buf)[4] = STATE_APP_IDLE; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - - return 1; - } - case DFU_DETACH: - if(req->wIndex == DFU_IF_NO) { - *complete = dfu_detach_complete; - return 1; - } - return 0; - } - return 0; -} - -int cdcacm_get_config(void) -{ - return configured; -} - -int cdcacm_get_dtr(void) -{ - return cdcacm_gdb_dtr; -} - -static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) -{ - configured = wValue; - - /* GDB interface */ -#ifdef STM32F4 - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, gdb_usb_out_cb); -#else - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); -#endif - usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, - 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); - -#if defined(PLATFORM_HAS_TRACESWO) - /* Trace interface */ - usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, - 64, trace_buf_drain); -#endif - - usbd_register_control_callback(dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); - - /* Notify the host that DCD is asserted. - * Allows the use of /dev/tty* devices on *BSD/MacOS - */ - char buf[10]; - struct usb_cdc_notification *notif = (void*)buf; - /* We echo signals back to host as notification */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - 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: */ -uint8_t usbd_control_buffer[256]; - -void cdcacm_init(void) -{ - void exti15_10_isr(void); - - get_dev_unique_id(serial_no); - - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, - sizeof(usb_strings)/sizeof(char *), - usbd_control_buffer, sizeof(usbd_control_buffer)); - - usbd_register_set_config_callback(usbdev, cdcacm_set_config); - - nvic_set_priority(USB_IRQ, IRQ_PRI_USB); - nvic_enable_irq(USB_IRQ); - setup_vbus_irq(); -} - -void USB_ISR(void) -{ - usbd_poll(usbdev); -} - -static char *get_dev_unique_id(char *s) -{ -#if defined(STM32F4) - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; -#else - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; -#endif - uint32_t unique_id = *unique_id_p + - *(unique_id_p + 1) + - *(unique_id_p + 2); - int i; - - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; - s[8] = 0; - - return s; -} diff --git a/src/platforms/stm32/serialno.c b/src/platforms/stm32/serialno.c new file mode 100644 index 0000000..ef28ed2 --- /dev/null +++ b/src/platforms/stm32/serialno.c @@ -0,0 +1,45 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "general.h" + +char *serialno_read(char *s) +{ +#if defined(STM32F4) + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; +#else + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; +#endif + uint32_t unique_id = *unique_id_p + + *(unique_id_p + 1) + + *(unique_id_p + 2); + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; + s[8] = 0; + + return s; +} + diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index ff349db..b68b1ab 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -16,7 +16,8 @@ VPATH += platforms/stm32 SRC += cdcacm.c \ platform.c \ - usbuart.c \ + usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 168ba2a..1b9a76e 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -118,7 +118,7 @@ const char *platform_target_voltage(void) return "unknown"; } -void disconnect_usb(void) +void platform_request_boot(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ rcc_periph_reset_pulse(RST_USB); @@ -127,10 +127,8 @@ void disconnect_usb(void) gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -} -void assert_boot_pin(void) -{ + /* Assert bootloader pin */ uint32_t crl = GPIOA_CRL; rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin @@ -141,4 +139,4 @@ void assert_boot_pin(void) crl |= 0x80; GPIOA_CRL = crl; } -void setup_vbus_irq(void){}; + diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index dec5548..6ee4a9c 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -146,8 +146,5 @@ extern jmp_buf fatal_error_jmpbuf; #define sprintf siprintf #define vasprintf vasiprintf -void disconnect_usb(void); -void assert_boot_pin(void); - #endif diff --git a/src/platforms/tm4c/cdcacm.c b/src/platforms/tm4c/cdcacm.c deleted file mode 100644 index 2677ad5..0000000 --- a/src/platforms/tm4c/cdcacm.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2011 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* This file implements a the USB Communications Device Class - Abstract - * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. - * A Device Firmware Upgrade (DFU 1.1) class interface is provided for - * field firmware upgrade. - * - * The device's unique id is used as the USB serial number string. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "general.h" -#include "gdb_if.h" -#if defined(PLATFORM_HAS_TRACESWO) -#include -#endif -#include - -#define DFU_IF_NO 4 - -usbd_device * usbdev; - -static char *get_dev_unique_id(char *serial_no); - -static int configured; -static int cdcacm_gdb_dtr = 1; - - -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0xEF, /* Miscellaneous Device */ - .bDeviceSubClass = 2, /* Common Class */ - .bDeviceProtocol = 1, /* Interface Association */ - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6018, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -/* This notification endpoint isn't implemented. According to CDC spec its - * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm - * driver. */ -static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x81, - .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)) gdb_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 = 1, - }, - .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 = 0, - .bSubordinateInterface0 = 1, - } -}; - -static const struct usb_interface_descriptor gdb_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 4, - - .endpoint = gdb_comm_endp, - - .extra = &gdb_cdcacm_functional_descriptors, - .extralen = sizeof(gdb_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor gdb_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = gdb_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor gdb_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 0, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .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, -}; - -const struct usb_dfu_descriptor dfu_function = { - .bLength = sizeof(struct usb_dfu_descriptor), - .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, - .wDetachTimeout = 255, - .wTransferSize = 1024, - .bcdDFUVersion = 0x011A, -}; - -const struct usb_interface_descriptor dfu_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = DFU_IF_NO, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 6, - - .extra = &dfu_function, - .extralen = sizeof(dfu_function), -}; - -static const struct usb_iface_assoc_descriptor dfu_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 4, - .bInterfaceCount = 1, - .bFunctionClass = 0xFE, - .bFunctionSubClass = 1, - .bFunctionProtocol = 1, - .iFunction = 6, -}; - -#if defined(PLATFORM_HAS_TRACESWO) -static const struct usb_endpoint_descriptor trace_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x85, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, -}}; - -const struct usb_interface_descriptor trace_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 5, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = 0xFF, - .bInterfaceSubClass = 0xFF, - .bInterfaceProtocol = 0xFF, - .iInterface = 7, - - .endpoint = trace_endp, -}; - -static const struct usb_iface_assoc_descriptor trace_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 5, - .bInterfaceCount = 1, - .bFunctionClass = 0xFF, - .bFunctionSubClass = 0xFF, - .bFunctionProtocol = 0xFF, - .iFunction = 7, -}; -#endif - -static const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .iface_assoc = &gdb_assoc, - .altsetting = gdb_comm_iface, -}, { - .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, -}, { - .num_altsetting = 1, - .iface_assoc = &dfu_assoc, - .altsetting = &dfu_iface, -#if defined(PLATFORM_HAS_TRACESWO) -}, { - .num_altsetting = 1, - .iface_assoc = &trace_assoc, - .altsetting = &trace_iface, -#endif -}}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, -#if defined(PLATFORM_HAS_TRACESWO) - .bNumInterfaces = 6, -#else - .bNumInterfaces = 5, -#endif - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - - .interface = ifaces, -}; - -char serial_no[9]; - -static const char *usb_strings[] = { - "Black Sphere Technologies", - BOARD_IDENT, - serial_no, - "Black Magic GDB Server", - "Black Magic UART Port", - DFU_IDENT, -#if defined(PLATFORM_HAS_TRACESWO) - "Black Magic Trace Capture", -#endif -}; - -static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) -{ - (void)dev; - (void)req; - - /* Disconnect USB cable */ - disconnect_usb(); - - /* Assert boot-request pin */ - //assert_boot_pin(); - - /* Reset core to enter bootloader */ - scb_reset_core(); -} - -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)) -{ - (void)dev; - (void)complete; - (void)buf; - (void)len; - - switch(req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - /* Ignore if not for GDB interface */ - if(req->wIndex != 0) - return 1; - - cdcacm_gdb_dtr = req->wValue & 1; - - return 1; - case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) - 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: - return 0; - } - case DFU_GETSTATUS: - if(req->wIndex == DFU_IF_NO) { - (*buf)[0] = DFU_STATUS_OK; - (*buf)[1] = 0; - (*buf)[2] = 0; - (*buf)[3] = 0; - (*buf)[4] = STATE_APP_IDLE; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - - return 1; - } - case DFU_DETACH: - if(req->wIndex == DFU_IF_NO) { - *complete = dfu_detach_complete; - return 1; - } - return 0; - } - return 0; -} - -int cdcacm_get_config(void) -{ - return configured; -} - -int cdcacm_get_dtr(void) -{ - return cdcacm_gdb_dtr; -} - -static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) -{ - configured = wValue; - - /* GDB interface */ - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, gdb_usb_out_cb); - usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, - 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); - -#if defined(PLATFORM_HAS_TRACESWO) - /* Trace interface */ - usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, - 64, trace_buf_drain); -#endif - - usbd_register_control_callback(dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); - - /* Notify the host that DCD is asserted. - * Allows the use of /dev/tty* devices on *BSD/MacOS - */ - char buf[10]; - struct usb_cdc_notification *notif = (void*)buf; - /* We echo signals back to host as notification */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - 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: */ -uint8_t usbd_control_buffer[256]; - -void cdcacm_init(void) -{ - get_dev_unique_id(serial_no); - - periph_clock_enable(RCC_GPIOD); - __asm__("nop"); __asm__("nop"); __asm__("nop"); - gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); - - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, - sizeof(usb_strings)/sizeof(char *), - usbd_control_buffer, sizeof(usbd_control_buffer)); - - usbd_register_set_config_callback(usbdev, cdcacm_set_config); - - usb_enable_interrupts(USB_INT_RESET|USB_INT_DISCON|USB_INT_RESUME|USB_INT_SUSPEND, - 0xff, 0xff); - nvic_set_priority(USB_IRQ, IRQ_PRI_USB); - nvic_enable_irq(USB_IRQ); - setup_vbus_irq(); -} - -void USB_ISR(void) -{ - usbd_poll(usbdev); -} - -static char *get_dev_unique_id(char *s) -{ - /* FIXME: Store a unique serial number somewhere and retreive here */ - uint32_t unique_id = 1; - int i; - - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; - s[8] = 0; - - return s; -} diff --git a/src/platforms/tm4c/traceswo.c b/src/platforms/tm4c/traceswo.c index 03c6d66..3e43a3b 100644 --- a/src/platforms/tm4c/traceswo.c +++ b/src/platforms/tm4c/traceswo.c @@ -28,6 +28,7 @@ */ #include "general.h" +#include "cdcacm.h" #include #include -- cgit v1.2.3