From 91709afcc2e94c4c185e7faa5677001497d4e031 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 18:13:18 +0100 Subject: [PATCH 01/42] More Files to ignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 305e4c25..bb584f7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +blackmagic +blackmagic.bin +blackmagic_dfu +blackmagic_dfu.bin +blackmagic_dfu.hex +mapfile *.o *.d .*.swp From 9a85146ebab1135cc412d8ace842224ef6bdbe15 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 18:14:40 +0100 Subject: [PATCH 02/42] Add explanation how toi fill the libopencm3 directory --- HACKING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HACKING b/HACKING index 0438c3c5..e79d5730 100644 --- a/HACKING +++ b/HACKING @@ -9,6 +9,11 @@ resides in the 'src' directory. Compiling for the native hardware --------------------------------- +Run +git submodule init +git submodule update +after cloning blackmagic to fill the libopencm3 directory. + To build the firmware for the standard hardware platform run 'make' in the src directory. You will require a GCC cross compiler for ARM Cortex-M3 targets. You will also need to have the libopenstm32 library installed. From ebb48245aa4c8f221044d219b321141fe63eb617 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 18:30:58 +0100 Subject: [PATCH 03/42] stlink: Use a seperate linker file as stlink has only 64 kByte --- src/platforms/stlink/Makefile.inc | 2 +- src/platforms/stm32/stlink.ld | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/platforms/stm32/stlink.ld diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index e12666bf..d298e789 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -5,7 +5,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -I../libopencm3/include LDFLAGS = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ - -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ + -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib diff --git a/src/platforms/stm32/stlink.ld b/src/platforms/stm32/stlink.ld new file mode 100644 index 00000000..ca03566d --- /dev/null +++ b/src/platforms/stm32/stlink.ld @@ -0,0 +1,28 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2010 Thomas Otto + * + * 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 . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script from libopenstm32. */ +INCLUDE libopencm3_stm32f1.ld From 16b9c1e83f5887b8572ad7f4955e586e1fc2ae9d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 18:24:58 +0100 Subject: [PATCH 04/42] stlink: Update to current libopencm3 usb api. --- src/platforms/stlink/cdcacm.c | 38 ++++++++++++++++++++++----------- src/platforms/stlink/platform.c | 6 +++--- src/platforms/stlink/platform.h | 3 +++ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/platforms/stlink/cdcacm.c b/src/platforms/stlink/cdcacm.c index db541855..a2a45106 100644 --- a/src/platforms/stlink/cdcacm.c +++ b/src/platforms/stlink/cdcacm.c @@ -27,17 +27,19 @@ */ #include -#include +#include #include #include #include #include -#include +#include #include #include #include "platform.h" +usbd_device * usbdev; + static char *get_dev_unique_id(char *serial_no); static int configured; @@ -197,9 +199,12 @@ static const char *usb_strings[] = { "Black Magic GDB Server", }; -static int cdcacm_control_request(struct usb_setup_data *req, uint8_t **buf, - uint16_t *len, void (**complete)(struct usb_setup_data *req)) +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; @@ -237,16 +242,18 @@ int cdcacm_get_dtr(void) return cdcacm_gdb_dtr; } -static void cdcacm_set_config(u16 wValue) +static void cdcacm_set_config(usbd_device *dev, u16 wValue) { configured = wValue; /* GDB interface */ - usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL); - usbd_ep_setup(0x81, USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL); - usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); + usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); + usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - usbd_register_control_callback( + usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, cdcacm_control_request); @@ -264,24 +271,29 @@ static void cdcacm_set_config(u16 wValue) notif->wLength = 2; buf[8] = 3; /* DCD | DSR */ buf[9] = 0; - usbd_ep_write_packet(0x82, buf, 10); + usbd_ep_write_packet(dev, 0x82, 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); - usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); - usbd_register_set_config_callback(cdcacm_set_config); + usbdev = usbd_init(&stm32f103_usb_driver, + &dev, &config, usb_strings, 7); + usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer)); + usbd_register_set_config_callback(usbdev, cdcacm_set_config); nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ); } void usb_lp_can_rx0_isr(void) { - usbd_poll(); + usbd_poll(usbdev); } static char *get_dev_unique_id(char *s) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 836a2e9d..f28764fc 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -23,9 +23,9 @@ */ #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index fb55441d..d804abc9 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -25,6 +25,7 @@ #define __PLATFORM_H #include +#include #include #include @@ -33,6 +34,8 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 + +extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 /* Important pin mappings for STM32 implementation: From 35d6adc236f54e94231b1959eb2d16b785c7733a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 20:44:43 +0100 Subject: [PATCH 05/42] native/usbuart: Move platform dependant parts to platform.h --- src/Makefile | 1 + src/platforms/native/Makefile.inc | 4 +- src/platforms/native/platform.c | 2 +- src/platforms/native/platform.h | 13 ++++- src/platforms/native/usbuart.c | 64 ++++++++++++----------- src/platforms/{native => stm32}/usbuart.h | 1 - 6 files changed, 50 insertions(+), 35 deletions(-) rename src/platforms/{native => stm32}/usbuart.h (99%) diff --git a/src/Makefile b/src/Makefile index 66991910..d9f3e9ee 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,6 +47,7 @@ blackmagic: $(OBJ) clean: host_clean $(RM) *.o *.d *~ blackmagic $(HOSTFILES) + $(RM) platforms/*/*.o platforms/*/*.d mapfile -include *.d diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index dc0e7433..585c50d0 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -3,7 +3,9 @@ CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ - -DSTM32F1 -I../libopencm3/include + -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include -Iplatforms/native \ + -Iplatforms/stm32 + LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 5b90976d..0f8b78ac 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -32,7 +32,7 @@ #include "platform.h" #include "jtag_scan.h" -#include "usbuart.h" +#include #include diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 17841ea9..30f063d3 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -90,6 +90,7 @@ extern usbd_device *usbdev; #define USB_VBUS_IRQ NVIC_EXTI15_10_IRQ #define LED_PORT GPIOB +#define LED_PORT_UART GPIOB #define LED_UART GPIO2 #define LED_IDLE_RUN GPIO10 #define LED_ERROR GPIO11 @@ -99,10 +100,19 @@ extern usbd_device *usbdev; * 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_USBUSART (1 << 4) #define IRQ_PRI_USB_VBUS (14 << 4) #define IRQ_PRI_TIM3 (0 << 4) +#define USBUSART USART1 +#define USBUSART_CR1 USART1_CR1 +#define USBUSART_IRQ NVIC_USART1_IRQ +#define USBUSART_APB_ENR RCC_APB2ENR +#define USBUSART_CLK_ENABLE RCC_APB2ENR_USART1EN +#define USBUSART_PORT GPIOA +#define USBUSART_TX_PIN GPIO9 +#define USBUSART_ISR usart1_isr + #define DEBUG(...) extern uint8_t running_status; @@ -174,4 +184,3 @@ static inline u16 _gpio_get(u32 gpioport, u16 gpios) #endif #endif - diff --git a/src/platforms/native/usbuart.c b/src/platforms/native/usbuart.c index 35a7d7d3..3d07b33a 100644 --- a/src/platforms/native/usbuart.c +++ b/src/platforms/native/usbuart.c @@ -26,62 +26,64 @@ #include #include -#include "platform.h" +#include void usbuart_init(void) { +#if defined(BLACKMAGIC) /* On mini hardware, UART and SWD share connector pins. * Don't enable UART if we're being debugged. */ if ((platform_hwversion() == 1) && (SCS_DEMCR & SCS_DEMCR_TRCENA)) return; +#endif - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_USART1EN); + rcc_peripheral_enable_clock(&USBUSART_APB_ENR, USBUSART_CLK_ENABLE); - /* UART1 TX to 'alternate function output push-pull' */ - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9); + /* UART TX to 'alternate function output push-pull' */ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); /* Setup UART parameters. */ - usart_set_baudrate(USART1, 38400); - usart_set_databits(USART1, 8); - usart_set_stopbits(USART1, USART_STOPBITS_1); - usart_set_mode(USART1, USART_MODE_TX_RX); - usart_set_parity(USART1, USART_PARITY_NONE); - usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_set_baudrate(USBUSART, 38400); + usart_set_databits(USBUSART, 8); + usart_set_stopbits(USBUSART, USART_STOPBITS_1); + usart_set_mode(USBUSART, USART_MODE_TX_RX); + usart_set_parity(USBUSART, USART_PARITY_NONE); + usart_set_flow_control(USBUSART, USART_FLOWCONTROL_NONE); /* Finally enable the USART. */ - usart_enable(USART1); + usart_enable(USBUSART); /* Enable interrupts */ - USART1_CR1 |= USART_CR1_RXNEIE; - nvic_set_priority(NVIC_USART1_IRQ, IRQ_PRI_USART1); - nvic_enable_irq(NVIC_USART1_IRQ); + USBUSART_CR1 |= USART_CR1_RXNEIE; + nvic_set_priority(USBUSART_IRQ, IRQ_PRI_USBUSART); + nvic_enable_irq(USBUSART_IRQ); } void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) { - usart_set_baudrate(USART1, coding->dwDTERate); - usart_set_databits(USART1, coding->bDataBits); + usart_set_baudrate(USBUSART, coding->dwDTERate); + usart_set_databits(USBUSART, coding->bDataBits); switch(coding->bCharFormat) { case 0: - usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_stopbits(USBUSART, USART_STOPBITS_1); break; case 1: - usart_set_stopbits(USART1, USART_STOPBITS_1_5); + usart_set_stopbits(USBUSART, USART_STOPBITS_1_5); break; case 2: - usart_set_stopbits(USART1, USART_STOPBITS_2); + usart_set_stopbits(USBUSART, USART_STOPBITS_2); break; } switch(coding->bParityType) { case 0: - usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_parity(USBUSART, USART_PARITY_NONE); break; case 1: - usart_set_parity(USART1, USART_PARITY_ODD); + usart_set_parity(USBUSART, USART_PARITY_ODD); break; case 2: - usart_set_parity(USART1, USART_PARITY_EVEN); + usart_set_parity(USBUSART, USART_PARITY_EVEN); break; } } @@ -94,16 +96,18 @@ void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep) int len = usbd_ep_read_packet(dev, CDCACM_UART_ENDPOINT, buf, CDCACM_PACKET_SIZE); +#if defined(BLACKMAGIC) /* Don't bother if uart is disabled. * This will be the case on mini while we're being debugged. */ if(!(RCC_APB2ENR & RCC_APB2ENR_USART1EN)) return; +#endif - gpio_set(LED_PORT, LED_UART); + gpio_set(LED_PORT_UART, LED_UART); for(int i = 0; i < len; i++) - usart_send_blocking(USART1, buf[i]); - gpio_clear(LED_PORT, LED_UART); + usart_send_blocking(USBUSART, buf[i]); + gpio_clear(LED_PORT_UART, LED_UART); } static uint8_t uart_usb_buf[CDCACM_PACKET_SIZE]; @@ -112,7 +116,7 @@ static uint8_t uart_usb_buf_size; void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep) { if (!uart_usb_buf_size) { - gpio_clear(LED_PORT, LED_UART); + gpio_clear(LED_PORT_UART, LED_UART); return; } @@ -120,11 +124,11 @@ void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep) uart_usb_buf_size = 0; } -void usart1_isr(void) +void USBUSART_ISR(void) { - char c = usart_recv(USART1); + char c = usart_recv(USBUSART); - gpio_set(LED_PORT, LED_UART); + gpio_set(LED_PORT_UART, LED_UART); /* Try to send now */ if (usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, &c, 1) == 1) diff --git a/src/platforms/native/usbuart.h b/src/platforms/stm32/usbuart.h similarity index 99% rename from src/platforms/native/usbuart.h rename to src/platforms/stm32/usbuart.h index 10cb60e3..39f7dcd9 100644 --- a/src/platforms/native/usbuart.h +++ b/src/platforms/stm32/usbuart.h @@ -31,4 +31,3 @@ void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); #endif - From 67f8176c5bcaed5cddbd84c46984d2f94e78ba3e Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 21:49:55 +0100 Subject: [PATCH 06/42] 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(-) diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index d298e789..9e72e566 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 a2a45106..1cad4d7e 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 f28764fc..26e1ad21 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 d804abc9..8f9e58ef 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 From 7188a4a8cb83529ea12ec790262d193f64a0a3c4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 12 Jan 2013 23:06:40 +0100 Subject: [PATCH 07/42] Move usbdfu to platforms/stm32 directory --- src/platforms/{native => stm32}/usbdfu.c | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) rename src/platforms/{native => stm32}/usbdfu.c (93%) diff --git a/src/platforms/native/usbdfu.c b/src/platforms/stm32/usbdfu.c similarity index 93% rename from src/platforms/native/usbdfu.c rename to src/platforms/stm32/usbdfu.c index a88ec735..d7034fb0 100644 --- a/src/platforms/native/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -29,11 +29,11 @@ #define APP_ADDRESS 0x08002000 /* Commands sent with wBlockNum == 0 as per ST implementation. */ -#define CMD_SETADDR 0x21 -#define CMD_ERASE 0x41 +#define CMD_SETADDR 0x21 +#define CMD_ERASE 0x41 -#define FLASH_OBP_RDP 0x1FFFF800 -#define FLASH_OBP_WRP10 0x1FFFF808 +#define FLASH_OBP_RDP 0x1FFFF800 +#define FLASH_OBP_WRP10 0x1FFFF808 #define FLASH_OBP_RDP_KEY 0x5aa5 @@ -88,7 +88,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. + /* The ST Microelectronics DfuSe application needs this string. * The format isn't documented... */ .iInterface = 4, @@ -128,7 +128,7 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout) { switch(usbdfu_state) { case STATE_DFU_DNLOAD_SYNC: - usbdfu_state = STATE_DFU_DNBUSY; + usbdfu_state = STATE_DFU_DNBUSY; *bwPollTimeout = 100; return DFU_STATUS_OK; @@ -165,17 +165,17 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) prog.addr = *(u32*)(prog.buf+1); } } else { - u32 baseaddr = prog.addr + - ((prog.blocknum - 2) * + u32 baseaddr = prog.addr + + ((prog.blocknum - 2) * dfu_function.wTransferSize); - for(i = 0; i < prog.len; i += 2) - flash_program_half_word(baseaddr + i, + for(i = 0; i < prog.len; i += 2) + flash_program_half_word(baseaddr + i, *(u16*)(prog.buf+i)); } flash_lock(); - /* We jump straight to dfuDNLOAD-IDLE, - * skipping dfuDNLOAD-SYNC + /* We jump straight to dfuDNLOAD-IDLE, + * skipping dfuDNLOAD-SYNC */ usbdfu_state = STATE_DFU_DNLOAD_IDLE; return; @@ -195,7 +195,7 @@ static int usbdfu_control_request(usbd_device *dev, { (void)dev; - if((req->bmRequestType & 0x7F) != 0x21) + if((req->bmRequestType & 0x7F) != 0x21) return 0; /* Only accept class request */ switch(req->bRequest) { @@ -279,13 +279,13 @@ int main(void) gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); systick_interrupt_enable(); systick_counter_enable(); - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); get_dev_unique_id(serial_no); @@ -319,7 +319,7 @@ static char *get_dev_unique_id(char *s) s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; } for(i = 0; i < 8; i++) - if(s[i] > '9') + if(s[i] > '9') s[i] += 'A' - '9' - 1; s[8] = 0; @@ -330,4 +330,3 @@ void sys_tick_handler() { gpio_toggle(GPIOB, GPIO11); /* LED2 on/off */ } - From 16ac8e0478e5c2c9049d56f9d953648100f1264d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 13 Jan 2013 18:23:24 +0100 Subject: [PATCH 08/42] stlink: Add DFU capability --- src/platforms/stlink/Makefile.inc | 20 +++++-- src/platforms/stlink/cdcacm.c | 89 ++++++++++++++++++++++++++++++- src/platforms/stm32/usbdfu.c | 56 ++++++++++++++++++- 3 files changed, 157 insertions(+), 8 deletions(-) diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 9e72e566..7cacb0e3 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -3,11 +3,12 @@ CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -mcpu=cortex-m3 -mthumb \ - -DSTM32F1 -I../libopencm3/include -Iplatforms/stlink -Iplatforms/stm32 -LDFLAGS = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ + -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include -Iplatforms/stlink -Iplatforms/stm32 +LDFLAGS_BOOT = -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 \ -L../libopencm3/lib +LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 VPATH += platforms/stm32 @@ -15,11 +16,20 @@ SRC += cdcacm.c \ platform.c \ platforms/native/usbuart.c \ -all: blackmagic.bin +all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex blackmagic.bin: blackmagic $(OBJCOPY) -O binary $^ $@ -host_clean: - -rm blackmagic.bin +blackmagic_dfu: usbdfu.o + $(CC) $^ -o $@ $(LDFLAGS_BOOT) + +blackmagic_dfu.bin: blackmagic_dfu + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu.hex: blackmagic_dfu + $(OBJCOPY) -O ihex $^ $@ + +host_clean: + -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/stlink/cdcacm.c b/src/platforms/stlink/cdcacm.c index 1cad4d7e..b051e621 100644 --- a/src/platforms/stlink/cdcacm.c +++ b/src/platforms/stlink/cdcacm.c @@ -39,6 +39,8 @@ #include "platform.h" #include +#define DFU_IF_NO 4 + usbd_device * usbdev; static char *get_dev_unique_id(char *serial_no); @@ -46,6 +48,7 @@ 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, @@ -271,6 +274,41 @@ static const struct usb_iface_assoc_descriptor uart_assoc = { .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, +}; + static const struct usb_interface ifaces[] = {{ .num_altsetting = 1, .iface_assoc = &gdb_assoc, @@ -285,13 +323,17 @@ static const struct usb_interface ifaces[] = {{ }, { .num_altsetting = 1, .altsetting = uart_data_iface, +}, { + .num_altsetting = 1, + .iface_assoc = &dfu_assoc, + .altsetting = &dfu_iface, }}; static const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, - .bNumInterfaces = 4, + .bNumInterfaces = 5, .bConfigurationValue = 1, .iConfiguration = 0, .bmAttributes = 0x80, @@ -308,8 +350,33 @@ static const char *usb_strings[] = { serial_no, "Black Magic GDB Server", "Black Magic UART Port", + "Black Magic Firmware Upgrade", }; +static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) +{ + (void)dev; + (void)req; + + /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); + + /* Assert boot-request pin */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); + + /* 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)) @@ -340,6 +407,24 @@ static int cdcacm_control_request(usbd_device *dev, 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; } @@ -405,7 +490,7 @@ void cdcacm_init(void) get_dev_unique_id(serial_no); usbdev = usbd_init(&stm32f103_usb_driver, - &dev, &config, usb_strings, 5); + &dev, &config, usb_strings, 6); usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer)); usbd_register_set_config_callback(usbdev, cdcacm_set_config); diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index d7034fb0..6aea11a3 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -41,6 +41,10 @@ usbd_device *usbdev; /* We need a special large control buffer for this device: */ u8 usbd_control_buffer[1024]; +#if defined(DISCOVERY_STLINK) +u32 led2_state = 0; +#endif + static enum dfu_state usbdfu_state = STATE_DFU_IDLE; static char *get_dev_unique_id(char *serial_no); @@ -118,7 +122,11 @@ static char serial_no[9]; static const char *usb_strings[] = { "Black Sphere Technologies", +#if defined(DISCOVERY_STLINK) + "Black Magic (Upgrade) for STLink/Discovery", +#else "Black Magic Probe (Upgrade)", +#endif serial_no, /* This string is used by ST Microelectronics' DfuSe utility */ "@Internal Flash /0x08000000/8*001Ka,120*001Kg" @@ -181,7 +189,19 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) return; case STATE_DFU_MANIFEST: - /* USB device must detach, we just reset... */ +#if defined (DISCOVERY_STLINK) + /* Disconnect USB cable by resetting USB Device + and pulling USB_DP low*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); +#else + /* USB device must detach, we just reset... */ +#endif scb_reset_system(); return; /* Will never return */ default: @@ -250,8 +270,13 @@ static int usbdfu_control_request(usbd_device *dev, int main(void) { +#if defined (DISCOVERY_STLINK) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + if(!gpio_get(GPIOC, GPIO13)) { +#else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); if(gpio_get(GPIOB, GPIO12)) { +#endif /* Boot the application if it's valid */ if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { /* Set vector table base address */ @@ -272,15 +297,31 @@ int main(void) flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } +#if defined (DISCOVERY_STLINK) + /* Just in case: Disconnect USB cable by resetting USB Device + and pulling USB_DP low*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); +#endif rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); +#if defined(DISCOVERY_STLINK) + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, GPIO0); +#else gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); +#endif systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); systick_interrupt_enable(); @@ -298,9 +339,11 @@ int main(void) USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, usbdfu_control_request); +#if defined(BLACKMAGIG) gpio_set(GPIOA, GPIO8); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8); +#endif while (1) usbd_poll(usbdev); @@ -328,5 +371,16 @@ static char *get_dev_unique_id(char *s) void sys_tick_handler() { +#if defined(DISCOVERY_STLINK) + if (led2_state & 1) + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO9); + else + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, GPIO9); + led2_state++; +#else gpio_toggle(GPIOB, GPIO11); /* LED2 on/off */ +#endif } + From 533608a2f4b2e0c19cb2f696fc491908ec980812 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 13 Jan 2013 18:37:32 +0100 Subject: [PATCH 09/42] Move usbuart to the stm32 directory --- src/{platforms/stm32 => include}/usbuart.h | 0 src/platforms/native/Makefile.inc | 3 +-- src/platforms/stlink/Makefile.inc | 4 ++-- src/platforms/{native => stm32}/usbuart.c | 5 ++--- 4 files changed, 5 insertions(+), 7 deletions(-) rename src/{platforms/stm32 => include}/usbuart.h (100%) rename src/platforms/{native => stm32}/usbuart.c (97%) diff --git a/src/platforms/stm32/usbuart.h b/src/include/usbuart.h similarity index 100% rename from src/platforms/stm32/usbuart.h rename to src/include/usbuart.h diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 585c50d0..36ee01cd 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -3,8 +3,7 @@ CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ - -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include -Iplatforms/native \ - -Iplatforms/stm32 + -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 7cacb0e3..0f784f50 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 -DDISCOVERY_STLINK -I../libopencm3/include -Iplatforms/stlink -Iplatforms/stm32 + -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include LDFLAGS_BOOT = -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 \ @@ -14,7 +14,7 @@ VPATH += platforms/stm32 SRC += cdcacm.c \ platform.c \ - platforms/native/usbuart.c \ + usbuart.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/native/usbuart.c b/src/platforms/stm32/usbuart.c similarity index 97% rename from src/platforms/native/usbuart.c rename to src/platforms/stm32/usbuart.c index 3d07b33a..27dbaa2f 100644 --- a/src/platforms/native/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -98,9 +98,9 @@ void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep) #if defined(BLACKMAGIC) /* Don't bother if uart is disabled. - * This will be the case on mini while we're being debugged. + * This will be the case on mini while we're being debugged. */ - if(!(RCC_APB2ENR & RCC_APB2ENR_USART1EN)) + if(!(RCC_APB2ENR & RCC_APB2ENR_USART1EN)) return; #endif @@ -142,4 +142,3 @@ void USBUSART_ISR(void) uart_usb_buf[uart_usb_buf_size++] = c; } - From 04415582bd19c3a33b938f88594b9c4d79b41d18 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 13 Jan 2013 19:15:16 +0100 Subject: [PATCH 10/42] cdcacm: move non-constant parts to platform.[hc] --- src/platforms/native/cdcacm.c | 67 +++++++++---------------- src/platforms/native/platform.c | 42 ++++++++++++++++ src/platforms/native/platform.h | 6 +++ src/platforms/stlink/cdcacm.c | 86 +++++++++++++++++++++++++++------ src/platforms/stlink/platform.c | 21 ++++++++ src/platforms/stlink/platform.h | 4 ++ 6 files changed, 167 insertions(+), 59 deletions(-) diff --git a/src/platforms/native/cdcacm.c b/src/platforms/native/cdcacm.c index bfe1006b..2bcaf160 100644 --- a/src/platforms/native/cdcacm.c +++ b/src/platforms/native/cdcacm.c @@ -26,10 +26,9 @@ * The device's unique id is used as the USB serial number string. */ -#include +#include #include -#include -#include +#include #include #include #include @@ -37,8 +36,10 @@ #include #include "platform.h" +#if defined(PLATFORM_HAS_TRACESWO) #include "traceswo.h" -#include "usbuart.h" +#endif +#include #define DFU_IF_NO 4 @@ -310,6 +311,7 @@ static const struct usb_iface_assoc_descriptor dfu_assoc = { .iFunction = 6, }; +#if defined(PLATFORM_HAS_TRACESWO) static const struct usb_endpoint_descriptor trace_endp[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -343,6 +345,7 @@ static const struct usb_iface_assoc_descriptor trace_assoc = { .bFunctionProtocol = 0xFF, .iFunction = 7, }; +#endif static const struct usb_interface ifaces[] = {{ .num_altsetting = 1, @@ -362,17 +365,23 @@ static const struct usb_interface ifaces[] = {{ .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, @@ -390,7 +399,9 @@ static const char *usb_strings[] = { "Black Magic GDB Server", "Black Magic UART Port", "Black Magic Firmware Upgrade", +#if defined(PLATFORM_HAS_TRACESWO) "Black Magic Trace Capture", +#endif }; static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) @@ -399,12 +410,10 @@ static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) (void)req; /* Disconnect USB cable */ - gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); + disconnect_usb(); /* Assert boot-request pin */ - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); - gpio_clear(GPIOB, GPIO12); + assert_boot_pin(); /* Reset core to enter bootloader */ scb_reset_core(); @@ -490,9 +499,11 @@ static void cdcacm_set_config(usbd_device *dev, u16 wValue) 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, @@ -526,50 +537,20 @@ void cdcacm_init(void) get_dev_unique_id(serial_no); - usbdev = usbd_init(&stm32f103_usb_driver, - &dev, &config, usb_strings, 7); + usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, sizeof(usb_strings)/sizeof(char *)); 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); - nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); - nvic_enable_irq(USB_VBUS_IRQ); - - gpio_set(USB_VBUS_PORT, USB_VBUS_PIN); - gpio_set(USB_PU_PORT, USB_PU_PIN); - - gpio_set_mode(USB_VBUS_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, USB_VBUS_PIN); - - /* Configure EXTI for USB VBUS monitor */ - exti_select_source(USB_VBUS_PIN, USB_VBUS_PORT); - exti_set_trigger(USB_VBUS_PIN, EXTI_TRIGGER_BOTH); - exti_enable_request(USB_VBUS_PIN); - - exti15_10_isr(); + nvic_set_priority(USB_IRQ, IRQ_PRI_USB); + nvic_enable_irq(USB_IRQ); + setup_vbus_irq(); } -void usb_lp_can_rx0_isr(void) +void USB_ISR(void) { usbd_poll(usbdev); } -void exti15_10_isr(void) -{ - if (gpio_get(USB_VBUS_PORT, USB_VBUS_PIN)) { - /* Drive pull-up high if VBUS connected */ - gpio_set_mode(USB_PU_PORT, GPIO_MODE_OUTPUT_10_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, USB_PU_PIN); - } else { - /* Allow pull-up to float if VBUS disconnected */ - gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, USB_PU_PIN); - } - - exti_reset_request(USB_VBUS_PIN); -} - static char *get_dev_unique_id(char *s) { volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 0f8b78ac..8ded81ad 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -262,3 +263,44 @@ const char *platform_target_voltage(void) return ret; } + +void assert_boot_pin(void) +{ + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + gpio_clear(GPIOB, GPIO12); +} + +void exti15_10_isr(void) +{ + if (gpio_get(USB_VBUS_PORT, USB_VBUS_PIN)) { + /* Drive pull-up high if VBUS connected */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_OUTPUT_10_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, USB_PU_PIN); + } else { + /* Allow pull-up to float if VBUS disconnected */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, USB_PU_PIN); + } + + exti_reset_request(USB_VBUS_PIN); +} + +void setup_vbus_irq(void) +{ + nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); + nvic_enable_irq(USB_VBUS_IRQ); + + gpio_set(USB_VBUS_PORT, USB_VBUS_PIN); + gpio_set(USB_PU_PORT, USB_PU_PIN); + + gpio_set_mode(USB_VBUS_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, USB_VBUS_PIN); + + /* Configure EXTI for USB VBUS monitor */ + exti_select_source(USB_VBUS_PIN, USB_VBUS_PORT); + exti_set_trigger(USB_VBUS_PIN, EXTI_TRIGGER_BOTH); + exti_enable_request(USB_VBUS_PIN); + + exti15_10_isr(); +} diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 30f063d3..538d29c3 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -95,6 +95,8 @@ extern usbd_device *usbdev; #define LED_IDLE_RUN GPIO10 #define LED_ERROR GPIO11 +#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ +#define USB_ISR usb_lp_can_rx0_isr /* 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. @@ -184,3 +186,7 @@ static inline u16 _gpio_get(u32 gpioport, u16 gpios) #endif #endif + +#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); diff --git a/src/platforms/stlink/cdcacm.c b/src/platforms/stlink/cdcacm.c index b051e621..840b7bc8 100644 --- a/src/platforms/stlink/cdcacm.c +++ b/src/platforms/stlink/cdcacm.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -37,6 +36,9 @@ #include #include "platform.h" +#if defined(PLATFORM_HAS_TRACESWO) +#include "traceswo.h" +#endif #include #define DFU_IF_NO 4 @@ -309,6 +311,42 @@ static const struct usb_iface_assoc_descriptor dfu_assoc = { .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, @@ -327,13 +365,23 @@ static const struct usb_interface ifaces[] = {{ .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, @@ -351,6 +399,9 @@ static const char *usb_strings[] = { "Black Magic GDB Server", "Black Magic UART Port", "Black Magic Firmware Upgrade", +#if defined(PLATFORM_HAS_TRACESWO) + "Black Magic Trace Capture", +#endif }; static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) @@ -358,20 +409,11 @@ static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) (void)dev; (void)req; - /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - gpio_clear(GPIOA, GPIO12); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); + /* Disconnect USB cable */ + disconnect_usb(); /* Assert boot-request pin */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); - gpio_set(GPIOC, GPIO13); + assert_boot_pin(); /* Reset core to enter bootloader */ scb_reset_core(); @@ -457,6 +499,12 @@ static void cdcacm_set_config(usbd_device *dev, u16 wValue) 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, @@ -490,12 +538,18 @@ void cdcacm_init(void) get_dev_unique_id(serial_no); usbdev = usbd_init(&stm32f103_usb_driver, - &dev, &config, usb_strings, 6); +#if defined(PLATFORM_HAS_TRACESWO) + &dev, &config, usb_strings, 6 +#else + &dev, &config, usb_strings, 7 +#endif + ); 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); + nvic_set_priority(USB_IRQ, IRQ_PRI_USB); + nvic_enable_irq(USB_IRQ); + setup_vbus_irq(); } void usb_lp_can_rx0_isr(void) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 26e1ad21..70ca6788 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -108,3 +108,24 @@ const char *platform_target_voltage(void) { return "unknown"; } + +void disconnect_usb(void) +{ + /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); +} + +void assert_boot_pin(void) +{ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); +} +void setup_vbus_irq(void){}; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 8f9e58ef..0ef1bd65 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -81,6 +81,8 @@ extern usbd_device *usbdev; #define LED_UART GPIO14 #define LED_IDLE_RUN GPIO8 +#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ +#define USB_ISR usb_lp_can_rx0_isr /* 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. @@ -168,3 +170,5 @@ static inline u16 _gpio_get(u32 gpioport, u16 gpios) #endif +void disconnect_usb(void); +void assert_boot_pin(void); From 30d8aa1eb770592d0bb35520c6b9dd1739ea66b1 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 13 Jan 2013 19:19:36 +0100 Subject: [PATCH 11/42] Move (now-constant) cdcacm.c to platforms/stm32 --- src/platforms/stlink/cdcacm.c | 579 ----------------------- src/platforms/{native => stm32}/cdcacm.c | 31 +- 2 files changed, 15 insertions(+), 595 deletions(-) delete mode 100644 src/platforms/stlink/cdcacm.c rename src/platforms/{native => stm32}/cdcacm.c (97%) diff --git a/src/platforms/stlink/cdcacm.c b/src/platforms/stlink/cdcacm.c deleted file mode 100644 index 840b7bc8..00000000 --- a/src/platforms/stlink/cdcacm.c +++ /dev/null @@ -1,579 +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 "platform.h" -#if defined(PLATFORM_HAS_TRACESWO) -#include "traceswo.h" -#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", - "Black Magic Probe", - serial_no, - "Black Magic GDB Server", - "Black Magic UART Port", - "Black Magic Firmware Upgrade", -#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, u16 wValue) -{ - configured = wValue; - - /* GDB interface */ - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); - 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(&stm32f103_usb_driver, -#if defined(PLATFORM_HAS_TRACESWO) - &dev, &config, usb_strings, 6 -#else - &dev, &config, usb_strings, 7 -#endif - ); - usbd_set_control_buffer_size(usbdev, 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_lp_can_rx0_isr(void) -{ - usbd_poll(usbdev); -} - -static char *get_dev_unique_id(char *s) -{ - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; - 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/native/cdcacm.c b/src/platforms/stm32/cdcacm.c similarity index 97% rename from src/platforms/native/cdcacm.c rename to src/platforms/stm32/cdcacm.c index 2bcaf160..2bbdcb62 100644 --- a/src/platforms/native/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -19,10 +19,10 @@ */ /* 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 + * 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. */ @@ -68,8 +68,8 @@ static const struct usb_device_descriptor dev = { .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 +/* 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, @@ -109,7 +109,7 @@ static const struct { .bcdCDC = 0x0110, }, .call_mgmt = { - .bFunctionLength = + .bFunctionLength = sizeof(struct usb_cdc_call_management_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, @@ -127,7 +127,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, .bControlInterface = 0, - .bSubordinateInterface0 = 1, + .bSubordinateInterface0 = 1, } }; @@ -212,7 +212,7 @@ static const struct { .bcdCDC = 0x0110, }, .call_mgmt = { - .bFunctionLength = + .bFunctionLength = sizeof(struct usb_cdc_call_management_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, @@ -230,7 +230,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, .bControlInterface = 2, - .bSubordinateInterface0 = 3, + .bSubordinateInterface0 = 3, } }; @@ -429,7 +429,7 @@ static int cdcacm_control_request(usbd_device *dev, (void)len; switch(req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* Ignore if not for GDB interface */ if(req->wIndex != 0) return 1; @@ -437,8 +437,8 @@ static int cdcacm_control_request(usbd_device *dev, cdcacm_gdb_dtr = req->wValue & 1; return 1; - case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) + case USB_CDC_REQ_SET_LINE_CODING: + if(*len < sizeof(struct usb_cdc_line_coding)) return 0; switch(req->wIndex) { @@ -449,7 +449,7 @@ static int cdcacm_control_request(usbd_device *dev, default: return 0; } - case DFU_GETSTATUS: + case DFU_GETSTATUS: if(req->wIndex == DFU_IF_NO) { (*buf)[0] = DFU_STATUS_OK; (*buf)[1] = 0; @@ -551,7 +551,7 @@ void USB_ISR(void) usbd_poll(usbdev); } -static char *get_dev_unique_id(char *s) +static char *get_dev_unique_id(char *s) { volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; uint32_t unique_id = *unique_id_p + @@ -564,10 +564,9 @@ static char *get_dev_unique_id(char *s) s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; } for(i = 0; i < 8; i++) - if(s[i] > '9') + if(s[i] > '9') s[i] += 'A' - '9' - 1; s[8] = 0; return s; } - From 1eb9bfc6509efdcd722d17b1fe3fe97efc93593c Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 14 Jan 2013 00:05:03 +0100 Subject: [PATCH 12/42] platforms/stm32: Move more platform dependencies to platform.h --- src/platforms/native/platform.h | 1 + src/platforms/stlink/platform.h | 1 + src/platforms/stm32/usbdfu.c | 12 ++++++++++-- src/platforms/stm32/usbuart.c | 4 ++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 538d29c3..d9721dcf 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -95,6 +95,7 @@ extern usbd_device *usbdev; #define LED_IDLE_RUN GPIO10 #define LED_ERROR GPIO11 +#define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 0ef1bd65..ffea6762 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -81,6 +81,7 @@ extern usbd_device *usbdev; #define LED_UART GPIO14 #define LED_IDLE_RUN GPIO8 +#define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 6aea11a3..12bb26cb 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -19,9 +19,17 @@ #include #include -#include -#include +#include +#include +#if defined(STM32F1) #include +#elif defined(STM32F2) +#include +#elif defined(STM32F4) +#include +#else +#warning "Unhandled STM32 family" +#endif #include #include #include diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 27dbaa2f..68dac60b 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -18,8 +18,8 @@ * along with this program. If not, see . */ -#include -#include +#include +#include #include #include #include From 313a24b31676e4d74362f9280e54d467815e7514 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 15 Jan 2013 15:20:42 +0100 Subject: [PATCH 13/42] usbdfu: Allow for different, but constant flash page sizes --- src/platforms/stm32/usbdfu.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 12bb26cb..f809a2a4 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -158,6 +158,13 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout) } } +#if defined (STM32_CAN) +#define FLASHBLOCKSIZE 2048 +#else +#define FLASHBLOCKSIZE 1024 +#endif +static uint32_t last_erased_pages=0xffffffff; + static void usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) { @@ -175,8 +182,15 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) return; } switch(prog.buf[0]) { - case CMD_ERASE: - flash_erase_page(*(u32*)(prog.buf+1)); + case CMD_ERASE: { + u32 page_start = *(u32*)(prog.buf+1); + + page_start &= (~(FLASHBLOCKSIZE-1)); + if (page_start != last_erased_pages) { + flash_erase_page(page_start); + last_erased_pages = page_start; + } + } case CMD_SETADDR: prog.addr = *(u32*)(prog.buf+1); } From 72ca77af530047c47646d0450f8a759d2ed595a1 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 15 Jan 2013 16:55:24 +0100 Subject: [PATCH 14/42] stm32_can: Changes to get blackmagic to work --- src/platforms/stm32/stm32_can.ld | 28 ++++ src/platforms/stm32/usbdfu.c | 38 +++++- src/platforms/stm32_can/Makefile.inc | 35 +++++ src/platforms/stm32_can/platform.c | 197 +++++++++++++++++++++++++++ src/platforms/stm32_can/platform.h | 180 ++++++++++++++++++++++++ 5 files changed, 474 insertions(+), 4 deletions(-) create mode 100644 src/platforms/stm32/stm32_can.ld create mode 100644 src/platforms/stm32_can/Makefile.inc create mode 100644 src/platforms/stm32_can/platform.c create mode 100644 src/platforms/stm32_can/platform.h diff --git a/src/platforms/stm32/stm32_can.ld b/src/platforms/stm32/stm32_can.ld new file mode 100644 index 00000000..86861b8d --- /dev/null +++ b/src/platforms/stm32/stm32_can.ld @@ -0,0 +1,28 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2010 Thomas Otto + * + * 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 . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* Include the common ld script from libopenstm32. */ +INCLUDE libopencm3_stm32f1.ld diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index f809a2a4..e33eddb1 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -130,14 +130,26 @@ static char serial_no[9]; static const char *usb_strings[] = { "Black Sphere Technologies", -#if defined(DISCOVERY_STLINK) - "Black Magic (Upgrade) for STLink/Discovery", -#else +#if defined(BLACKMAGIC) "Black Magic Probe (Upgrade)", +#elif defined(DISCOVERY_STLINK) + "Black Magic (Upgrade) for STLink/Discovery", +#elif defined(STM32_CAN) + "Black Magic (Upgrade) for STM32_CAN", +#else +#warning "Unhandled board" #endif serial_no, /* This string is used by ST Microelectronics' DfuSe utility */ +#if defined(BLACKMAGIC) "@Internal Flash /0x08000000/8*001Ka,120*001Kg" +#elif defined(DISCOVERY_STLINK) + "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +#elif defined(STM32_CAN) + "@Internal Flash /0x08000000/4*002Ka,124*002Kg" +#else +#warning "Unhandled board" +#endif }; static u8 usbdfu_getstatus(u32 *bwPollTimeout) @@ -190,6 +202,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_erase_page(page_start); last_erased_pages = page_start; } + } case CMD_SETADDR: prog.addr = *(u32*)(prog.buf+1); @@ -295,6 +308,9 @@ int main(void) #if defined (DISCOVERY_STLINK) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); if(!gpio_get(GPIOC, GPIO13)) { +#elif defined (STM32_CAN) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + if(!gpio_get(GPIOA, GPIO0)) { #else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); if(gpio_get(GPIOB, GPIO12)) { @@ -316,6 +332,8 @@ int main(void) FLASH_CR = 0; flash_erase_option_bytes(); flash_program_option_bytes(FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); + /* CL Device: Protect 2 bits with (2 * 2k pages each)*/ + /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } @@ -332,13 +350,18 @@ int main(void) #endif rcc_clock_setup_in_hse_8mhz_out_72mhz(); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); #if defined(DISCOVERY_STLINK) gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0); +#elif defined (STM32_CAN) + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); #else + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, @@ -353,8 +376,13 @@ int main(void) get_dev_unique_id(serial_no); +#if defined(STM32_CAN) + usbdev = usbd_init(&stm32f107_usb_driver, + &dev, &config, usb_strings, 4); +#else usbdev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings, 4); +#endif usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer)); usbd_register_control_callback(usbdev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, @@ -401,6 +429,8 @@ void sys_tick_handler() gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO9); led2_state++; +#elif defined(STM32_CAN) + gpio_toggle(GPIOB, GPIO0); /* LED2 on/off */ #else gpio_toggle(GPIOB, GPIO11); /* LED2 on/off */ #endif diff --git a/src/platforms/stm32_can/Makefile.inc b/src/platforms/stm32_can/Makefile.inc new file mode 100644 index 00000000..6365ce14 --- /dev/null +++ b/src/platforms/stm32_can/Makefile.inc @@ -0,0 +1,35 @@ +CROSS_COMPILE ?= arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ + -DSTM32F1 -DSTM32_CAN -I../libopencm3/include + +LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20010000 \ + -Wl,-T,platforms/stm32/stm32_can.ld -nostartfiles -lc -lnosys \ + -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ + -L../libopencm3/lib +LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 + +VPATH += platforms/stm32 + +SRC += cdcacm.c \ + platform.c \ + usbuart.c \ + +all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex + +blackmagic.bin: blackmagic + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu: usbdfu.o + $(CC) $^ -o $@ $(LDFLAGS_BOOT) + +blackmagic_dfu.bin: blackmagic_dfu + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu.hex: blackmagic_dfu + $(OBJCOPY) -O ihex $^ $@ + +host_clean: + -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/stm32_can/platform.c b/src/platforms/stm32_can/platform.c new file mode 100644 index 00000000..e93d3be3 --- /dev/null +++ b/src/platforms/stm32_can/platform.c @@ -0,0 +1,197 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform.h" +#include "jtag_scan.h" +#include + +#include + +uint8_t running_status; +volatile uint32_t timeout_counter; + +jmp_buf fatal_error_jmpbuf; + +static void morse_update(void); + +int platform_init(void) +{ + + /* Enable peripherals */ + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); + 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_IOPCEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + /* Setup GPIO ports */ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + TMS_PIN); + + gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + TCK_PIN | TDI_PIN); + + gpio_set_mode(TCK_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, + TDO_PIN); + + gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + LED_UART | LED_IDLE_RUN | LED_ERROR); + + /* 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); + + return 0; +} + +void platform_delay(uint32_t delay) +{ + timeout_counter = delay; + while(timeout_counter); +} + +void sys_tick_handler(void) +{ + if(running_status) + gpio_toggle(LED_PORT, LED_IDLE_RUN); + + if(timeout_counter) + timeout_counter--; + + morse_update(); +} + + +/* Morse code patterns and lengths */ +static const struct { + uint16_t code; + uint8_t bits; +} morse_letter[] = { + { 0b00011101, 8}, // 'A' .- + { 0b000101010111, 12}, // 'B' -... + { 0b00010111010111, 14}, // 'C' -.-. + { 0b0001010111, 10}, // 'D' -.. + { 0b0001, 4}, // 'E' . + { 0b000101110101, 12}, // 'F' ..-. + { 0b000101110111, 12}, // 'G' --. + { 0b0001010101, 10}, // 'H' .... + { 0b000101, 6}, // 'I' .. + {0b0001110111011101, 16}, // 'J' .--- + { 0b000111010111, 12}, // 'K' -.- + { 0b000101011101, 12}, // 'L' .-.. + { 0b0001110111, 10}, // 'M' -- + { 0b00010111, 8}, // 'N' -. + { 0b00011101110111, 14}, // 'O' --- + { 0b00010111011101, 14}, // 'P' .--. + {0b0001110101110111, 16}, // 'Q' --.- + { 0b0001011101, 10}, // 'R' .-. + { 0b00010101, 8}, // 'S' ... + { 0b000111, 6}, // 'T' - + { 0b0001110101, 10}, // 'U' ..- + { 0b000111010101, 12}, // 'V' ...- + { 0b000111011101, 12}, // 'W' .-- + { 0b00011101010111, 14}, // 'X' -..- + {0b0001110111010111, 16}, // 'Y' -.-- + { 0b00010101110111, 14}, // 'Z' --.. +}; + + +const char *morse_msg; +static const char * volatile morse_ptr; +static char morse_repeat; + +void morse(const char *msg, char repeat) +{ + morse_msg = morse_ptr = msg; + morse_repeat = repeat; + SET_ERROR_STATE(0); +} +static void morse_update(void) +{ + static uint16_t code; + static uint8_t bits; + + if(!morse_ptr) return; + + if(!bits) { + char c = *morse_ptr++; + if(!c) { + if(morse_repeat) { + morse_ptr = morse_msg; + c = *morse_ptr++; + } else { + morse_ptr = 0; + return; + } + } + if((c >= 'A') && (c <= 'Z')) { + c -= 'A'; + code = morse_letter[c].code; + bits = morse_letter[c].bits; + } else { + code = 0; bits = 4; + } + } + SET_ERROR_STATE(code & 1); + code >>= 1; bits--; +} + +const char *platform_target_voltage(void) +{ + return "ABSENT!"; + +} + +void assert_boot_pin(void) +{ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); + gpio_set(GPIOA, GPIO0); +} diff --git a/src/platforms/stm32_can/platform.h b/src/platforms/stm32_can/platform.h new file mode 100644 index 00000000..cf08b543 --- /dev/null +++ b/src/platforms/stm32_can/platform.h @@ -0,0 +1,180 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ +#ifndef __PLATFORM_H +#define __PLATFORM_H + +#include +#include + +#include +#include + +#include "gdb_packet.h" + +#define INLINE_GPIO +#define CDCACM_PACKET_SIZE 64 +/*#define PLATFORM_HAS_TRACESWO*/ + +extern usbd_device *usbdev; +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +/* Important pin mappings for STM32 implementation: + * + * LED0 = PB2 (Yellow LED : Running) + * LED1 = PB10 (Yellow LED : Idle) + * LED2 = PB11 (Red LED : Error) + * + * TPWR = RB0 (input) -- analogue on mini design ADC1, ch8 + * nTRST = PC9 + * SRST_OUT = NA + * TDI = PC12 + * TMS = PB14(input for SWDP) + * TCK = PC10 + * TDO = PC11(input) + * nSRST = PA7 (input) + * + * Force DFU mode button: PA0 Read High for Bootloader Req + */ + +/* Hardware definitions... */ +#define TDI_PORT GPIOC +#define TMS_PORT GPIOB +#define TCK_PORT GPIOC +#define TDO_PORT GPIOC +#define TDI_PIN GPIO12 +#define TMS_PIN GPIO14 +#define TCK_PIN GPIO10 +#define TDO_PIN GPIO11 + +#define SWDIO_PORT TMS_PORT +#define SWCLK_PORT TCK_PORT +#define SWDIO_PIN TMS_PIN +#define SWCLK_PIN TCK_PIN + +//#define TRST_PORT GPIOC +//#define TRST_PIN GPIO9 + +#define LED_PORT GPIOB +#define LED_PORT_UART GPIOB +#define LED_UART GPIO0 + +#define LED_IDLE_RUN GPIO1 +#define LED_ERROR GPIO12 + +#define USB_DRIVER stm32f107_usb_driver +#define USB_IRQ NVIC_OTG_FS_IRQ +#define USB_ISR otg_fs_isr +/* 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_USBUSART (1 << 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; +extern volatile uint32_t timeout_counter; + +extern jmp_buf fatal_error_jmpbuf; + +extern const char *morse_msg; + +#define gpio_set_val(port, pin, val) do { \ + if(val) \ + gpio_set((port), (pin)); \ + else \ + gpio_clear((port), (pin)); \ +} while(0) + +#define SET_RUN_STATE(state) {running_status = (state);} +#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} +#define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} + +#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} +#define PLATFORM_FATAL_ERROR(error) { \ + if(running_status) gdb_putpacketz("X1D"); \ + else gdb_putpacketz("EFF"); \ + running_status = 0; \ + target_list_free(); \ + morse("TARGET LOST.", 1); \ + longjmp(fatal_error_jmpbuf, (error)); \ +} + +int platform_init(void); +void morse(const char *msg, char repeat); +const char *platform_target_voltage(void); +int platform_hwversion(void); +void platform_delay(uint32_t delay); + +/* */ +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +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 +#define vasprintf vasiprintf + +#ifdef INLINE_GPIO +static inline void _gpio_set(u32 gpioport, u16 gpios) +{ + GPIO_BSRR(gpioport) = gpios; +} +#define gpio_set _gpio_set + +static inline void _gpio_clear(u32 gpioport, u16 gpios) +{ + GPIO_BRR(gpioport) = gpios; +} +#define gpio_clear _gpio_clear + +static inline u16 _gpio_get(u32 gpioport, u16 gpios) +{ + return (u16)GPIO_IDR(gpioport) & gpios; +} +#define gpio_get _gpio_get +#endif + +#endif + +#define disconnect_usb() usbd_disconnect(usbdev,1) +void assert_boot_pin(void); +#define setup_vbus_irq() From 09715e1db84560e1669a4ee36d99ce4770cdd85d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 16 Jan 2013 16:32:10 +0100 Subject: [PATCH 15/42] traceswo: factor out platform dependant parts --- src/platforms/native/platform.h | 7 ++++- src/platforms/native/traceswo.c | 49 +++++++++++++++++---------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index d9721dcf..d22e6417 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -105,7 +105,7 @@ extern usbd_device *usbdev; #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 IRQ_PRI_TRACE (0 << 4) #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 @@ -116,6 +116,11 @@ extern usbd_device *usbdev; #define USBUSART_TX_PIN GPIO9 #define USBUSART_ISR usart1_isr +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR tim3_isr + #define DEBUG(...) extern uint8_t running_status; diff --git a/src/platforms/native/traceswo.c b/src/platforms/native/traceswo.c index 2e450d4c..7cd42d1c 100644 --- a/src/platforms/native/traceswo.c +++ b/src/platforms/native/traceswo.c @@ -40,12 +40,13 @@ #include #include +#include "platform.h" void traceswo_init(void) { - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN); + TRACE_TIM_CLK_EN(); - timer_reset(TIM3); + timer_reset(TRACE_TIM); /* Refer to ST doc RM0008 - STM32F10xx Reference Manual. * Section 14.3.4 - 14.3.6 (General Purpose Timer - Input Capture) @@ -54,29 +55,29 @@ void traceswo_init(void) */ /* Use TI1 as capture input for CH1 and CH2 */ - timer_ic_set_input(TIM3, TIM_IC1, TIM_IC_IN_TI1); - timer_ic_set_input(TIM3, TIM_IC2, TIM_IC_IN_TI1); + timer_ic_set_input(TRACE_TIM, TIM_IC1, TIM_IC_IN_TI1); + timer_ic_set_input(TRACE_TIM, TIM_IC2, TIM_IC_IN_TI1); /* Capture CH1 on rising edge, CH2 on falling edge */ - timer_ic_set_polarity(TIM3, TIM_IC1, TIM_IC_RISING); - timer_ic_set_polarity(TIM3, TIM_IC2, TIM_IC_FALLING); + timer_ic_set_polarity(TRACE_TIM, TIM_IC1, TIM_IC_RISING); + timer_ic_set_polarity(TRACE_TIM, TIM_IC2, TIM_IC_FALLING); /* Trigger on Filtered Timer Input 1 (TI1FP1) */ - timer_slave_set_trigger(TIM3, TIM_SMCR_TS_IT1FP1); + timer_slave_set_trigger(TRACE_TIM, TIM_SMCR_TS_IT1FP1); /* Slave reset mode: reset counter on trigger */ - timer_slave_set_mode(TIM3, TIM_SMCR_SMS_RM); + timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_RM); /* Enable capture interrupt */ - nvic_set_priority(NVIC_TIM3_IRQ, IRQ_PRI_TIM3); - nvic_enable_irq(NVIC_TIM3_IRQ); - timer_enable_irq(TIM3, TIM_DIER_CC1IE); + nvic_set_priority(TRACE_IRQ, IRQ_PRI_TRACE); + nvic_enable_irq(TRACE_IRQ); + timer_enable_irq(TRACE_TIM, TIM_DIER_CC1IE); /* Enable the capture channels */ - timer_ic_enable(TIM3, TIM_IC1); - timer_ic_enable(TIM3, TIM_IC2); + timer_ic_enable(TRACE_TIM, TIM_IC1); + timer_ic_enable(TRACE_TIM, TIM_IC2); - timer_enable_counter(TIM3); + timer_enable_counter(TRACE_TIM); } static uint8_t trace_usb_buf[64]; @@ -107,9 +108,9 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) #define ALLOWED_DUTY_ERROR 5 -void tim3_isr(void) +void trace_isr(void) { - uint16_t sr = TIM_SR(TIM3); + uint16_t sr = TIM_SR(TRACE_TIM); uint16_t duty, cycle; static uint16_t bt; static uint8_t lastbit; @@ -120,13 +121,13 @@ void tim3_isr(void) /* Reset decoder state if capture overflowed */ if (sr & (TIM_SR_CC1OF | TIM_SR_UIF)) { - timer_clear_flag(TIM3, TIM_SR_CC1OF | TIM_SR_UIF); + timer_clear_flag(TRACE_TIM, TIM_SR_CC1OF | TIM_SR_UIF); if (!(sr & (TIM_SR_CC2IF | TIM_SR_CC1IF))) goto flush_and_reset; } - cycle = TIM_CCR1(TIM3); - duty = TIM_CCR2(TIM3); + cycle = TIM_CCR1(TRACE_TIM); + duty = TIM_CCR2(TRACE_TIM); /* Reset decoder state if crazy shit happened */ if ((bt && (((duty / bt) > 2) || ((duty / bt) == 0))) || (duty == 0)) @@ -147,9 +148,9 @@ void tim3_isr(void) bt = duty; lastbit = 1; halfbit = 0; - timer_set_period(TIM3, duty * 6); - timer_clear_flag(TIM3, TIM_SR_UIF); - timer_enable_irq(TIM3, TIM_DIER_UIE); + timer_set_period(TRACE_TIM, duty * 6); + timer_clear_flag(TRACE_TIM, TIM_SR_UIF); + timer_enable_irq(TRACE_TIM, TIM_DIER_UIE); } else { /* If high time is extended we need to flip the bit */ if ((duty / bt) > 1) { @@ -179,8 +180,8 @@ void tim3_isr(void) return; flush_and_reset: - timer_set_period(TIM3, -1); - timer_disable_irq(TIM3, TIM_DIER_UIE); + timer_set_period(TRACE_TIM, -1); + timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); trace_buf_push(decbuf, decbuf_pos >> 3); bt = 0; decbuf_pos = 0; From 15d7077115f4c1fbaee03a0cb1b641e40215c86e Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 16 Jan 2013 16:54:30 +0100 Subject: [PATCH 16/42] traceswo: Move (now-constant) traceswo.c to platforms/stm32 --- src/{platforms/native => include}/traceswo.h | 1 - src/platforms/stm32/cdcacm.c | 2 +- src/platforms/{native => stm32}/traceswo.c | 10 ++++------ 3 files changed, 5 insertions(+), 8 deletions(-) rename src/{platforms/native => include}/traceswo.h (99%) rename src/platforms/{native => stm32}/traceswo.c (98%) diff --git a/src/platforms/native/traceswo.h b/src/include/traceswo.h similarity index 99% rename from src/platforms/native/traceswo.h rename to src/include/traceswo.h index 9b2cf2c8..5566f944 100644 --- a/src/platforms/native/traceswo.h +++ b/src/include/traceswo.h @@ -26,4 +26,3 @@ void traceswo_init(void); void trace_buf_drain(usbd_device *dev, uint8_t ep); #endif - diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 2bbdcb62..9799d137 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -37,7 +37,7 @@ #include "platform.h" #if defined(PLATFORM_HAS_TRACESWO) -#include "traceswo.h" +#include #endif #include diff --git a/src/platforms/native/traceswo.c b/src/platforms/stm32/traceswo.c similarity index 98% rename from src/platforms/native/traceswo.c rename to src/platforms/stm32/traceswo.c index 7cd42d1c..31fdc4e6 100644 --- a/src/platforms/native/traceswo.c +++ b/src/platforms/stm32/traceswo.c @@ -130,19 +130,19 @@ void trace_isr(void) duty = TIM_CCR2(TRACE_TIM); /* Reset decoder state if crazy shit happened */ - if ((bt && (((duty / bt) > 2) || ((duty / bt) == 0))) || (duty == 0)) + if ((bt && (((duty / bt) > 2) || ((duty / bt) == 0))) || (duty == 0)) goto flush_and_reset; if(!(sr & TIM_SR_CC1IF)) notstart = 1; if (!bt) { - if (notstart) { + if (notstart) { notstart = 0; return; } /* First bit, sync decoder */ duty -= ALLOWED_DUTY_ERROR; - if (((cycle / duty) != 2) && + if (((cycle / duty) != 2) && ((cycle / duty) != 3)) return; bt = duty; @@ -176,7 +176,7 @@ void trace_isr(void) decbuf_pos++; } - if (decbuf_pos < 128) + if (decbuf_pos < 128) return; flush_and_reset: @@ -187,5 +187,3 @@ flush_and_reset: decbuf_pos = 0; memset(decbuf, 0, sizeof(decbuf)); } - - From 7e91f68efa13e7a2b510d2631a916209d4317f9b Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 16 Jan 2013 16:56:22 +0100 Subject: [PATCH 17/42] f4discovery: Create a platforms directory for the F4 on the F4 Discovery board --- src/platforms/f4discovery/Makefile.inc | 36 +++ src/platforms/f4discovery/platform.c | 306 +++++++++++++++++++++++++ src/platforms/f4discovery/platform.h | 198 ++++++++++++++++ src/platforms/stm32/f4discovery.ld | 28 +++ 4 files changed, 568 insertions(+) create mode 100644 src/platforms/f4discovery/Makefile.inc create mode 100644 src/platforms/f4discovery/platform.c create mode 100644 src/platforms/f4discovery/platform.h create mode 100644 src/platforms/stm32/f4discovery.ld diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc new file mode 100644 index 00000000..4c56bd68 --- /dev/null +++ b/src/platforms/f4discovery/Makefile.inc @@ -0,0 +1,36 @@ +CROSS_COMPILE ?= arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ + -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include + +LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ + -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ + -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ + -L../libopencm3/lib +LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 + +VPATH += platforms/stm32 + +SRC += cdcacm.c \ + platform.c \ + traceswo.c \ + usbuart.c \ + +all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex + +blackmagic.bin: blackmagic + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu: usbdfu.o + $(CC) $^ -o $@ $(LDFLAGS_BOOT) + +blackmagic_dfu.bin: blackmagic_dfu + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu.hex: blackmagic_dfu + $(OBJCOPY) -O ihex $^ $@ + +host_clean: + -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c new file mode 100644 index 00000000..0e81ba43 --- /dev/null +++ b/src/platforms/f4discovery/platform.c @@ -0,0 +1,306 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform.h" +#include "jtag_scan.h" +#include + +#include + +uint8_t running_status; +volatile uint32_t timeout_counter; + +jmp_buf fatal_error_jmpbuf; + +static void morse_update(void); + +static void adc_init(void); + +/* Pins PB[7:5] are used to detect hardware revision. + * 000 - Original production build. + * 001 - Mini production build. + */ +int platform_hwversion(void) +{ + static int hwversion = -1; + if (hwversion == -1) { + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, + GPIO7 | GPIO6 | GPIO5); + gpio_clear(GPIOB, GPIO7 | GPIO6 | GPIO5); + hwversion = gpio_get(GPIOB, GPIO7 | GPIO6 | GPIO5) >> 5; + } + return hwversion; +} + +int platform_init(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable peripherals */ + 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_clear(USB_PU_PORT, USB_PU_PIN); + gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, + USB_PU_PIN); + + gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + TMS_PIN | TCK_PIN | TDI_PIN); + + /* This needs some fixing... */ + /* Toggle required to sort out line drivers... */ + gpio_port_write(GPIOA, 0x8100); + gpio_port_write(GPIOB, 0x2000); + + gpio_port_write(GPIOA, 0x8180); + gpio_port_write(GPIOB, 0x2002); + + gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + LED_UART | LED_IDLE_RUN | LED_ERROR); + + /* FIXME: This pin in intended to be input, but the TXS0108 fails + * to release the device from reset if this floats. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO7); + + /* 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(); + + if (platform_hwversion() > 0) { + adc_init(); + } else { + gpio_clear(GPIOB, GPIO0); + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); + } + + SCB_VTOR = 0x2000; // Relocate interrupt vector table here + + cdcacm_init(); + + jtag_scan(NULL); + + return 0; +} + +void platform_delay(uint32_t delay) +{ + timeout_counter = delay; + while(timeout_counter); +} + +void sys_tick_handler(void) +{ + if(running_status) + gpio_toggle(LED_PORT, LED_IDLE_RUN); + + if(timeout_counter) + timeout_counter--; + + morse_update(); +} + + +/* Morse code patterns and lengths */ +static const struct { + uint16_t code; + uint8_t bits; +} morse_letter[] = { + { 0b00011101, 8}, // 'A' .- + { 0b000101010111, 12}, // 'B' -... + { 0b00010111010111, 14}, // 'C' -.-. + { 0b0001010111, 10}, // 'D' -.. + { 0b0001, 4}, // 'E' . + { 0b000101110101, 12}, // 'F' ..-. + { 0b000101110111, 12}, // 'G' --. + { 0b0001010101, 10}, // 'H' .... + { 0b000101, 6}, // 'I' .. + {0b0001110111011101, 16}, // 'J' .--- + { 0b000111010111, 12}, // 'K' -.- + { 0b000101011101, 12}, // 'L' .-.. + { 0b0001110111, 10}, // 'M' -- + { 0b00010111, 8}, // 'N' -. + { 0b00011101110111, 14}, // 'O' --- + { 0b00010111011101, 14}, // 'P' .--. + {0b0001110101110111, 16}, // 'Q' --.- + { 0b0001011101, 10}, // 'R' .-. + { 0b00010101, 8}, // 'S' ... + { 0b000111, 6}, // 'T' - + { 0b0001110101, 10}, // 'U' ..- + { 0b000111010101, 12}, // 'V' ...- + { 0b000111011101, 12}, // 'W' .-- + { 0b00011101010111, 14}, // 'X' -..- + {0b0001110111010111, 16}, // 'Y' -.-- + { 0b00010101110111, 14}, // 'Z' --.. +}; + + +const char *morse_msg; +static const char * volatile morse_ptr; +static char morse_repeat; + +void morse(const char *msg, char repeat) +{ + morse_msg = morse_ptr = msg; + morse_repeat = repeat; + SET_ERROR_STATE(0); +} + +static void morse_update(void) +{ + static uint16_t code; + static uint8_t bits; + + if(!morse_ptr) return; + + if(!bits) { + char c = *morse_ptr++; + if(!c) { + if(morse_repeat) { + morse_ptr = morse_msg; + c = *morse_ptr++; + } else { + morse_ptr = 0; + return; + } + } + if((c >= 'A') && (c <= 'Z')) { + c -= 'A'; + code = morse_letter[c].code; + bits = morse_letter[c].bits; + } else { + code = 0; bits = 4; + } + } + SET_ERROR_STATE(code & 1); + code >>= 1; bits--; +} + +static void adc_init(void) +{ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); + + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, GPIO0); + + adc_off(ADC1); + adc_disable_scan_mode(ADC1); + adc_set_single_conversion_mode(ADC1); + adc_disable_external_trigger_regular(ADC1); + adc_set_right_aligned(ADC1); + adc_set_conversion_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); + + adc_power_on(ADC1); + + /* Wait for ADC starting up. */ + for (int i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("nop"); + + adc_reset_calibration(ADC1); + adc_calibration(ADC1); +} + +const char *platform_target_voltage(void) +{ + if (platform_hwversion() == 0) + return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!"; + + static char ret[] = "0.0V"; + const u8 channel = 8; + adc_set_regular_sequence(ADC1, 1, (u8*)&channel); + + adc_on(ADC1); + + /* Wait for end of conversion. */ + while (!(ADC_SR(ADC1) & ADC_SR_EOC)); + + u32 val = ADC_DR(ADC1) * 99; /* 0-4095 */ + ret[0] = '0' + val / 81910; + ret[2] = '0' + (val / 8191) % 10; + + return ret; +} + +void assert_boot_pin(void) +{ + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + gpio_clear(GPIOB, GPIO12); +} + +void exti15_10_isr(void) +{ + if (gpio_get(USB_VBUS_PORT, USB_VBUS_PIN)) { + /* Drive pull-up high if VBUS connected */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_OUTPUT_10_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, USB_PU_PIN); + } else { + /* Allow pull-up to float if VBUS disconnected */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, USB_PU_PIN); + } + + exti_reset_request(USB_VBUS_PIN); +} + +void setup_vbus_irq(void) +{ + nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); + nvic_enable_irq(USB_VBUS_IRQ); + + gpio_set(USB_VBUS_PORT, USB_VBUS_PIN); + gpio_set(USB_PU_PORT, USB_PU_PIN); + + gpio_set_mode(USB_VBUS_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, USB_VBUS_PIN); + + /* Configure EXTI for USB VBUS monitor */ + exti_select_source(USB_VBUS_PIN, USB_VBUS_PORT); + exti_set_trigger(USB_VBUS_PIN, EXTI_TRIGGER_BOTH); + exti_enable_request(USB_VBUS_PIN); + + exti15_10_isr(); +} diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h new file mode 100644 index 00000000..7d84533f --- /dev/null +++ b/src/platforms/f4discovery/platform.h @@ -0,0 +1,198 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ +#ifndef __PLATFORM_H +#define __PLATFORM_H + +#include +#include + +#include +#include + +#include "gdb_packet.h" + +#define INLINE_GPIO +#define CDCACM_PACKET_SIZE 64 +#define PLATFORM_HAS_TRACESWO + +extern usbd_device *usbdev; +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +/* Important pin mappings for STM32 implementation: + * + * LED0 = PB2 (Yellow LED : Running) + * LED1 = PB10 (Yellow LED : Idle) + * LED2 = PB11 (Red LED : Error) + * + * TPWR = RB0 (input) -- analogue on mini design ADC1, ch8 + * nTRST = PB1 + * SRST_OUT = PA2 + * TDI = PA3 + * TMS = PA4 (input for SWDP) + * TCK = PA5 + * TDO = PA6 (input) + * nSRST = PA7 (input) + * + * USB cable pull-up: PA8 + * USB VBUS detect: PB13 -- New on mini design. + * Enable pull up for compatibility. + * Force DFU mode button: PB12 + */ + +/* Hardware definitions... */ +#define JTAG_PORT GPIOA +#define TDI_PORT JTAG_PORT +#define TMS_PORT JTAG_PORT +#define TCK_PORT JTAG_PORT +#define TDO_PORT JTAG_PORT +#define TDI_PIN GPIO3 +#define TMS_PIN GPIO4 +#define TCK_PIN GPIO5 +#define TDO_PIN GPIO6 + +#define SWDIO_PORT JTAG_PORT +#define SWCLK_PORT JTAG_PORT +#define SWDIO_PIN TMS_PIN +#define SWCLK_PIN TCK_PIN + +#define TRST_PORT GPIOB +#define TRST_PIN GPIO1 +#define SRST_PORT GPIOA +#define SRST_PIN GPIO2 + +#define USB_PU_PORT GPIOA +#define USB_PU_PIN GPIO8 + +#define USB_VBUS_PORT GPIOB +#define USB_VBUS_PIN GPIO13 +#define USB_VBUS_IRQ NVIC_EXTI15_10_IRQ + +#define LED_PORT GPIOB +#define LED_PORT_UART GPIOB +#define LED_UART GPIO2 +#define LED_IDLE_RUN GPIO10 +#define LED_ERROR GPIO11 + +#define USB_DRIVER stm32f103_usb_driver +#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ +#define USB_ISR usb_lp_can_rx0_isr +/* 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_USBUSART (1 << 4) +#define IRQ_PRI_USB_VBUS (14 << 4) +#define IRQ_PRI_TRACE (0 << 4) + +#define USBUSART USART1 +#define USBUSART_CR1 USART1_CR1 +#define USBUSART_IRQ NVIC_USART1_IRQ +#define USBUSART_APB_ENR RCC_APB2ENR +#define USBUSART_CLK_ENABLE RCC_APB2ENR_USART1EN +#define USBUSART_PORT GPIOA +#define USBUSART_TX_PIN GPIO9 +#define USBUSART_ISR usart1_isr + +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR tim3_isr + +#define DEBUG(...) + +extern uint8_t running_status; +extern volatile uint32_t timeout_counter; + +extern jmp_buf fatal_error_jmpbuf; + +extern const char *morse_msg; + +#define gpio_set_val(port, pin, val) do { \ + if(val) \ + gpio_set((port), (pin)); \ + else \ + gpio_clear((port), (pin)); \ +} while(0) + +#define SET_RUN_STATE(state) {running_status = (state);} +#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} +#define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} + +#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} +#define PLATFORM_FATAL_ERROR(error) { \ + if(running_status) gdb_putpacketz("X1D"); \ + else gdb_putpacketz("EFF"); \ + running_status = 0; \ + target_list_free(); \ + morse("TARGET LOST.", 1); \ + longjmp(fatal_error_jmpbuf, (error)); \ +} + +int platform_init(void); +void morse(const char *msg, char repeat); +const char *platform_target_voltage(void); +int platform_hwversion(void); +void platform_delay(uint32_t delay); + +/* */ +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +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 +#define vasprintf vasiprintf + +#ifdef INLINE_GPIO +static inline void _gpio_set(u32 gpioport, u16 gpios) +{ + GPIO_BSRR(gpioport) = gpios; +} +#define gpio_set _gpio_set + +static inline void _gpio_clear(u32 gpioport, u16 gpios) +{ + GPIO_BRR(gpioport) = gpios; +} +#define gpio_clear _gpio_clear + +static inline u16 _gpio_get(u32 gpioport, u16 gpios) +{ + return (u16)GPIO_IDR(gpioport) & gpios; +} +#define gpio_get _gpio_get +#endif + +#endif + +#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); diff --git a/src/platforms/stm32/f4discovery.ld b/src/platforms/stm32/f4discovery.ld new file mode 100644 index 00000000..b70739cd --- /dev/null +++ b/src/platforms/stm32/f4discovery.ld @@ -0,0 +1,28 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2010 Thomas Otto + * + * 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 . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script from libopenstm32. */ +INCLUDE libopencm3_stm32f1.ld From 8b1ec3151fd49bf31cb0a3fd719de5c061f8dce8 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 16 Jan 2013 19:37:37 +0100 Subject: [PATCH 18/42] usbuart, jtagtap, swdptap: Factor out GPIO setup --- src/platforms/native/platform.h | 14 ++++++++++++++ src/platforms/stlink/platform.h | 14 ++++++++++++++ src/platforms/stm32/jtagtap.c | 4 ++-- src/platforms/stm32/swdptap.c | 10 ++++------ src/platforms/stm32/usbuart.c | 4 +--- src/platforms/stm32_can/platform.h | 14 ++++++++++++++ 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index d22e6417..94e7fa33 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -95,6 +95,20 @@ extern usbd_device *usbdev; #define LED_IDLE_RUN GPIO10 #define LED_ERROR GPIO11 +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + +#define UART_PIN_SETUP() \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); + #define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index ffea6762..97e86979 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -81,6 +81,20 @@ extern usbd_device *usbdev; #define LED_UART GPIO14 #define LED_IDLE_RUN GPIO8 +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + +#define UART_PIN_SETUP() \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); + #define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c index a98c1d21..d6e298b5 100644 --- a/src/platforms/stm32/jtagtap.c +++ b/src/platforms/stm32/jtagtap.c @@ -25,11 +25,11 @@ #include "general.h" #include "jtagtap.h" +#include "platform.h" int jtagtap_init(void) { - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); + TMS_SET_MODE(); /* Go to JTAG mode for SWJ-DP */ for(int i = 0; i <= 50; i++) jtagtap_next(1, 0); /* Reset SW-DP */ diff --git a/src/platforms/stm32/swdptap.c b/src/platforms/stm32/swdptap.c index dceb23e9..72fb0f98 100644 --- a/src/platforms/stm32/swdptap.c +++ b/src/platforms/stm32/swdptap.c @@ -38,14 +38,12 @@ static void swdptap_turnaround(uint8_t dir) if(dir == olddir) return; olddir = dir; - if(dir) - gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); + if(dir) + SWDIO_MODE_FLOAT(); gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); - if(!dir) - gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + if(!dir) + SWDIO_MODE_DRIVE(); } static uint8_t swdptap_bit_in(void) diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 68dac60b..fac7b96a 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -39,9 +39,7 @@ void usbuart_init(void) rcc_peripheral_enable_clock(&USBUSART_APB_ENR, USBUSART_CLK_ENABLE); - /* UART TX to 'alternate function output push-pull' */ - gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); + UART_PIN_SETUP(); /* Setup UART parameters. */ usart_set_baudrate(USBUSART, 38400); diff --git a/src/platforms/stm32_can/platform.h b/src/platforms/stm32_can/platform.h index cf08b543..030855b9 100644 --- a/src/platforms/stm32_can/platform.h +++ b/src/platforms/stm32_can/platform.h @@ -83,6 +83,20 @@ extern usbd_device *usbdev; #define LED_IDLE_RUN GPIO1 #define LED_ERROR GPIO12 +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + +#define UART_PIN_SETUP() \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); + #define USB_DRIVER stm32f107_usb_driver #define USB_IRQ NVIC_OTG_FS_IRQ #define USB_ISR otg_fs_isr From 5e71ea3f60a8c61c753b1a6660898b81b00fc7fa Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 17 Jan 2013 11:00:35 +0100 Subject: [PATCH 19/42] stm32_mem: Allow to select the programmer with the serial number --- scripts/stm32_mem.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/scripts/stm32_mem.py b/scripts/stm32_mem.py index 97bdbbf8..a543317b 100755 --- a/scripts/stm32_mem.py +++ b/scripts/stm32_mem.py @@ -21,6 +21,7 @@ from time import sleep import struct from sys import stdout, argv +import argparse import usb import dfu @@ -60,11 +61,15 @@ def stm32_manifest(dev): if __name__ == "__main__": print - print "USB Device Firmware Upgrade - Host Utility -- version 1.1" + print "USB Device Firmware Upgrade - Host Utility -- version 1.2" print "Copyright (C) 2011 Black Sphere Technologies" print "License GPLv3+: GNU GPL version 3 or later " print + parser = argparse.ArgumentParser() + parser.add_argument("progfile", help="Binary file to program") + parser.add_argument("-s", "--serial_target", help="Match Serial Number") + args = parser.parse_args() devs = dfu.finddevs() if not devs: print "No devices found!" @@ -73,13 +78,22 @@ if __name__ == "__main__": for dev in devs: dfudev = dfu.dfu_device(*dev) man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30) - product = dfudev.handle.getString(dfudev.dev.iProduct, 30) - if man == "Black Sphere Technologies": break - if man == "STMicroelectronics": break + product = dfudev.handle.getString(dfudev.dev.iProduct, 64) + serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30) + if args.serial_target: + if man == "Black Sphere Technologies" and serial_no == args.serial_target: break + if man == "STMicroelectronics" and serial_no == args.serial_target: break + else: + if man == "Black Sphere Technologies": break + if man == "STMicroelectronics": break - print "Device %s: ID %04x:%04x %s - %s" % (dfudev.dev.filename, - dfudev.dev.idVendor, dfudev.dev.idProduct, man, product) + print "Device %s: ID %04x:%04x %s - %s\n\tSerial %s" % ( + dfudev.dev.filename, dfudev.dev.idVendor, + dfudev.dev.idProduct, man, product, serial_no) + if args.serial_target and serial_no != args.serial_target: + print "Serial number doesn't match!\n" + exit(-2) try: state = dfudev.get_state() except: @@ -92,9 +106,12 @@ if __name__ == "__main__": dfudev.make_idle() - bin = open(argv[1], "rb").read() + bin = open(args.progfile, "rb").read() - addr = 0x8002000 + if product.find("F4") : + addr = 0x8004000 + else: + addr = 0x8002000 while bin: print ("Programming memory at 0x%08X\r" % addr), stdout.flush() From 06c2d52c59e456d86b74e4f2b9a4fd4759a83b85 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 17 Jan 2013 14:04:43 +0100 Subject: [PATCH 20/42] stm32_mem.py: Add exception handler for better diagnosis, as erase on STM32F407 times out --- scripts/stm32_mem.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/stm32_mem.py b/scripts/stm32_mem.py index a543317b..d7785e53 100755 --- a/scripts/stm32_mem.py +++ b/scripts/stm32_mem.py @@ -115,7 +115,11 @@ if __name__ == "__main__": while bin: print ("Programming memory at 0x%08X\r" % addr), stdout.flush() - stm32_erase(dfudev, addr) + try: + stm32_erase(dfudev, addr) + except: + print "\nErase Timed out\n" + break stm32_write(dfudev, bin[:1024]) bin = bin[1024:] From e3736193745ad89e3dcb69a73f8906a4de41c4ca Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 17 Jan 2013 19:18:23 +0100 Subject: [PATCH 21/42] stlink: LED is connected to GPIO9. Before LED was associated with the MCO Output. --- src/platforms/stlink/platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 97e86979..e5fd0b4b 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -79,7 +79,7 @@ extern usbd_device *usbdev; /* 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 +#define LED_IDLE_RUN GPIO9 #define TMS_SET_MODE() \ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ From 04624af4e50eb59c0be7a9e5e1ef42b968a2c200 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 17 Jan 2013 20:05:25 +0100 Subject: [PATCH 22/42] f4discovery: Adapt from the "native" file and add or change code where needed - stm32_mem.py has problems with erasing the big pages, but dfu-util works - serial GDB remote server doesn't work. It neither works for the STM32F107, so maybe there is a problem with the usbd_f107_driver. --- src/platforms/f4discovery/Makefile.inc | 8 +- src/platforms/f4discovery/Readme | 17 +++ src/platforms/f4discovery/platform.c | 170 ++++++------------------ src/platforms/f4discovery/platform.h | 105 ++++++++------- src/platforms/stm32/cdcacm.c | 4 + src/platforms/stm32/f4discovery.ld | 7 +- src/platforms/stm32/usbdfu.c | 172 ++++++++++++++++++++----- 7 files changed, 264 insertions(+), 219 deletions(-) create mode 100644 src/platforms/f4discovery/Readme diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 4c56bd68..8d9b3c1c 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -3,13 +3,13 @@ CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ - -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include + -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include -LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ - -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ +LDFLAGS_BOOT = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ + -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib -LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 +LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8010000 VPATH += platforms/stm32 diff --git a/src/platforms/f4discovery/Readme b/src/platforms/f4discovery/Readme new file mode 100644 index 00000000..6035917b --- /dev/null +++ b/src/platforms/f4discovery/Readme @@ -0,0 +1,17 @@ +Application start address: +========================= + +Use 0x8010000 +- lower 3 16 k pages may be used for parameter storage +- Erasing a single 64 k Page is faster then erasing 2 16 k Pages + eventual the 64 k page + + +Internal boot loader: +==================== + +When we request invokation of a bootloader from inside the application, +we boot the device internal bootloader with the blue botton pressed. + +That way, we can easy exchange the custom bootloader via the device +internale bootloader \ No newline at end of file diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 0e81ba43..4aa14a67 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -22,14 +22,14 @@ * implementation. */ -#include +#include #include #include #include #include #include +#include #include -#include #include "platform.h" #include "jtag_scan.h" @@ -44,64 +44,39 @@ jmp_buf fatal_error_jmpbuf; static void morse_update(void); -static void adc_init(void); - -/* Pins PB[7:5] are used to detect hardware revision. - * 000 - Original production build. - * 001 - Mini production build. - */ -int platform_hwversion(void) -{ - static int hwversion = -1; - if (hwversion == -1) { - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, - GPIO7 | GPIO6 | GPIO5); - gpio_clear(GPIOB, GPIO7 | GPIO6 | GPIO5); - hwversion = gpio_get(GPIOB, GPIO7 | GPIO6 | GPIO5) >> 5; - } - return hwversion; -} - int platform_init(void) { - rcc_clock_setup_in_hse_8mhz_out_72mhz(); + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); /* Enable peripherals */ - 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); + rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); - /* Setup GPIO ports */ - gpio_clear(USB_PU_PORT, USB_PU_PIN); - gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, - USB_PU_PIN); - gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, + /* Set up USB Pins and alternate function*/ + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO9 | GPIO11 | GPIO12); + gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); + + GPIOA_OSPEEDR &=~0xfc; + GPIOA_OSPEEDR |= 0xa8; + gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, TMS_PIN | TCK_PIN | TDI_PIN); - /* This needs some fixing... */ - /* Toggle required to sort out line drivers... */ - gpio_port_write(GPIOA, 0x8100); - gpio_port_write(GPIOB, 0x2000); + gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, + GPIO_PUPD_NONE, + TDO_PIN); - gpio_port_write(GPIOA, 0x8180); - gpio_port_write(GPIOB, 0x2002); - - gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, - LED_UART | LED_IDLE_RUN | LED_ERROR); - - /* FIXME: This pin in intended to be input, but the TXS0108 fails - * to release the device from reset if this floats. */ - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO7); + gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, + LED_UART | LED_IDLE_RUN | LED_ERROR | LED_SPARE1); /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); /* Interrupt us at 10 Hz */ + systick_set_reload(168000000/(10*8)); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); systick_interrupt_enable(); @@ -109,15 +84,7 @@ int platform_init(void) usbuart_init(); - if (platform_hwversion() > 0) { - adc_init(); - } else { - gpio_clear(GPIOB, GPIO0); - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); - } - - SCB_VTOR = 0x2000; // Relocate interrupt vector table here + SCB_VTOR = 0x10000; // Relocate interrupt vector table here cdcacm_init(); @@ -219,88 +186,23 @@ static void morse_update(void) code >>= 1; bits--; } -static void adc_init(void) -{ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); - - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_ANALOG, GPIO0); - - adc_off(ADC1); - adc_disable_scan_mode(ADC1); - adc_set_single_conversion_mode(ADC1); - adc_disable_external_trigger_regular(ADC1); - adc_set_right_aligned(ADC1); - adc_set_conversion_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); - - adc_power_on(ADC1); - - /* Wait for ADC starting up. */ - for (int i = 0; i < 800000; i++) /* Wait a bit. */ - __asm__("nop"); - - adc_reset_calibration(ADC1); - adc_calibration(ADC1); -} - const char *platform_target_voltage(void) { - if (platform_hwversion() == 0) - return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!"; - - static char ret[] = "0.0V"; - const u8 channel = 8; - adc_set_regular_sequence(ADC1, 1, (u8*)&channel); - - adc_on(ADC1); - - /* Wait for end of conversion. */ - while (!(ADC_SR(ADC1) & ADC_SR_EOC)); - - u32 val = ADC_DR(ADC1) * 99; /* 0-4095 */ - ret[0] = '0' + val / 81910; - ret[2] = '0' + (val / 8191) % 10; - - return ret; + return "ABSENT!"; } void assert_boot_pin(void) { - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); - gpio_clear(GPIOB, GPIO12); -} - -void exti15_10_isr(void) -{ - if (gpio_get(USB_VBUS_PORT, USB_VBUS_PIN)) { - /* Drive pull-up high if VBUS connected */ - gpio_set_mode(USB_PU_PORT, GPIO_MODE_OUTPUT_10_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, USB_PU_PIN); - } else { - /* Allow pull-up to float if VBUS disconnected */ - gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, USB_PU_PIN); + if (gpio_get(GPIOA, GPIO0)) { + /* Jump to the built in bootloader by mapping System flash */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN); + SYSCFG_MEMRM &= ~3; + SYSCFG_MEMRM |= 1; + } + else { + /* Flag Bootloader Request by mimicing a pushed USER button*/ + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, GPIO0); + gpio_set(GPIOA, GPIO0); } - - exti_reset_request(USB_VBUS_PIN); -} - -void setup_vbus_irq(void) -{ - nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); - nvic_enable_irq(USB_VBUS_IRQ); - - gpio_set(USB_VBUS_PORT, USB_VBUS_PIN); - gpio_set(USB_PU_PORT, USB_PU_PIN); - - gpio_set_mode(USB_VBUS_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, USB_VBUS_PIN); - - /* Configure EXTI for USB VBUS monitor */ - exti_select_source(USB_VBUS_PIN, USB_VBUS_PORT); - exti_set_trigger(USB_VBUS_PIN, EXTI_TRIGGER_BOTH); - exti_enable_request(USB_VBUS_PIN); - - exti15_10_isr(); } diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 7d84533f..6cbbc1b0 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -24,7 +24,7 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include +#include #include #include @@ -42,18 +42,18 @@ extern usbd_device *usbdev; /* Important pin mappings for STM32 implementation: * - * LED0 = PB2 (Yellow LED : Running) - * LED1 = PB10 (Yellow LED : Idle) - * LED2 = PB11 (Red LED : Error) + * LED0 = PD12 (Green LED : Running) + * LED1 = PD13 (Orange LED : Idle) + * LED2 = PD12 (Red LED : Error) * - * TPWR = RB0 (input) -- analogue on mini design ADC1, ch8 - * nTRST = PB1 - * SRST_OUT = PA2 - * TDI = PA3 - * TMS = PA4 (input for SWDP) - * TCK = PA5 - * TDO = PA6 (input) - * nSRST = PA7 (input) + * TPWR = XXX (input) -- analogue on mini design ADC1, ch8 + * nTRST = PD0 + * SRST_OUT = PD1 + * TDI = PA1 + * TMS = PA3 (input for SWDP) + * TCK = PA8 + * TDO = PB4 (input) + * nSRST = PD2 (input) * * USB cable pull-up: PA8 * USB VBUS detect: PB13 -- New on mini design. @@ -66,55 +66,68 @@ extern usbd_device *usbdev; #define TDI_PORT JTAG_PORT #define TMS_PORT JTAG_PORT #define TCK_PORT JTAG_PORT -#define TDO_PORT JTAG_PORT -#define TDI_PIN GPIO3 -#define TMS_PIN GPIO4 -#define TCK_PIN GPIO5 -#define TDO_PIN GPIO6 +#define TDO_PORT GPIOB +#define TDI_PIN GPIO1 +#define TMS_PIN GPIO3 +#define TCK_PIN GPIO2 +#define TDO_PIN GPIO4 #define SWDIO_PORT JTAG_PORT #define SWCLK_PORT JTAG_PORT #define SWDIO_PIN TMS_PIN #define SWCLK_PIN TCK_PIN -#define TRST_PORT GPIOB -#define TRST_PIN GPIO1 -#define SRST_PORT GPIOA -#define SRST_PIN GPIO2 +#define TRST_PORT GPIOD +#define TRST_PIN GPIO0 +#define SRST_PORT GPIOD +#define SRST_PIN GPIO1 -#define USB_PU_PORT GPIOA -#define USB_PU_PIN GPIO8 +#define LED_PORT GPIOD +#define LED_PORT_UART GPIOD +#define LED_UART GPIO12 +#define LED_IDLE_RUN GPIO13 +#define LED_ERROR GPIO14 +#define LED_SPARE1 GPIO15 -#define USB_VBUS_PORT GPIOB -#define USB_VBUS_PIN GPIO13 -#define USB_VBUS_IRQ NVIC_EXTI15_10_IRQ +#define TMS_SET_MODE() gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, TMS_PIN); +#define SWDIO_MODE_FLOAT() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); -#define LED_PORT GPIOB -#define LED_PORT_UART GPIOB -#define LED_UART GPIO2 -#define LED_IDLE_RUN GPIO10 -#define LED_ERROR GPIO11 +#define SWDIO_MODE_DRIVE() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); -#define USB_DRIVER stm32f103_usb_driver -#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ -#define USB_ISR usb_lp_can_rx0_isr + +#define USB_DRIVER stm32f107_usb_driver +#define USB_IRQ NVIC_OTG_FS_IRQ +#define USB_ISR otg_fs_isr /* 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_USBUSART (1 << 4) -#define IRQ_PRI_USB_VBUS (14 << 4) #define IRQ_PRI_TRACE (0 << 4) -#define USBUSART USART1 -#define USBUSART_CR1 USART1_CR1 -#define USBUSART_IRQ NVIC_USART1_IRQ -#define USBUSART_APB_ENR RCC_APB2ENR -#define USBUSART_CLK_ENABLE RCC_APB2ENR_USART1EN -#define USBUSART_PORT GPIOA -#define USBUSART_TX_PIN GPIO9 -#define USBUSART_ISR usart1_isr +#define USBUSART USART3 +#define USBUSART_CR1 USART3_CR1 +#define USBUSART_IRQ NVIC_USART3_IRQ +#define USBUSART_APB_ENR RCC_APB1ENR +#define USBUSART_CLK_ENABLE RCC_APB1ENR_USART3EN +#define USBUSART_TX_PORT GPIOD +#define USBUSART_TX_PIN GPIO8 +#define USBUSART_RX_PORT GPIOD +#define USBUSART_RX_PIN GPIO9 +#define USBUSART_ISR usart3_isr + +#define UART_PIN_SETUP() do { \ + gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_TX_PIN); \ + gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_RX_PIN); \ + gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \ + gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \ + } while(0) #define TRACE_TIM TIM3 #define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) @@ -180,7 +193,7 @@ static inline void _gpio_set(u32 gpioport, u16 gpios) static inline void _gpio_clear(u32 gpioport, u16 gpios) { - GPIO_BRR(gpioport) = gpios; + GPIO_BSRR(gpioport) = gpios<<16; } #define gpio_clear _gpio_clear @@ -193,6 +206,6 @@ static inline u16 _gpio_get(u32 gpioport, u16 gpios) #endif -#define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); +#define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) void assert_boot_pin(void); -void setup_vbus_irq(void); +#define setup_vbus_irq() diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 9799d137..0cbfc5f9 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -553,7 +553,11 @@ void USB_ISR(void) 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); diff --git a/src/platforms/stm32/f4discovery.ld b/src/platforms/stm32/f4discovery.ld index b70739cd..b0664264 100644 --- a/src/platforms/stm32/f4discovery.ld +++ b/src/platforms/stm32/f4discovery.ld @@ -20,9 +20,10 @@ /* Define memory regions. */ MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K } /* Include the common ld script from libopenstm32. */ -INCLUDE libopencm3_stm32f1.ld +INCLUDE libopencm3_stm32f4.ld + diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index e33eddb1..4535b348 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -34,8 +34,6 @@ #include #include -#define APP_ADDRESS 0x08002000 - /* Commands sent with wBlockNum == 0 as per ST implementation. */ #define CMD_SETADDR 0x21 #define CMD_ERASE 0x41 @@ -49,10 +47,60 @@ usbd_device *usbdev; /* We need a special large control buffer for this device: */ u8 usbd_control_buffer[1024]; +#if defined (STM32_CAN) +#define FLASHBLOCKSIZE 2048 +#else +#define FLASHBLOCKSIZE 1024 +#endif + #if defined(DISCOVERY_STLINK) u32 led2_state = 0; #endif +static u32 max_address; +#if defined (STM32F4) +#define APP_ADDRESS 0x08010000 +static u32 sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000, + 0x8010000, 0x8020000, 0x8040000, 0x8060000, + 0x8080000, 0x80a0000, 0x80c0000, 0x80e0000, + 0x8100000, 0}; +u16 sector_erase_time[12]= {500, 500, 500, 500, + 1100, + 2600, 2600, 2600, 2600, 2600, 2600, 2600}; +u8 sector_num = 0xff; +/* Find the sector number for a given address*/ +void get_sector_num(u32 addr) +{ + int i = 0; + while(sector_addr[i+1]) { + if (addr < sector_addr[i+1]) + break; + i++; + } + if (!sector_addr[i]) + return; + sector_num = i; +} + +void check_and_do_sector_erase(u32 addr) +{ + if(addr == sector_addr[sector_num]) { + flash_erase_sector((sector_num & 0x1f)<<3, FLASH_PROGRAM_X32); + } +} +#else +#define APP_ADDRESS 0x08002000 +static uint32_t last_erased_page=0xffffffff; +void check_and_do_sector_erase(u32 sector) +{ + sector &= (~(FLASHBLOCKSIZE-1)); + if (sector != last_erased_page) { + flash_erase_page(sector); + last_erased_page = sector; + } +} +#endif + static enum dfu_state usbdfu_state = STATE_DFU_IDLE; static char *get_dev_unique_id(char *serial_no); @@ -136,6 +184,8 @@ static const char *usb_strings[] = { "Black Magic (Upgrade) for STLink/Discovery", #elif defined(STM32_CAN) "Black Magic (Upgrade) for STM32_CAN", +#elif defined(F4DISCOVERY) + "Black Magic (Upgrade) for F4DISCOVERY", #else #warning "Unhandled board" #endif @@ -147,6 +197,8 @@ static const char *usb_strings[] = { "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #elif defined(STM32_CAN) "@Internal Flash /0x08000000/4*002Ka,124*002Kg" +#elif defined(F4DISCOVERY) + "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" #else #warning "Unhandled board" #endif @@ -157,7 +209,20 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout) switch(usbdfu_state) { case STATE_DFU_DNLOAD_SYNC: usbdfu_state = STATE_DFU_DNBUSY; +#if defined(STM32F4) + /* Programming 256 word with 100 us(max) per word*/ + *bwPollTimeout = 26; + /* Erase for big pages on STM2/4 needs "long" time + Try not to hit USB timeouts*/ + if ((prog.blocknum == 0) && (prog.buf[0] == CMD_ERASE)) { + u32 addr = *(u32 *)(prog.buf + 1); + get_sector_num(addr); + if(addr == sector_addr[sector_num]) + *bwPollTimeout = sector_erase_time[sector_num]; + } +#else *bwPollTimeout = 100; +#endif return DFU_STATUS_OK; case STATE_DFU_MANIFEST_SYNC: @@ -170,13 +235,6 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout) } } -#if defined (STM32_CAN) -#define FLASHBLOCKSIZE 2048 -#else -#define FLASHBLOCKSIZE 1024 -#endif -static uint32_t last_erased_pages=0xffffffff; - static void usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) { @@ -188,32 +246,33 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_unlock(); if(prog.blocknum == 0) { - if ((*(u32*)(prog.buf+1) < 0x8002000) || - (*(u32*)(prog.buf+1) >= 0x8020000)) { + u32 addr = *(u32 *)(prog.buf + 1); + if (addr < APP_ADDRESS || + (addr >= max_address)) { + flash_lock(); usbd_ep_stall_set(dev, 0, 1); return; } switch(prog.buf[0]) { - case CMD_ERASE: { - u32 page_start = *(u32*)(prog.buf+1); - - page_start &= (~(FLASHBLOCKSIZE-1)); - if (page_start != last_erased_pages) { - flash_erase_page(page_start); - last_erased_pages = page_start; - } - - } + case CMD_ERASE: + check_and_do_sector_erase(addr); case CMD_SETADDR: - prog.addr = *(u32*)(prog.buf+1); + prog.addr = addr; } } else { u32 baseaddr = prog.addr + ((prog.blocknum - 2) * dfu_function.wTransferSize); +#if defined (STM32F4) + for(i = 0; i < prog.len; i += 4) + flash_program_word(baseaddr + i, + *(u32*)(prog.buf+i), + FLASH_PROGRAM_X32); +#else for(i = 0; i < prog.len; i += 2) flash_program_half_word(baseaddr + i, *(u16*)(prog.buf+i)); +#endif } flash_lock(); @@ -311,14 +370,23 @@ int main(void) #elif defined (STM32_CAN) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); if(!gpio_get(GPIOA, GPIO0)) { +#elif defined (F4DISCOVERY) + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); + if(!gpio_get(GPIOA, GPIO0)) { #else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); if(gpio_get(GPIOB, GPIO12)) { #endif /* Boot the application if it's valid */ +#if defined (STM32F4) + /* Vector table may be anywhere in 128 kByte RAM + CCM not handled*/ + if((*(volatile u32*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) { +#else if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { +#endif /* Set vector table base address */ - SCB_VTOR = APP_ADDRESS & 0xFFFF; + SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ /* Initialise master stack pointer */ asm volatile ("msr msp, %0"::"g" (*(volatile u32*)APP_ADDRESS)); @@ -327,6 +395,9 @@ int main(void) } } +#if defined (STM32F4) + /* don' touch option bits for now */ +#else if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); FLASH_CR = 0; @@ -336,6 +407,7 @@ int main(void) /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } +#endif #if defined (DISCOVERY_STLINK) /* Just in case: Disconnect USB cable by resetting USB Device @@ -348,19 +420,22 @@ int main(void) gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); #endif +#if defined (F4DISCOVERY) + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); +#else rcc_clock_setup_in_hse_8mhz_out_72mhz(); - - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); +#endif #if defined(DISCOVERY_STLINK) - gpio_set_mode(GPIOA, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_ANALOG, GPIO0); +#elif defined(F4DISCOVERY) #elif defined (STM32_CAN) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); #else + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); @@ -368,18 +443,33 @@ int main(void) GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); #endif systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); + systick_set_reload(2100000); systick_interrupt_enable(); systick_counter_enable(); - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); - get_dev_unique_id(serial_no); #if defined(STM32_CAN) + usbdev = usbd_init(&stm32f107_usb_driver, + &dev, &config, usb_strings, 4); +#elif defined(F4DISCOVERY) + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); + gpio_clear(GPIOD, GPIO12 | GPIO13 | GPIO14 |GPIO15); + gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, + GPIO12 | GPIO13 | GPIO14 |GPIO15); + + rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); + + /* Set up USB Pins and alternate function*/ + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO9 | GPIO11 | GPIO12); + gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); + usbdev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings, 4); #else + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); + usbdev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings, 4); #endif @@ -401,12 +491,28 @@ int main(void) static char *get_dev_unique_id(char *s) { - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; +#if defined(STM32F4) || defined(STM32F2) +#define UNIQUE_SERIAL_R 0x1FFF7A10 +#define FLASH_SIZE_R 0x1fff7A22 +#elif defined(STM32F3) +#define UNIQUE_SERIAL_R 0x1FFFF7AC +#define FLASH_SIZE_R 0x1fff77cc +#elif defined(STM32L1) +#define UNIQUE_SERIAL_R 0x1ff80050 +#define FLASH_SIZE_R 0x1FF8004C +#else +#define UNIQUE_SERIAL_R 0x1FFFF7E8; +#define FLASH_SIZE_R 0x1ffff7e0 +#endif + volatile uint32_t *unique_id_p = (volatile uint32_t *)UNIQUE_SERIAL_R; uint32_t unique_id = *unique_id_p + *(unique_id_p + 1) + *(unique_id_p + 2); int i; + /* Calculated the upper flash limit from the exported data + in theparameter block*/ + max_address = (*(u32 *) FLASH_SIZE_R) <<10; /* Fetch serial number from chip's unique ID */ for(i = 0; i < 8; i++) { s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; @@ -429,6 +535,8 @@ void sys_tick_handler() gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO9); led2_state++; +#elif defined (F4DISCOVERY) + gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */ #elif defined(STM32_CAN) gpio_toggle(GPIOB, GPIO0); /* LED2 on/off */ #else From 1fa961841dd9a6abd3ad50106f59b2e18eeccb77 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 20 Jan 2013 20:38:04 +0100 Subject: [PATCH 23/42] Product and DFU String now tell the hardware they run on --- src/platforms/f4discovery/platform.h | 2 ++ src/platforms/native/platform.h | 2 ++ src/platforms/stlink/platform.h | 2 ++ src/platforms/stm32/cdcacm.c | 4 ++-- src/platforms/stm32/usbdfu.c | 2 +- src/platforms/stm32_can/platform.h | 2 ++ 6 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 6cbbc1b0..b19aa115 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -35,6 +35,8 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO +#define BOARD_IDENT "Black Magic Probe (F4Discovery)" +#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 94e7fa33..4a0f2736 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -35,6 +35,8 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO +#define BOARD_IDENT "Black Magic Probe" +#define DFU_IDENT "Black Magic Firmware Upgrade" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index e5fd0b4b..a5eee6c7 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -34,6 +34,8 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 +#define BOARD_IDENT "Black Magic Probe (STLINK)" +#define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 0cbfc5f9..00c5ed2f 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -394,11 +394,11 @@ char serial_no[9]; static const char *usb_strings[] = { "Black Sphere Technologies", - "Black Magic Probe", + BOARD_IDENT, serial_no, "Black Magic GDB Server", "Black Magic UART Port", - "Black Magic Firmware Upgrade", + DFU_IDENT, #if defined(PLATFORM_HAS_TRACESWO) "Black Magic Trace Capture", #endif diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 4535b348..fb8f34f4 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -185,7 +185,7 @@ static const char *usb_strings[] = { #elif defined(STM32_CAN) "Black Magic (Upgrade) for STM32_CAN", #elif defined(F4DISCOVERY) - "Black Magic (Upgrade) for F4DISCOVERY", + "Black Magic (Upgrade) for F4Discovery", #else #warning "Unhandled board" #endif diff --git a/src/platforms/stm32_can/platform.h b/src/platforms/stm32_can/platform.h index 030855b9..8b0d567a 100644 --- a/src/platforms/stm32_can/platform.h +++ b/src/platforms/stm32_can/platform.h @@ -39,6 +39,8 @@ extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 #define CDCACM_UART_ENDPOINT 3 +#define BOARD_IDENT "Black Magic Probe (STM32_CAN)" +#define DFU_IDENT "Black Magic Firmware Upgrade (STM32_CAN)" /* Important pin mappings for STM32 implementation: * From 749fb318e78b89584af000f4e2b41dce013a6fc3 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 20 Jan 2013 21:47:03 +0100 Subject: [PATCH 24/42] gdb_if: Use a doubled buffer scheme for reading data from USB Needed, as the OTG driver erases the data read after eventually calling the callback --- src/include/gdb_if.h | 3 +++ src/platforms/stm32/cdcacm.c | 3 ++- src/platforms/stm32/gdb_if.c | 29 +++++++++++++++++++++++------ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/include/gdb_if.h b/src/include/gdb_if.h index 930a3d6d..0d6a6029 100644 --- a/src/include/gdb_if.h +++ b/src/include/gdb_if.h @@ -21,7 +21,10 @@ #ifndef __GDB_IF_H #define __GDB_IF_H +#include + int gdb_if_init(void); +void gdb_usb_out_cb(usbd_device *dev, uint8_t ep); unsigned char gdb_if_getchar(void); unsigned char gdb_if_getchar_to(int timeout); void gdb_if_putchar(unsigned char c, int flush); diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 00c5ed2f..b6d26020 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -36,6 +36,7 @@ #include #include "platform.h" +#include "gdb_if.h" #if defined(PLATFORM_HAS_TRACESWO) #include #endif @@ -487,7 +488,7 @@ static void cdcacm_set_config(usbd_device *dev, u16 wValue) /* GDB interface */ usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); + 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); diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 0e702a22..030205a7 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -28,9 +28,11 @@ #include "gdb_if.h" static uint32_t count_out; +static uint32_t count_new; static uint32_t count_in; static uint32_t out_ptr; static uint8_t buffer_out[CDCACM_PACKET_SIZE]; +static uint8_t double_buffer_out[CDCACM_PACKET_SIZE]; static uint8_t buffer_in[CDCACM_PACKET_SIZE]; void gdb_if_putchar(unsigned char c, int flush) @@ -49,17 +51,28 @@ void gdb_if_putchar(unsigned char c, int flush) } } +void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) +{ + (void)ep; + count_new = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, + double_buffer_out, CDCACM_PACKET_SIZE); +} + unsigned char gdb_if_getchar(void) { + while(!(out_ptr < count_out)) { /* Detach if port closed */ if(!cdcacm_get_dtr()) return 0x04; while(cdcacm_get_config() != 1); - count_out = usbd_ep_read_packet(usbdev, CDCACM_GDB_ENDPOINT, - buffer_out, CDCACM_PACKET_SIZE); - out_ptr = 0; + if (count_new) { + memcpy(buffer_out, double_buffer_out,count_new); + count_out = count_new; + count_new = 0; + out_ptr = 0; + } } return buffer_out[out_ptr++]; @@ -74,9 +87,13 @@ unsigned char gdb_if_getchar_to(int timeout) if(!cdcacm_get_dtr()) return 0x04; - count_out = usbd_ep_read_packet(usbdev, CDCACM_GDB_ENDPOINT, - buffer_out, CDCACM_PACKET_SIZE); - out_ptr = 0; + while(cdcacm_get_config() != 1); + if (count_new) { + memcpy(buffer_out, double_buffer_out,count_new); + count_out = count_new; + count_new = 0; + out_ptr = 0; + } } while(timeout_counter && !(out_ptr < count_out)); if(out_ptr < count_out) From 8033fb2529c08ccae24aaa8853be76e97eb945da Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 20 Jan 2013 23:17:23 +0100 Subject: [PATCH 25/42] STLINK: Allow to force bootloader by starting with the RESET button pressed --- src/platforms/stm32/usbdfu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index fb8f34f4..55318ec6 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -55,6 +55,18 @@ u8 usbd_control_buffer[1024]; #if defined(DISCOVERY_STLINK) u32 led2_state = 0; +int stlink_test_nrst(void) { +/* Test if NRST is pulled down*/ + int i; + uint16_t nrst; + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); + gpio_set(GPIOB, GPIO0); + for (i=0; i< 100000; i++) + nrst = gpio_get(GPIOB, GPIO0); + return (nrst)?1:0; +} #endif static u32 max_address; @@ -366,7 +378,7 @@ int main(void) { #if defined (DISCOVERY_STLINK) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - if(!gpio_get(GPIOC, GPIO13)) { + if(!gpio_get(GPIOC, GPIO13) && stlink_test_nrst()) { #elif defined (STM32_CAN) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); if(!gpio_get(GPIOA, GPIO0)) { From ef09fb2b69137508a371d8b542d9c706887e9143 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 21 Jan 2013 11:01:44 +0100 Subject: [PATCH 26/42] README: Add the hint about "set mem inaccessible-by-default off" from the mailing list --- README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README b/README index 413428d5..1bef2e65 100644 --- a/README +++ b/README @@ -38,6 +38,11 @@ instead of JTAG to connect to the target. Once attached, all the standard GDB commands may be used to start and control the execution of the embedded application. +The peripheral registers are not included in the memory map provided to GDB. +I suggest you add the command "set mem inaccessible-by-default off' to +your '.gdbinit'. That will allow you to access addresses outside of +the memory map. It will treat anything outside of the memory map as +RAM. Project layout ============== From 747cc58c2c57f259430eeede8386be4214d00c9d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 21 Jan 2013 12:48:37 +0100 Subject: [PATCH 27/42] STLINK: Unconditionally enable MCO from 8 MHz HSE to PA8 as on original firmware. F3 Discovery has has no quarz for the F3 and needs it. --- src/platforms/stlink/platform.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 70ca6788..40dcf8ff 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -62,6 +62,12 @@ int platform_init(void) gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, LED_IDLE_RUN); + /* unconditionally activate MCO on PORTA8 with HSE*/ + RCC_CFGR &= ~( 0xf<< 24); + RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ From 29fc42e4198029bb958d9feb68787b9d2eeb124f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 21 Jan 2013 13:50:02 +0100 Subject: [PATCH 28/42] Add note about -mfloat-abi=hard versus -mfloat-abi=soft --- HACKING | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/HACKING b/HACKING index e79d5730..ee1fc24b 100644 --- a/HACKING +++ b/HACKING @@ -44,6 +44,16 @@ over USB: The device should reset and re-enumerate as a CDC-ACM device implementing the GDB protocol. +Errors when compiling libopencm3 +------------------------------- +If while compiling libopencm3 you get an error like +arm-none-eabi/bin/ld: error: cdcacm.elf uses VFP register arguments, \ + arm-none-eabi/lib/thumb/v7m/libc.a(lib_a-memcpy-stub.o) does not +your toolchain and libopencm3 disagree on the calling convention for floation +point functions on the F4. Change in +lib/stm32/f4/Makefile and examples/stm32/f4/Makefile.include all apperance of +-mfloat-abi=hard to -mfloat-abi=soft +This doesn't matter for blackmagic, as it doesn't use floating point. Compiling as a Linux application using FT2232 hardware ------------------------------------------------------ From 09e2d00b8e16d8acffa9759b159b0281efb7d667 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 22 Jan 2013 18:49:11 +0100 Subject: [PATCH 29/42] STM32F4: Add option byte handling --- src/stm32f4.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/stm32f4.c b/src/stm32f4.c index ecf99e1e..364fef83 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -36,6 +36,15 @@ #include "general.h" #include "adiv5.h" #include "target.h" +#include "command.h" + +static bool stm32f4_cmd_option(target *t, int argc, char *argv[]); + +const struct command_s stm32f4_cmd_list[] = { + {"option", (cmd_handler)stm32f4_cmd_option, "Manipulate option bytes"}, + {NULL, NULL, NULL} +}; + static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len); static int stm32f4_flash_write(struct target_s *target, uint32_t dest, @@ -85,9 +94,16 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_SR_BSY (1 << 16) +#define FLASH_OPTCR_OPTLOCK (1 << 0) +#define FLASH_OPTCR_OPTSTRT (1 << 1) +#define FLASH_OPTCR_RESERVED 0xf0000013 + #define KEY1 0x45670123 #define KEY2 0xCDEF89AB +#define OPTKEY1 0x08192A3B +#define OPTKEY2 0x4C5D6E7F + #define SR_ERROR_MASK 0xF2 #define SR_EOP 0x01 @@ -145,6 +161,7 @@ bool stm32f4_probe(struct target_s *target) target->xml_mem_map = stm32f4_xml_memory_map; target->flash_erase = stm32f4_flash_erase; target->flash_write = stm32f4_flash_write; + target_add_commands(target, stm32f4_cmd_list, "STM32F4"); return true; } return false; @@ -234,3 +251,45 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, return 0; } +static bool stm32f4_option_write(target *t, uint32_t value) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY1); + adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY2); + value &= ~FLASH_OPTCR_RESERVED; + while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + if(target_check_error(t)) + return -1; + + /* WRITE option bytes instruction */ + adiv5_ap_mem_write(ap, FLASH_OPTCR, value); + adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); + /* Read FLASH_SR to poll for BSY bit */ + while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + if(target_check_error(t)) + return false; + adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK); + return true; +} + +static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) +{ + uint32_t addr, val; + + ADIv5_AP_t *ap = adiv5_target_ap(t); + + if ((argc == 3) && !strcmp(argv[1], "write")) { + val = strtoul(argv[2], NULL, 0); + stm32f4_option_write(t, val); + } else { + gdb_out("usage: monitor option write \n"); + } + + for (int i = 0; i < 0xf; i += 8) { + addr = 0x1fffC000 + i; + val = adiv5_ap_mem_read(ap, addr); + gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); + } + return true; +} From 73d120577b08b718356086f071ffbd070b818f2f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 22 Jan 2013 19:04:51 +0100 Subject: [PATCH 30/42] usbdfu: Write protect the bootloader sector on F4 --- src/platforms/stm32/usbdfu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 55318ec6..212b88e3 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -408,7 +408,10 @@ int main(void) } #if defined (STM32F4) - /* don' touch option bits for now */ + if ((FLASH_OPTCR & 0x10000) != 0) { + flash_program_option_bytes(FLASH_OPTCR & ~0x10000); + flash_lock_option_bytes(); + } #else if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); From ce059cc8edee9163fb5f9517468e337616932471 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 4 Nov 2012 12:03:35 +0100 Subject: [PATCH 31/42] LIBFTDI: Propagate the command line arguments to platform_init --- src/include/gdb_if.h | 4 +++- src/main.c | 9 +++++++-- src/platforms/libftdi/Makefile.inc | 1 + src/platforms/libftdi/platform.c | 2 +- src/platforms/libftdi/platform.h | 4 ++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/include/gdb_if.h b/src/include/gdb_if.h index 0d6a6029..33074549 100644 --- a/src/include/gdb_if.h +++ b/src/include/gdb_if.h @@ -21,10 +21,12 @@ #ifndef __GDB_IF_H #define __GDB_IF_H +#if !defined(LIBFTDI) #include +void gdb_usb_out_cb(usbd_device *dev, uint8_t ep); +#endif int gdb_if_init(void); -void gdb_usb_out_cb(usbd_device *dev, uint8_t ep); unsigned char gdb_if_getchar(void); unsigned char gdb_if_getchar_to(int timeout); void gdb_if_putchar(unsigned char c, int flush); diff --git a/src/main.c b/src/main.c index 4b46764d..4921aedc 100644 --- a/src/main.c +++ b/src/main.c @@ -34,10 +34,15 @@ #include "target.h" int -main(void) +main(int argc, char **argv) { +#if defined(LIBFTDI) + assert(platform_init(argc, argv) == 0); +#else + (void) argc; + (void) argv; assert(platform_init() == 0); - +#endif PLATFORM_SET_FATAL_ERROR_RECOVERY(); gdb_main(); diff --git a/src/platforms/libftdi/Makefile.inc b/src/platforms/libftdi/Makefile.inc index 095b3a7a..fa6292b5 100644 --- a/src/platforms/libftdi/Makefile.inc +++ b/src/platforms/libftdi/Makefile.inc @@ -1 +1,2 @@ +CFLAGS += -DLIBFTDI LDFLAGS += -lftdi -lusb diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index bcf742cf..2b541e2e 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -32,7 +32,7 @@ struct ftdi_context *ftdic; static uint8_t outbuf[BUF_SIZE]; static uint16_t bufptr = 0; -int platform_init(void) +int platform_init(int argc, char **argv) { int err; diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index 56393588..e23bf96c 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -40,12 +40,12 @@ #define PLATFORM_FATAL_ERROR(error) abort() #define PLATFORM_SET_FATAL_ERROR_RECOVERY() -#define morse(x, y) do {} while(0) +#define morse(x, y) fprintf(stderr,"%s\n", x) #define morse_msg 0 extern struct ftdi_context *ftdic; -int platform_init(void); +int platform_init(int argc, char **argv); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); From 6157754201f7b6d12497ee178106249ed201074c Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 4 Nov 2012 13:23:12 +0100 Subject: [PATCH 32/42] libftdi: List some know cables and allow to specify cable and serial --- src/platforms/libftdi/jtagtap.c | 8 -- src/platforms/libftdi/platform.c | 130 ++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 10 deletions(-) diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index fdfb0518..cd58707c 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -55,14 +55,6 @@ int jtagtap_init(void) assert(ftdic != NULL); - if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_MPSSE)) != 0) { - fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", - err, ftdi_get_error_string(ftdic)); - abort(); - } - - assert(ftdi_write_data(ftdic, "\x86\x00\x00\x80\xA8\xAB", 6) == 6); - /* Go to JTAG mode for SWJ-DP */ for(int i = 0; i <= 50; i++) jtagtap_next(1, 0); /* Reset SW-DP */ jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */ diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 2b541e2e..d7f11ddc 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -32,9 +32,125 @@ struct ftdi_context *ftdic; static uint8_t outbuf[BUF_SIZE]; static uint16_t bufptr = 0; +static struct cable_desc_s { + int vendor; + int product; + int interface; + uint8_t dbus_data; + uint8_t dbus_ddr; + uint8_t cbus_data; + uint8_t cbus_ddr; + char *description; + char * name; +} cable_desc[] = { + { + .vendor = 0x0403, + .product = 0x6010, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .description = "FTDIJTAG", + .name = "ftdijtag" + }, + { + .vendor = 0x15b1, + .product = 0x0003, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .name = "olimex" + }, + { + .vendor = 0x0403, + .product = 0xbdc8, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .name = "turtelizer" + }, + { + .vendor = 0x0403, + .product = 0xbdc8, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .name = "jtaghs1" + }, + { + .vendor = 0x0403, + .product = 0xbdc8, + .interface = INTERFACE_A, + .dbus_data = 0xA8, + .dbus_ddr = 0xAB, + .name = "ftdi" + }, + { + .vendor = 0x0403, + .product = 0x6014, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x0B, + .name = "ft232h" + }, + { + .vendor = 0x0403, + .product = 0x6011, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x0B, + .name = "ft4232h" + }, + { + .vendor = 0x15ba, + .product = 0x002b, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .cbus_data = 0x00, + .cbus_ddr = 0x08, + .name = "arm-usb-ocd-h" + }, +}; + int platform_init(int argc, char **argv) { int err; + int c; + int index = 0; + char *serial = NULL; + char * cablename = "ftdi"; + uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0, + SET_BITS_HIGH, 0,0}; + + while((c = getopt(argc, argv, "c:s:")) != -1) { + switch(c) { + case 'c': + cablename = optarg; + break; + case 's': + serial = optarg; + break; + } + } + + for(index = 0; index < sizeof(cable_desc)/sizeof(cable_desc[0]); + index++) + if (strcmp(cable_desc[index].name, cablename) == 0) + break; + + if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){ + fprintf(stderr, "No cable matching %s found\n",cablename); + return -1; + } + + if (cable_desc[index].dbus_data) + ftdi_init[4]= cable_desc[index].dbus_data; + if (cable_desc[index].dbus_ddr) + ftdi_init[5]= cable_desc[index].dbus_ddr; + if (cable_desc[index].cbus_data) + ftdi_init[7]= cable_desc[index].cbus_data; + if(cable_desc[index].cbus_ddr) + ftdi_init[8]= cable_desc[index].cbus_ddr; if(ftdic) { ftdi_usb_close(ftdic); @@ -46,12 +162,14 @@ int platform_init(int argc, char **argv) ftdi_get_error_string(ftdic)); abort(); } - if((err = ftdi_set_interface(ftdic, INTERFACE_A)) != 0) { + if((err = ftdi_set_interface(ftdic, cable_desc[index].interface)) != 0) { fprintf(stderr, "ftdi_set_interface: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } - if((err = ftdi_usb_open(ftdic, FT2232_VID, FT2232_PID)) != 0) { + if((err = ftdi_usb_open_desc( + ftdic, cable_desc[index].vendor, cable_desc[index].product, + cable_desc[index].description, serial)) != 0) { fprintf(stderr, "unable to open ftdi device: %d (%s)\n", err, ftdi_get_error_string(ftdic)); abort(); @@ -78,6 +196,14 @@ int platform_init(int argc, char **argv) abort(); } + if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_MPSSE)) != 0) { + fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", + err, ftdi_get_error_string(ftdic)); + abort(); + } + + assert(ftdi_write_data(ftdic, ftdi_init, 9) == 9); + assert(gdb_if_init() == 0); jtag_scan(NULL); From d868088d78caf96e5e46bdcbc57153e7370d255d Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 23 Jan 2013 00:13:20 +0100 Subject: [PATCH 33/42] STM32L1: Add to the list of known JTAG IDs --- src/jtag_scan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jtag_scan.c b/src/jtag_scan.c index 0dd588ba..bfce1ec8 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -58,6 +58,8 @@ static struct jtag_dev_descr_s { .descr = "ST Microelectronics: STM32, Low density."}, {.idcode = 0x06414041, .idmask = 0x0FFFFFFF, .descr = "ST Microelectronics: STM32, High density."}, + {.idcode = 0x06416041, .idmask = 0x0FFFFFFF, + .descr = "ST Microelectronics: STM32L."}, {.idcode = 0x06418041, .idmask = 0x0FFFFFFF, .descr = "ST Microelectronics: STM32, Connectivity Line."}, {.idcode = 0x06420041, .idmask = 0x0FFFFFFF, From 32b909067b2a34f475a52585b965c195de87c172 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 23 Jan 2013 16:11:17 +0100 Subject: [PATCH 34/42] STM32: Use hardware CRC unit --- src/crc32.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/crc32.c b/src/crc32.c index 25cd53bc..d5c87320 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -21,6 +21,7 @@ #include "platform.h" #include "target.h" +#if !defined(STM32F1) && !defined(STM32F4) static const uint32_t crc32_table[] = { 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, @@ -107,4 +108,31 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) } return crc; } +#else +#include +uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) +{ + uint32_t data; + uint8_t byte; + CRC_CR |= CRC_CR_RESET; + + while (len >3) { + if (target_mem_read_words(target, &data, base, 1) != 0) + return -1; + + CRC_DR = data; + base+=4; + len -= 4; + } + while (len--) { + if (target_mem_read_bytes(target, &byte, base, 1) != 0) + return -1; + + CRC_DR = byte; + base++; + } + return CRC_DR; +} + +#endif From 8415fc829bf5243b3f77c2ac5db73b41c7cbf3e6 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 23 Jan 2013 17:28:34 +0100 Subject: [PATCH 35/42] stm32/cdcacm.c: remove unneeded includes --- src/platforms/stm32/cdcacm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index b6d26020..93b0f330 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -26,9 +26,7 @@ * The device's unique id is used as the USB serial number string. */ -#include #include -#include #include #include #include From 96ae3886ff33e4b88c147ae06e83fe128ef12245 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 24 Jan 2013 18:38:07 +0100 Subject: [PATCH 36/42] stm32:cdcacm/usbdfu: Print version and build information in the product string --- src/platforms/f4discovery/platform.h | 2 +- src/platforms/native/platform.h | 2 +- src/platforms/stlink/platform.h | 2 +- src/platforms/stm32/usbdfu.c | 8 ++++---- src/platforms/stm32_can/platform.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index b19aa115..e7565f2e 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -35,7 +35,7 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO -#define BOARD_IDENT "Black Magic Probe (F4Discovery)" +#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" extern usbd_device *usbdev; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 4a0f2736..de40927e 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -35,7 +35,7 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO -#define BOARD_IDENT "Black Magic Probe" +#define BOARD_IDENT "Black Magic Probe, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade" extern usbd_device *usbdev; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index a5eee6c7..9b765fbe 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -34,7 +34,7 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 -#define BOARD_IDENT "Black Magic Probe (STLINK)" +#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" extern usbd_device *usbdev; diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 212b88e3..d2ae2a93 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -191,13 +191,13 @@ static char serial_no[9]; static const char *usb_strings[] = { "Black Sphere Technologies", #if defined(BLACKMAGIC) - "Black Magic Probe (Upgrade)", + "Black Magic Probe (Upgrade), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #elif defined(DISCOVERY_STLINK) - "Black Magic (Upgrade) for STLink/Discovery", + "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #elif defined(STM32_CAN) - "Black Magic (Upgrade) for STM32_CAN", + "Black Magic (Upgrade) for STM32_CAN, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #elif defined(F4DISCOVERY) - "Black Magic (Upgrade) for F4Discovery", + "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #else #warning "Unhandled board" #endif diff --git a/src/platforms/stm32_can/platform.h b/src/platforms/stm32_can/platform.h index 8b0d567a..b91ddac7 100644 --- a/src/platforms/stm32_can/platform.h +++ b/src/platforms/stm32_can/platform.h @@ -39,7 +39,7 @@ extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 #define CDCACM_UART_ENDPOINT 3 -#define BOARD_IDENT "Black Magic Probe (STM32_CAN)" +#define BOARD_IDENT "Black Magic Probe (STM32_CAN), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (STM32_CAN)" /* Important pin mappings for STM32 implementation: From b1a942aca3e80aaaa8405d313424f1d6f9273bd9 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 30 Jan 2013 17:16:44 +0100 Subject: [PATCH 37/42] STM32F0/3: Handle the option bytes --- src/stm32f1.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/stm32f1.c b/src/stm32f1.c index 456c8125..4cc7b2aa 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -93,6 +93,7 @@ static const char stm32hd_xml_memory_map[] = "" #define FLASH_OBR (FPEC_BASE+0x1C) #define FLASH_WRPR (FPEC_BASE+0x20) +#define FLASH_CR_OBL_LAUNCH (1<<13) #define FLASH_CR_OPTWRE (1 << 9) #define FLASH_CR_STRT (1 << 6) #define FLASH_CR_OPTER (1 << 5) @@ -104,6 +105,7 @@ static const char stm32hd_xml_memory_map[] = "" #define FLASH_OBP_RDP 0x1FFFF800 #define FLASH_OBP_RDP_KEY 0x5aa5 +#define FLASH_OBP_RDP_KEY_F3 0x55AA #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -153,10 +155,9 @@ uint16_t stm32f1_flash_write_stub[] = { bool stm32f1_probe(struct target_s *target) { - uint32_t idcode; - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE); - switch(idcode & 0xFFF) { + target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE) & 0xfff; + switch(target->idcode) { case 0x410: /* Medium density */ case 0x412: /* Low denisty */ case 0x420: /* Value Line, Low-/Medium density */ @@ -164,7 +165,7 @@ bool stm32f1_probe(struct target_s *target) target->xml_mem_map = stm32f1_xml_memory_map; target->flash_erase = stm32md_flash_erase; target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32"); + target_add_commands(target, stm32f1_cmd_list, "STM32 LD/MD"); return true; case 0x414: /* High density */ case 0x418: /* Connectivity Line */ @@ -173,7 +174,7 @@ bool stm32f1_probe(struct target_s *target) target->xml_mem_map = stm32hd_xml_memory_map; target->flash_erase = stm32hd_flash_erase; target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32"); + target_add_commands(target, stm32f1_cmd_list, "STM32 HD/CL"); return true; case 0x422: /* STM32F30x */ case 0x432: /* STM32F37x */ @@ -181,18 +182,18 @@ bool stm32f1_probe(struct target_s *target) target->xml_mem_map = stm32hd_xml_memory_map; target->flash_erase = stm32hd_flash_erase; target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32"); + target_add_commands(target, stm32f1_cmd_list, "STM32F3"); return true; } - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0); - switch(idcode & 0xFFF) { + target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff; + switch(target->idcode) { case 0x440: /* STM32F0 */ target->driver = stm32f0_driver_str; target->xml_mem_map = stm32f1_xml_memory_map; target->flash_erase = stm32md_flash_erase; target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32"); + target_add_commands(target, stm32f1_cmd_list, "STM32F0"); return true; } @@ -338,15 +339,24 @@ static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; - + uint32_t flash_obp_rdp_key; ADIv5_AP_t *ap = adiv5_target_ap(t); + + switch(t->idcode) { + case 0x422: /* STM32F30x */ + case 0x432: /* STM32F37x */ + case 0x440: /* STM32F0 */ + flash_obp_rdp_key = FLASH_OBP_RDP_KEY_F3; + break; + default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY; + } stm32f1_flash_unlock(ap); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2); if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f1_option_erase(t); - stm32f1_option_write(t, FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); + stm32f1_option_write(t, FLASH_OBP_RDP, flash_obp_rdp_key); } else if (argc == 3) { addr = strtol(argv[1], NULL, 0); val = strtol(argv[2], NULL, 0); @@ -356,6 +366,15 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) gdb_out("usage: monitor option \n"); } + if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) { + /* Reload option bytes on F0 and F3*/ + val = adiv5_ap_mem_read(ap, FLASH_CR); + val |= FLASH_CR_OBL_LAUNCH; + stm32f1_option_write(t, FLASH_CR, val); + val &= ~FLASH_CR_OBL_LAUNCH; + stm32f1_option_write(t, FLASH_CR, val); + } + for (int i = 0; i < 0xf; i += 4) { addr = 0x1ffff800 + i; val = adiv5_ap_mem_read(ap, addr); From 31f39339fde9750d80a31cc6d5722fea5ebe97e8 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 3 Feb 2013 14:14:48 +0100 Subject: [PATCH 38/42] stm32/usbdfu.c: Rearrange code to clarify the tasks to be done --- src/platforms/stm32/usbdfu.c | 70 ++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index d2ae2a93..3ffd4da2 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -376,6 +376,7 @@ static int usbdfu_control_request(usbd_device *dev, int main(void) { + /* Check the force bootloader pin*/ #if defined (DISCOVERY_STLINK) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); if(!gpio_get(GPIOC, GPIO13) && stlink_test_nrst()) { @@ -424,9 +425,22 @@ int main(void) } #endif -#if defined (DISCOVERY_STLINK) + /* Set up clock*/ +#if defined (F4DISCOVERY) + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(2100000); +#else + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(900000); +#endif + + /* Handle USB disconnect/connect */ +#if defined(DISCOVERY_STLINK) /* Just in case: Disconnect USB cable by resetting USB Device - and pulling USB_DP low*/ + * and pulling USB_DP low + * Device will reconnect automatically as Pull-Up is hard wired*/ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); @@ -434,57 +448,53 @@ int main(void) gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -#endif -#if defined (F4DISCOVERY) - rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); -#else - rcc_clock_setup_in_hse_8mhz_out_72mhz(); -#endif - -#if defined(DISCOVERY_STLINK) #elif defined(F4DISCOVERY) -#elif defined (STM32_CAN) - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); +#elif defined(STM32_CAN) #else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); #endif - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); - systick_set_reload(2100000); systick_interrupt_enable(); systick_counter_enable(); get_dev_unique_id(serial_no); -#if defined(STM32_CAN) - usbdev = usbd_init(&stm32f107_usb_driver, - &dev, &config, usb_strings, 4); -#elif defined(F4DISCOVERY) +/* Handle LEDs */ +#if defined(F4DISCOVERY) rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); gpio_clear(GPIOD, GPIO12 | GPIO13 | GPIO14 |GPIO15); gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 |GPIO15); +#elif defined (STM32_CAN) + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); +#else + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); +#endif + +/* Set up USB*/ +#if defined(STM32_CAN) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + usbdev = usbd_init(&stm32f107_usb_driver, + &dev, &config, usb_strings, 4); +#elif defined(STM32F2)||defined(STM32F4) + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); /* Set up USB Pins and alternate function*/ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, - GPIO9 | GPIO11 | GPIO12); - gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); - + GPIO9 | GPIO10 | GPIO11 | GPIO12); + gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10| GPIO11 | GPIO12); usbdev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings, 4); #else - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); - usbdev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings, 4); #endif From 327ee49a67772cc7642133cf3f1ecf531e345954 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 3 Feb 2013 14:22:14 +0100 Subject: [PATCH 39/42] usps_f407: add another platform --- src/platforms/stm32/usbdfu.c | 23 ++- src/platforms/usps_f407/Makefile.inc | 36 +++++ src/platforms/usps_f407/Readme | 22 +++ src/platforms/usps_f407/platform.c | 207 ++++++++++++++++++++++++++ src/platforms/usps_f407/platform.h | 208 +++++++++++++++++++++++++++ 5 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 src/platforms/usps_f407/Makefile.inc create mode 100644 src/platforms/usps_f407/Readme create mode 100644 src/platforms/usps_f407/platform.c create mode 100644 src/platforms/usps_f407/platform.h diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index 3ffd4da2..e42e00f1 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -198,6 +198,8 @@ static const char *usb_strings[] = { "Black Magic (Upgrade) for STM32_CAN, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #elif defined(F4DISCOVERY) "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", +#elif defined(USPS_F407) + "Black Magic (Upgrade) for USPS_F407, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")", #else #warning "Unhandled board" #endif @@ -209,7 +211,7 @@ static const char *usb_strings[] = { "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #elif defined(STM32_CAN) "@Internal Flash /0x08000000/4*002Ka,124*002Kg" -#elif defined(F4DISCOVERY) +#elif defined(F4DISCOVERY) || defined(USPS_F407) "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" #else #warning "Unhandled board" @@ -386,6 +388,15 @@ int main(void) #elif defined (F4DISCOVERY) rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); if(!gpio_get(GPIOA, GPIO0)) { +#elif defined (USPS_F407) + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); + /* Pull up an look if external pulled low or if we restart with PB1 low*/ + GPIOB_PUPDR |= 4; + { + int i; + for(i=0; i<100000; i++) __asm__("NOP"); + } + if(gpio_get(GPIOB, GPIO1)) { #else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); if(gpio_get(GPIOB, GPIO12)) { @@ -426,7 +437,7 @@ int main(void) #endif /* Set up clock*/ -#if defined (F4DISCOVERY) +#if defined (F4DISCOVERY) || defined(USPS_F407) rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(2100000); @@ -449,6 +460,7 @@ int main(void) gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); #elif defined(F4DISCOVERY) +#elif defined(USPS_F407) #elif defined(STM32_CAN) #else rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); @@ -466,6 +478,11 @@ int main(void) gpio_clear(GPIOD, GPIO12 | GPIO13 | GPIO14 |GPIO15); gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 |GPIO15); +#elif defined(USPS_F407) + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); + gpio_clear(GPIOB, GPIO2); + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, + GPIO2); #elif defined (STM32_CAN) gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); @@ -562,6 +579,8 @@ void sys_tick_handler() led2_state++; #elif defined (F4DISCOVERY) gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */ +#elif defined (USPS_F407) + gpio_toggle(GPIOB, GPIO2); /* Green LED on/off */ #elif defined(STM32_CAN) gpio_toggle(GPIOB, GPIO0); /* LED2 on/off */ #else diff --git a/src/platforms/usps_f407/Makefile.inc b/src/platforms/usps_f407/Makefile.inc new file mode 100644 index 00000000..3bf262db --- /dev/null +++ b/src/platforms/usps_f407/Makefile.inc @@ -0,0 +1,36 @@ +CROSS_COMPILE ?= arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ + -DSTM32F4 -DUSPS_F407 -I../libopencm3/include + +LDFLAGS_BOOT = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ + -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ + -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ + -L../libopencm3/lib +LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8010000 + +VPATH += platforms/stm32 + +SRC += cdcacm.c \ + platform.c \ + traceswo.c \ + usbuart.c \ + +all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex + +blackmagic.bin: blackmagic + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu: usbdfu.o + $(CC) $^ -o $@ $(LDFLAGS_BOOT) + +blackmagic_dfu.bin: blackmagic_dfu + $(OBJCOPY) -O binary $^ $@ + +blackmagic_dfu.hex: blackmagic_dfu + $(OBJCOPY) -O ihex $^ $@ + +host_clean: + -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/usps_f407/Readme b/src/platforms/usps_f407/Readme new file mode 100644 index 00000000..ce020152 --- /dev/null +++ b/src/platforms/usps_f407/Readme @@ -0,0 +1,22 @@ +Hardware +======== +Find eagle schematics at +https://github.com/UweBonnes/wiki_fuer_alex/tree/master/layout +The board can be used for F1/L1/F2 and F4 with some changed parts, +see the datasheet and hints in the schematic + +JTAG: Reuse the JTAG Connector, unconnect JTAG Tap and reuse JTAG pins +in inverse direction. +Forced boot request: Connect Jumper Wire X11-34/X11-40 to pull PC15 +to ground +System Bootloader: Jumper Boot0 to '1' + +Led: PB2 (Boot1) + +Application start address: +========================= + +Use 0x8010000 +- lower 3 16 k pages may be used for parameter storage +- Erasing a single 64 k Page is faster then erasing 2 16 k Pages + eventual the 64 k page diff --git a/src/platforms/usps_f407/platform.c b/src/platforms/usps_f407/platform.c new file mode 100644 index 00000000..45417870 --- /dev/null +++ b/src/platforms/usps_f407/platform.c @@ -0,0 +1,207 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform.h" +#include "jtag_scan.h" +#include + +#include + +uint8_t running_status; +volatile uint32_t timeout_counter; + +jmp_buf fatal_error_jmpbuf; + +static void morse_update(void); + +int platform_init(void) +{ + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + + /* Enable peripherals */ + rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); + + /* Fix all flaoting pins*/ + gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, + 0x1ff); + + gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, + 0xffe2); + + gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, + 0xf3ff); + + /* Set up USB Pins and alternate function*/ + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO9 | GPIO10| GPIO11 | GPIO12); + gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10| GPIO11 | GPIO12); + + /* Set TMS/TCK/TDI to high speed*/ + GPIOA_OSPEEDR &=~0xfc00; + GPIOA_OSPEEDR |= 0xa800; + gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, + TMS_PIN | TCK_PIN | TDI_PIN); + + gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, + GPIO_PUPD_NONE, + TDO_PIN | TRST_PIN); + + gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, + LED_UART ); + + /* Setup heartbeat timer */ + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(168000000/(10*8)); /* 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 = 0x10000; // Relocate interrupt vector table here + + cdcacm_init(); + + jtag_scan(NULL); + + return 0; +} + +void platform_delay(uint32_t delay) +{ + timeout_counter = delay; + while(timeout_counter); +} + +void sys_tick_handler(void) +{ + if(timeout_counter) + timeout_counter--; + + morse_update(); +} + + +/* Morse code patterns and lengths */ +static const struct { + uint16_t code; + uint8_t bits; +} morse_letter[] = { + { 0b00011101, 8}, // 'A' .- + { 0b000101010111, 12}, // 'B' -... + { 0b00010111010111, 14}, // 'C' -.-. + { 0b0001010111, 10}, // 'D' -.. + { 0b0001, 4}, // 'E' . + { 0b000101110101, 12}, // 'F' ..-. + { 0b000101110111, 12}, // 'G' --. + { 0b0001010101, 10}, // 'H' .... + { 0b000101, 6}, // 'I' .. + {0b0001110111011101, 16}, // 'J' .--- + { 0b000111010111, 12}, // 'K' -.- + { 0b000101011101, 12}, // 'L' .-.. + { 0b0001110111, 10}, // 'M' -- + { 0b00010111, 8}, // 'N' -. + { 0b00011101110111, 14}, // 'O' --- + { 0b00010111011101, 14}, // 'P' .--. + {0b0001110101110111, 16}, // 'Q' --.- + { 0b0001011101, 10}, // 'R' .-. + { 0b00010101, 8}, // 'S' ... + { 0b000111, 6}, // 'T' - + { 0b0001110101, 10}, // 'U' ..- + { 0b000111010101, 12}, // 'V' ...- + { 0b000111011101, 12}, // 'W' .-- + { 0b00011101010111, 14}, // 'X' -..- + {0b0001110111010111, 16}, // 'Y' -.-- + { 0b00010101110111, 14}, // 'Z' --.. +}; + + +const char *morse_msg; +static const char * volatile morse_ptr; +static char morse_repeat; + +void morse(const char *msg, char repeat) +{ + morse_msg = morse_ptr = msg; + morse_repeat = repeat; + SET_ERROR_STATE(0); +} + +static void morse_update(void) +{ + static uint16_t code; + static uint8_t bits; + + if(!morse_ptr) return; + + if(!bits) { + char c = *morse_ptr++; + if(!c) { + if(morse_repeat) { + morse_ptr = morse_msg; + c = *morse_ptr++; + } else { + morse_ptr = 0; + return; + } + } + if((c >= 'A') && (c <= 'Z')) { + c -= 'A'; + code = morse_letter[c].code; + bits = morse_letter[c].bits; + } else { + code = 0; bits = 4; + } + } + SET_ERROR_STATE(code & 1); + code >>= 1; bits--; +} + +const char *platform_target_voltage(void) +{ + return "ABSENT!"; +} + +void assert_boot_pin(void) +{ + /* Flag Bootloader Request by mimicing a pushed USER button*/ + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, GPIO1); + gpio_clear(GPIOB, GPIO11); +} diff --git a/src/platforms/usps_f407/platform.h b/src/platforms/usps_f407/platform.h new file mode 100644 index 00000000..acdfd5c7 --- /dev/null +++ b/src/platforms/usps_f407/platform.h @@ -0,0 +1,208 @@ +/* + * 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 the platform specific functions for the STM32 + * implementation. + */ +#ifndef __PLATFORM_H +#define __PLATFORM_H + +#include +#include + +#include +#include + +#include "gdb_packet.h" + +#define INLINE_GPIO +#define CDCACM_PACKET_SIZE 64 +#define PLATFORM_HAS_TRACESWO +#define BOARD_IDENT "Black Magic Probe (USPS_F407), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define DFU_IDENT "Black Magic Firmware Upgrade (USPS_F407)" + +extern usbd_device *usbdev; +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +/* Important pin mappings for STM32 implementation: + * + * LED0 = PB2 + + * TPWR = XXX (input) -- analogue on mini design ADC1, ch8 + * nTRST = PD0 + * SRST_OUT = PD1 + * TDI = PA1 + * TMS = PA3 (input for SWDP) + * TCK = PA8 + * TDO = PB4 (input) + * nSRST = PD2 (input) + * + * USB cable pull-up: PA8 + * USB VBUS detect: PB13 -- New on mini design. + * Enable pull up for compatibility. + * Force DFU mode button: PB1 + */ + +/* Hardware definitions... */ +#define JTAG_PORT GPIOA +#define TDI_PORT JTAG_PORT +#define TMS_PORT JTAG_PORT +#define TCK_PORT JTAG_PORT +#define TDO_PORT GPIOB +#define TMS_PIN GPIO13 +#define TCK_PIN GPIO14 +#define TDI_PIN GPIO15 +#define TDO_PIN GPIO3 + +#define SWDIO_PORT JTAG_PORT +#define SWCLK_PORT JTAG_PORT +#define SWDIO_PIN TMS_PIN +#define SWCLK_PIN TCK_PIN + +#define TRST_PORT TDO_PORT +#define TRST_PIN GPIO4 +#define SRST_PORT GPIOB +#define SRST_PIN GPIO4 + +#define LED_PORT GPIOB +#define LED_PORT_UART GPIOB +#define LED_UART GPIO2 + +#define TMS_SET_MODE() gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, TMS_PIN); +#define SWDIO_MODE_FLOAT() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); + +#define SWDIO_MODE_DRIVE() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); + + +#define USB_DRIVER stm32f107_usb_driver +#define USB_IRQ NVIC_OTG_FS_IRQ +#define USB_ISR otg_fs_isr +/* 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_USBUSART (1 << 4) +#define IRQ_PRI_TRACE (0 << 4) + +#define USBUSART USART3 +#define USBUSART_CR1 USART3_CR1 +#define USBUSART_IRQ NVIC_USART3_IRQ +#define USBUSART_APB_ENR RCC_APB1ENR +#define USBUSART_CLK_ENABLE RCC_APB1ENR_USART3EN +#define USBUSART_TX_PORT GPIOC +#define USBUSART_TX_PIN GPIO10 +#define USBUSART_RX_PORT GPIOC +#define USBUSART_RX_PIN GPIO11 +#define USBUSART_ISR usart3_isr + +#define UART_PIN_SETUP() do { \ + gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_TX_PIN); \ + gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_RX_PIN); \ + gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \ + gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \ + } while(0) + +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR tim3_isr + +#define DEBUG(...) + +extern uint8_t running_status; +extern volatile uint32_t timeout_counter; + +extern jmp_buf fatal_error_jmpbuf; + +extern const char *morse_msg; + +#define gpio_set_val(port, pin, val) do { \ + if(val) \ + gpio_set((port), (pin)); \ + else \ + gpio_clear((port), (pin)); \ +} while(0) + +#define SET_RUN_STATE(state) {running_status = (state);} +#define SET_IDLE_STATE(state) +#define SET_ERROR_STATE(state) + +#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} +#define PLATFORM_FATAL_ERROR(error) { \ + if(running_status) gdb_putpacketz("X1D"); \ + else gdb_putpacketz("EFF"); \ + running_status = 0; \ + target_list_free(); \ + morse("TARGET LOST.", 1); \ + longjmp(fatal_error_jmpbuf, (error)); \ +} + +int platform_init(void); +void morse(const char *msg, char repeat); +const char *platform_target_voltage(void); +int platform_hwversion(void); +void platform_delay(uint32_t delay); + +/* */ +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +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 +#define vasprintf vasiprintf + +#ifdef INLINE_GPIO +static inline void _gpio_set(u32 gpioport, u16 gpios) +{ + GPIO_BSRR(gpioport) = gpios; +} +#define gpio_set _gpio_set + +static inline void _gpio_clear(u32 gpioport, u16 gpios) +{ + GPIO_BSRR(gpioport) = gpios<<16; +} +#define gpio_clear _gpio_clear + +static inline u16 _gpio_get(u32 gpioport, u16 gpios) +{ + return (u16)GPIO_IDR(gpioport) & gpios; +} +#define gpio_get _gpio_get +#endif + +#endif + +#define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) +void assert_boot_pin(void); +#define setup_vbus_irq() From f8ea9542752005ca3bbbcb62fffc3fe38b01d011 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 11 Feb 2013 19:36:22 +0100 Subject: [PATCH 40/42] STLINK: Add pointer to Discoveryboard modification instructions --- src/platforms/stlink/Readme | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/platforms/stlink/Readme diff --git a/src/platforms/stlink/Readme b/src/platforms/stlink/Readme new file mode 100644 index 00000000..a677e559 --- /dev/null +++ b/src/platforms/stlink/Readme @@ -0,0 +1,3 @@ +Find a description how to modify a Discovery Board to use it's Stlink as +black magic debug at +http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe \ No newline at end of file From dee82a0d4fe2b649611525e5415f19186a051dfa Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 15 Feb 2013 17:39:27 +0100 Subject: [PATCH 41/42] Document changes between ST-Link V1 and V2 and implement needed changes --- src/platforms/stlink/Readme | 10 +++++- src/platforms/stlink/platform.c | 62 +++++++++++++++++++++++++------- src/platforms/stlink/platform.h | 4 +-- src/platforms/stm32/usbdfu.c | 64 +++++++++++++++++++++++++-------- 4 files changed, 111 insertions(+), 29 deletions(-) diff --git a/src/platforms/stlink/Readme b/src/platforms/stlink/Readme index a677e559..b20a6db1 100644 --- a/src/platforms/stlink/Readme +++ b/src/platforms/stlink/Readme @@ -1,3 +1,11 @@ Find a description how to modify a Discovery Board to use it's Stlink as black magic debug at -http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe \ No newline at end of file +http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe + +Differences between V1/V2 + + V1 V2 +ID Pins PC13/14 unconnected PC 13 pulled low +LED STLINK PA8, active High PA9, Dual Led +MCO Out NA PA8 +RESET(Target) T_JRST(PB1) NRST (PB0) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 40dcf8ff..5eaf5fcd 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -41,6 +41,34 @@ volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; +uint16_t led_idle_run; +/* Pins PC[14:13] are used to detect hardware revision. Read + * 11 for STLink V1 e.g. on VL Discovery, tag as hwversion 0 + * 10 for STLink V2 e.g. on F4 Discovery, tag as hwversion 1 + */ +int platform_hwversion(void) +{ + static int hwversion = -1; + int i; + if (hwversion == -1) { + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, + GPIO14 | GPIO13); + gpio_set(GPIOC, GPIO14 | GPIO13); + for (i = 0; i<10; i++) + hwversion = ~(gpio_get(GPIOC, GPIO14 | GPIO13) >> 13) & 3; + switch (hwversion) + { + case 0: + led_idle_run = GPIO8; + break; + default: + led_idle_run = GPIO9; + } + } + return hwversion; +} + int platform_init(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -49,8 +77,19 @@ 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_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + /* On Rev 1 unconditionally activate MCO on PORTA8 with HSE + * platform_hwversion() also needed to initialize led_idle_run! + */ + if (platform_hwversion() == 1) + { + RCC_CFGR &= ~( 0xf<< 24); + RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + } /* Setup GPIO ports */ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); @@ -60,13 +99,7 @@ int platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, LED_IDLE_RUN); - - /* unconditionally activate MCO on PORTA8 with HSE*/ - RCC_CFGR &= ~( 0xf<< 24); - RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); @@ -96,7 +129,7 @@ void platform_delay(uint32_t delay) void sys_tick_handler(void) { if(running_status) - gpio_toggle(LED_PORT, LED_IDLE_RUN); + gpio_toggle(LED_PORT, led_idle_run); if(timeout_counter) timeout_counter--; @@ -129,9 +162,14 @@ void disconnect_usb(void) void assert_boot_pin(void) { - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); - gpio_set(GPIOC, GPIO13); + uint32_t crl = GPIOA_CRL; + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + /* Enable Pull on GPIOA1. We don't rely on the external pin + * really pulled, but only on the value of the CNF register + * changed from the reset value + */ + crl &= 0xffffff0f; + crl |= 0x80; + GPIOA_CRL = crl; } void setup_vbus_irq(void){}; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 9b765fbe..d22a4e22 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -81,7 +81,6 @@ extern usbd_device *usbdev; /* 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 GPIO9 #define TMS_SET_MODE() \ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ @@ -134,8 +133,9 @@ extern const char *morse_msg; gpio_clear((port), (pin)); \ } while(0) +extern uint16_t led_idle_run; #define SET_RUN_STATE(state) {running_status = (state);} -#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} +#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} #define PLATFORM_FATAL_ERROR(error) { \ diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index e42e00f1..b582a441 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -54,17 +54,44 @@ u8 usbd_control_buffer[1024]; #endif #if defined(DISCOVERY_STLINK) +uint8_t rev; +uint16_t led_idle_run; u32 led2_state = 0; int stlink_test_nrst(void) { -/* Test if NRST is pulled down*/ +/* Test if JRST/NRST is pulled down*/ int i; uint16_t nrst; + uint16_t pin; + + /* First, get Board revision by pulling PC13/14 up. Read + * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 + * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 + */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14|GPIO13); + gpio_set(GPIOC, GPIO14|GPIO13); + for (i=0; i< 100; i++) + rev = (~(gpio_get(GPIOC, GPIO14|GPIO13))>>13) & 3; + + switch (rev) + { + case 0: + pin = GPIO1; + led_idle_run= GPIO8; + break; + default: + pin = GPIO0; + led_idle_run = GPIO9; + } + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); - gpio_set(GPIOB, GPIO0); - for (i=0; i< 100000; i++) - nrst = gpio_get(GPIOB, GPIO0); + GPIO_CNF_INPUT_PULL_UPDOWN, pin); + gpio_set(GPIOB, pin); + for (i=0; i< 100; i++) + nrst = gpio_get(GPIOB, pin); return (nrst)?1:0; } #endif @@ -380,8 +407,12 @@ int main(void) { /* Check the force bootloader pin*/ #if defined (DISCOVERY_STLINK) - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - if(!gpio_get(GPIOC, GPIO13) && stlink_test_nrst()) { + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); +/* Check value of GPIOA1 configuration. This pin is unconnected on + * STLink V1 and V2. If we have a value other than the reset value (0x4), + * we have a warm start and request Bootloader entry + */ + if(((GPIOA_CRL & 0x40) == 0x40) && stlink_test_nrst()) { #elif defined (STM32_CAN) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); if(!gpio_get(GPIOA, GPIO0)) { @@ -569,14 +600,19 @@ static char *get_dev_unique_id(char *s) void sys_tick_handler() { -#if defined(DISCOVERY_STLINK) - if (led2_state & 1) - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO9); + #if defined(DISCOVERY_STLINK) + if (rev == 0) + gpio_toggle(GPIOA, led_idle_run); else - gpio_set_mode(GPIOA, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_ANALOG, GPIO9); - led2_state++; + { + if (led2_state & 1) + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); + else + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, led_idle_run); + led2_state++; + } #elif defined (F4DISCOVERY) gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */ #elif defined (USPS_F407) From ff8de3977411011c3540bff3a6e781d82e7f1d42 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 15 Feb 2013 17:55:36 +0100 Subject: [PATCH 42/42] usbuart: Don't try to send until configured. Enumeration may hang else --- src/platforms/stm32/usbuart.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index fac7b96a..1c71105d 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -126,6 +126,12 @@ void USBUSART_ISR(void) { char c = usart_recv(USBUSART); + /* Don't try to write until we are configured. + * Otherwise enumeration hanged in some cases. + */ + if (cdcacm_get_config() != 1) + return; + gpio_set(LED_PORT_UART, LED_UART); /* Try to send now */