From 49148e76706e5e24c2ba7f6ccc1d7ec4736ab2f3 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 3 Mar 2021 15:24:13 +0000 Subject: support cheap chinese blue pill boards, make usb dfu compatible with dfuse --- .gitignore | 2 + Makefile.include | 4 +- Makefile.rules | 6 +- app/Makefile | 29 +++- app/cdcacm.c | 188 +++++++--------------- app/dfu.c | 28 ++-- app/dummy_kb.c | 26 +++ app/gdb.script | 2 + app/i2c_bb.c | 70 ++++---- app/i2c_hw.c | 12 +- app/main.c | 34 ++-- app/project.h | 11 +- app/prototypes.h | 20 ++- app/ring.c | 12 +- app/ticker.c | 24 ++- app/usart.c | 18 +-- app/usb.c | 139 ++++++++++++++++ app/vuart.c | 45 +++--- boot/Makefile | 16 ++ boot/gdb.script | 2 + boot/usbdfu.c | 448 +++++++++++++++++++++++++++++----------------------- id.h | 5 +- tools/dfuse-pack.py | 256 ++++++++++++++++++++++++++++++ 23 files changed, 919 insertions(+), 478 deletions(-) create mode 100644 app/dummy_kb.c create mode 100644 app/gdb.script create mode 100644 app/usb.c create mode 100644 boot/gdb.script create mode 100755 tools/dfuse-pack.py diff --git a/.gitignore b/.gitignore index e46adcb..ac9bbcd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ *.hex *~ *.dfu +*.bin +*.orig diff --git a/Makefile.include b/Makefile.include index 5d6f84f..389aa68 100644 --- a/Makefile.include +++ b/Makefile.include @@ -28,8 +28,8 @@ ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd # OpenOCD specific variables OOCD ?= openocd -#OOCD_INTERFACE ?= ../oocd/interface/stlink-v2.cfg -OOCD_INTERFACE ?= ../oocd/interface/j-link.cfg +OOCD_INTERFACE ?= ../oocd/interface/stlink-v2.cfg +#OOCD_INTERFACE ?= ../oocd/interface/j-link.cfg OOCD_BOARD ?= ../oocd/board/STM32F103R_BOARD.cfg ################################################################################ diff --git a/Makefile.rules b/Makefile.rules index 28422d9..6e9fe6c 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -149,9 +149,9 @@ flash: $(BINARY).flash @#printf " OBJCOPY $(*).hex\n" $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex -%.dfu: %.elf - @#printf " OBJCOPY $(*).dfu\n" - $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).dfu +#%.dfu: %.elf +# @#printf " OBJCOPY $(*).dfu\n" +# $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).dfu %.srec: %.elf @#printf " OBJCOPY $(*).srec\n" diff --git a/app/Makefile b/app/Makefile index dc5503b..e264ad4 100644 --- a/app/Makefile +++ b/app/Makefile @@ -24,7 +24,7 @@ PROG=serial_over_dp V=1 default: ${PROG}.elf -CSRCS= main.c cdcacm.c dfu.c i2c_bb.c vuart.c ring.c usart.c i2c_hw.c ticker.c ddc.c +CSRCS= main.c cdcacm.c dfu.c i2c_bb.c vuart.c ring.c usart.c i2c_hw.c ticker.c ddc.c dummy_kb.c usb.c HSRCS = project.h @@ -38,14 +38,37 @@ VID=$(shell printf '\#include "id.h"\nID_VENDOR' | ${CC} -I.. -E - | grep -v ^\# INCLUDES += -I.. -dfu:${PROG}.dfu - dfu-util -R -a 0 -d ${VID}:${DID} -s 0x08002000:leave -D $< + +%.bin: %.elf + $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin + +%.dfu:%.bin + ../tools/dfuse-pack.py -D 0x483:0xff03 -b 0x08002000:$< $@ + +dfu:${PROG}.bin + dfu-util -R -a 0 -d 0483:ff03,0483:df11 -s 0x08002000:leave -D $< program: ${PROG}.elf echo halt | nc -t localhost 4444 echo flash write_image erase ${PWD}/$< 0x2000 | nc -t localhost 4444 echo reset run | nc -t localhost 4444 +ds: + $(Q)$(OOCD) -f $(OOCD_INTERFACE) \ + -f $(OOCD_BOARD) \ + +debug: ${PROG}.elf + ${PREFIX}-gdb -x gdb.script ${PROG}.elf + +reset: + $(Q)$(OOCD) -f $(OOCD_INTERFACE) \ + -f $(OOCD_BOARD) \ + -c "init" -c "reset run" \ + -c shutdown + + + + protos: echo -n > prototypes.h ${CPROTO} $(INCLUDES) $(DEFINES) -e -v ${CSRCS} > prototypes.h.tmp diff --git a/app/cdcacm.c b/app/cdcacm.c index b300241..f6a1b0f 100644 --- a/app/cdcacm.c +++ b/app/cdcacm.c @@ -9,30 +9,17 @@ static uint8_t cdcacm_rx_ring_buf[BUFFER_SIZE]; ring_t cdcacm_tx_ring; static uint8_t cdcacm_tx_ring_buf[BUFFER_SIZE]; +static int cdcacm_ready = 0; -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_CDC, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = 64, - .idVendor = ID_VENDOR, - .idProduct = ID_PRODUCT, - .bcdDevice = 0x0200, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - +#define COMM_EP 0x83 +#define DATA_IN 0x01 +#define DATA_OUT 0x82 static const struct usb_endpoint_descriptor comm_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, + .bEndpointAddress = COMM_EP, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .wMaxPacketSize = 16, .bInterval = 255, @@ -43,7 +30,7 @@ static const struct usb_endpoint_descriptor data_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, + .bEndpointAddress = DATA_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, @@ -51,7 +38,7 @@ static const struct usb_endpoint_descriptor data_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, + .bEndpointAddress = DATA_OUT, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, @@ -63,7 +50,7 @@ static const struct { struct usb_cdc_call_management_descriptor call_mgmt; struct usb_cdc_acm_descriptor acm; struct usb_cdc_union_descriptor cdc_union; -} __attribute__ ( (packed)) cdcacm_functional_descriptors = { +} __attribute__ ((packed)) cdcacm_functional_descriptors = { .header = { .bFunctionLength = sizeof (struct usb_cdc_header_descriptor), .bDescriptorType = CS_INTERFACE, @@ -76,7 +63,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bmCapabilities = 0, - .bDataInterface = 1, + .bDataInterface = 3, }, .acm = { .bFunctionLength = sizeof (struct usb_cdc_acm_descriptor), @@ -88,15 +75,15 @@ static const struct { .bFunctionLength = sizeof (struct usb_cdc_union_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, + .bControlInterface = 2, + .bSubordinateInterface0 = 3, } }; -static const struct usb_interface_descriptor comm_iface = { +const struct usb_interface_descriptor comm_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, + .bInterfaceNumber = 2, .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_CDC, @@ -108,10 +95,10 @@ static const struct usb_interface_descriptor comm_iface = { .extralen = sizeof (cdcacm_functional_descriptors) }; -static const struct usb_interface_descriptor data_iface = { +const struct usb_interface_descriptor data_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, + .bInterfaceNumber = 3, .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_DATA, @@ -121,71 +108,30 @@ static const struct usb_interface_descriptor data_iface = { .endpoint = data_endp, }; -static const struct usb_interface ifaces[] = { - { - .num_altsetting = 1, - .altsetting = &comm_iface, - }, - { - .num_altsetting = 1, - .altsetting = &data_iface, - }, -#ifdef INCLUDE_DFU_INTERFACE - { - .num_altsetting = 1, - .altsetting = &dfu_iface, - }, -#endif -}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, -#ifdef INCLUDE_DFU_INTERFACE - .bNumInterfaces = 3, -#else - .bNumInterfaces = 2, -#endif - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - .interface = ifaces, -}; -static const char *usb_strings[] = { - "Meh", - "Fish", - "Soup", -#ifdef INCLUDE_DFU_INTERFACE - "DFU", -#endif +const struct usb_iface_assoc_descriptor cdc_iface_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 = 6, }; -/* Buffer to be used for control requests. */ -uint8_t usbd_control_buffer[128]; - -usbd_device *usbd_dev; - -static int cdcacm_control_request (usbd_device *usbd_dev, - struct usb_setup_data *req, - uint8_t **buf, - uint16_t *len, - usbd_control_complete_callback *complete) +int cdcacm_control_request (usbd_device *usbd_dev, + struct usb_setup_data *req, + uint8_t **buf, + uint16_t *len, + usbd_control_complete_callback *complete) { (void) complete; (void) buf; (void) usbd_dev; -#ifdef INCLUDE_DFU_INTERFACE - - if (dfu_control_request (usbd_dev, req, buf, len, complete)) { - return 1; - } -#endif switch (req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { @@ -194,24 +140,12 @@ static int cdcacm_control_request (usbd_device *usbd_dev, * even though it's optional in the CDC spec, and we don't * advertise it in the ACM functional descriptor. */ - char local_buf[10]; - struct usb_cdc_notification *notif = (void *) local_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; - local_buf[8] = req->wValue & 3; - local_buf[9] = 0; - // usbd_ep_write_packet(0x83, buf, 10); 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; - } return 1; } @@ -220,69 +154,67 @@ static int cdcacm_control_request (usbd_device *usbd_dev, } + void cdcacm_tick (void) { - unsigned ep = 0x82; + unsigned ep = DATA_OUT; uint8_t buf[16]; uint8_t *ptr = buf; size_t n = 0; - if (ring_empty (&cdcacm_tx_ring)) { + if (!cdcacm_ready) return; - } - if ( (*USB_EP_REG (ep & 0x7f) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID) { + if (ring_empty (&cdcacm_tx_ring)) + return; + + /* Return if endpoint is already enabled. */ + if ((*USB_EP_REG (ep & 0x7f) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID) return; - } while (!ring_read_byte (&cdcacm_tx_ring, ptr++)) { n++; + + if (n == sizeof (buf)) break; } - usbd_ep_write_packet (usbd_dev, ep, buf, n); + usbd_ep_write_packet (usb_device, ep, buf, n); +} + +int cdcacm_write (char *ptr, int len) +{ + int ret; + + ret = ring_write (&cdcacm_tx_ring, (uint8_t *) ptr, len); + return ret; } + static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep) { (void) ep; uint8_t buf[64]; - int len = usbd_ep_read_packet (usbd_dev, 0x01, buf, 64); + int len = usbd_ep_read_packet (usbd_dev, DATA_IN, buf, 64); - if (len) { + if (len) ring_write (&cdcacm_rx_ring, buf, len); - } } -static void cdcacm_set_config (usbd_device *usbd_dev, uint16_t wValue) +void cdcacm_set_config (usbd_device *usbd_dev, uint16_t wValue) { (void) wValue; - usbd_ep_setup (usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); - usbd_ep_setup (usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); - usbd_ep_setup (usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - usbd_register_control_callback (usbd_dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); + + usbd_ep_setup (usbd_dev, DATA_IN, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); + usbd_ep_setup (usbd_dev, DATA_OUT, USB_ENDPOINT_ATTR_BULK, 64, NULL); + usbd_ep_setup (usbd_dev, COMM_EP, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + cdcacm_ready = 1; } -void usb_init (void) +void cdcacm_rings_init (void) { ring_init (&cdcacm_rx_ring, cdcacm_rx_ring_buf, sizeof (cdcacm_rx_ring_buf)); ring_init (&cdcacm_tx_ring, cdcacm_tx_ring_buf, sizeof (cdcacm_tx_ring_buf)); - usbd_dev = usbd_init (&stm32f103_usb_driver, - &dev, - &config, - usb_strings, -#ifdef INCLUDE_DFU_INTERFACE - 4, -#else - 3, -#endif - usbd_control_buffer, - sizeof (usbd_control_buffer)); - usbd_register_set_config_callback (usbd_dev, cdcacm_set_config); } - diff --git a/app/dfu.c b/app/dfu.c index dcde674..b0715be 100644 --- a/app/dfu.c +++ b/app/dfu.c @@ -1,13 +1,9 @@ #include "project.h" -#ifdef INCLUDE_DFU_INTERFACE - -extern uint32_t dfu_flag; - const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof (struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -16,25 +12,37 @@ const struct usb_dfu_descriptor dfu_function = { const struct usb_interface_descriptor dfu_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 2, + .bInterfaceNumber = 1, .bAlternateSetting = 0, .bNumEndpoints = 0, .bInterfaceClass = 0xFE, .bInterfaceSubClass = 1, .bInterfaceProtocol = 1, .iInterface = 4, - .extra = &dfu_function, .extralen = sizeof (dfu_function), }; +const struct usb_iface_assoc_descriptor dfu_iface_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 1, + .bInterfaceCount = 1, + .bFunctionClass = 0xfe, + .bFunctionSubClass = 1, + .bFunctionProtocol = 1, + .iFunction = 5, +}; + + static int dfu_detach_complete (usbd_device *usbd_dev, struct usb_setup_data *req) { (void) req; (void) usbd_dev; dfu_flag = 0xfee1dead; + scb_reset_core(); return 1; } @@ -48,7 +56,7 @@ dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, (void) len; (void) usbd_dev; - if ( (req->bmRequestType & 0x7F) != 0x21) { + if ((req->bmRequestType & 0x7F) != 0x21) { return 0; /* Only accept class request. */ } @@ -63,11 +71,13 @@ dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, *len = 6; return 1; } + case DFU_GETSTATE: /* Return state with no state transision. */ *buf[0] = STATE_APP_IDLE; *len = 1; return 1; + case DFU_DETACH: *complete = dfu_detach_complete; return 1; @@ -75,4 +85,4 @@ dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, return 0; } -#endif + diff --git a/app/dummy_kb.c b/app/dummy_kb.c new file mode 100644 index 0000000..a1d61c7 --- /dev/null +++ b/app/dummy_kb.c @@ -0,0 +1,26 @@ +#include "project.h" + +const struct usb_interface_descriptor dummy_kb_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + + +const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 1, + .bFunctionClass = 0xff, + .bFunctionSubClass = 0, + .bFunctionProtocol = 0, + .iFunction = 4, +}; + diff --git a/app/gdb.script b/app/gdb.script new file mode 100644 index 0000000..7cf9d09 --- /dev/null +++ b/app/gdb.script @@ -0,0 +1,2 @@ +target remote localhost:3333 +cont diff --git a/app/i2c_bb.c b/app/i2c_bb.c index f392b5e..cfa6742 100644 --- a/app/i2c_bb.c +++ b/app/i2c_bb.c @@ -106,57 +106,54 @@ static void i2c_bb_sm (int od, int d, int oc, int c) } // Check for STOP - if (oc && c && !od && d) { + if (oc && c && !od && d) state = ST_LOST; - } switch (state) { case ST_LOST: i2c_bb_sda (1); i2c_bb_scl (1); break; + case ST_ADDRESS_7...ST_ADDRESS_0: - if (! (!oc && c)) { + if (! (!oc && c)) break; - } //rising scl of a7...a0 sr = (sr << 1) | !!d; if (state == ST_ADDRESS_0) { - if ( (sr & ~I2C_READ) == OUR_ADDRESS) { + if ((sr & ~I2C_READ) == OUR_ADDRESS) { state++; rnw = d; - } else { + } else state = ST_LOST; - } - } else { + } else state++; - } break; + case ST_ADDRESS_ACK: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of a0 i2c_bb_sda (0); - if (rnw) { + if (rnw) state++; - } else { + + else state = ST_PREP_REG_7; - } break; + case ST_OUT_7: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of ack i2c_bb_sda (1); @@ -168,32 +165,32 @@ static void i2c_bb_sm (int od, int d, int oc, int c) i2c_bb_scl (1); state++; break; + case ST_OUT_6...ST_OUT_0: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of d6...d0 i2c_bb_sda (sr & 0x80); sr <<= 1; state++; break; + case ST_PREP_OUT_ACK: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of d0 i2c_bb_sda (1); state++; break; + case ST_OUT_ACK: - if (! (!oc && c)) { + if (! (!oc && c)) break; - } //rising scl of ack @@ -207,74 +204,74 @@ static void i2c_bb_sm (int od, int d, int oc, int c) } break; + case ST_PREP_REG_7: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of ack i2c_bb_sda (1); sr = 0; state++; break; + case ST_REG_7...ST_REG_0: - if (! (!oc && c)) { + if (! (!oc && c)) break; - } //rising scl of r7..r0 sr = (sr << 1) | !!d; state++; break; + case ST_REG_ACK: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of r0 reg = sr; i2c_bb_sda (0); state = ST_PREP_IN_7; break; + case ST_PREP_IN_7: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of ack i2c_bb_sda (1); sr = 0; state++; break; + case ST_IN_7...ST_IN_0: - if (! (!oc && c)) { + if (! (!oc && c)) break; - } //rising scl of i7..i0 sr = (sr << 1) | !!d; state++; break; + case ST_IN_ACK: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of i0 i2c_bb_sda (0); state++; break; + case ST_REG_WRITE: - if (! (oc && !c)) { + if (! (oc && !c)) break; - } //falling scl of ack i2c_bb_sda (1); @@ -286,6 +283,7 @@ static void i2c_bb_sm (int od, int d, int oc, int c) sr = 0; state = ST_IN_7; break; + default: state = ST_LOST; } diff --git a/app/i2c_hw.c b/app/i2c_hw.c index 11e796e..9b77009 100644 --- a/app/i2c_hw.c +++ b/app/i2c_hw.c @@ -34,11 +34,11 @@ void i2c1_ev_isr (void) } if (sr1 & I2C_SR1_TxE) { - if (device) { + if (device) v = ddc_read (reg++); - } else { + + else v = vuart_read (reg++); - } I2C_DR (I2C) = v; } @@ -50,11 +50,11 @@ void i2c1_ev_isr (void) reg = v; next_is_reg = 0; } else { - if (reg == 0x10) { + if (reg == 0x10) vuart_write (0, v); - } else { + + else vuart_write (reg++, v); - } } } diff --git a/app/main.c b/app/main.c index b98bd82..2ac458f 100644 --- a/app/main.c +++ b/app/main.c @@ -15,39 +15,27 @@ int main (void) rcc_periph_clock_enable (RCC_USART1); rcc_periph_clock_enable (RCC_AFIO); rcc_periph_clock_enable (RCC_I2C1); -#if 0 - nvic_set_priority (NVIC_I2C1_EV_IRQ, 0x38); - nvic_set_priority (NVIC_I2C1_ER_IRQ, 0x39); - nvic_set_priority (NVIC_USART1_IRQ, 0x44); - nvic_set_priority (NVIC_SYSTICK_IRQ, 0xff); -#else nvic_set_priority (NVIC_I2C1_EV_IRQ, 0xff); nvic_set_priority (NVIC_I2C1_ER_IRQ, 0xff); nvic_set_priority (NVIC_SYSTICK_IRQ, 0x80); nvic_set_priority (NVIC_USART1_IRQ, 0x40); -#endif + nvic_set_priority (NVIC_USB_HP_CAN_TX_IRQ, 0x40); + nvic_set_priority (NVIC_USB_LP_CAN_RX0_IRQ, 0x40); + gpio_set_mode (LED1_BANK, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LED1_GPIO); gpio_set_mode (LED2_BANK, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LED2_GPIO); usart_init(); ticker_init(); - printf ("Morning chaps!\r\n"); -#ifdef USB + cdcacm_rings_init(); usb_init(); -#endif -#ifdef I2C_BIT_BANG - i2c_bb_init(); -#else + + printf ("Morning chaps!\r\n"); + i2c_hw_init(); -#endif - - for (;;) { -#ifdef USB - usbd_poll (usbd_dev); -#endif -#ifdef I2C_BIT_BANG - i2c_bb_poll(); -#endif - } + + printf ("Ready\n"); + + for (;;); return 0; } diff --git a/app/project.h b/app/project.h index 3df1a38..f4b113b 100644 --- a/app/project.h +++ b/app/project.h @@ -10,16 +10,11 @@ #include #include #include +#include +#include #include -#define INCLUDE_DFU_INTERFACE #undef I2C_BIT_BANG -#define USB - -#ifdef INCLUDE_DFU_INTERFACE -#include -#include -#endif #include #include @@ -33,3 +28,5 @@ #include "ring.h" #include "prototypes.h" + +extern uint32_t dfu_flag; diff --git a/app/prototypes.h b/app/prototypes.h index a877992..a432df4 100644 --- a/app/prototypes.h +++ b/app/prototypes.h @@ -3,13 +3,18 @@ extern int main(void); /* cdcacm.c */ extern ring_t cdcacm_rx_ring; extern ring_t cdcacm_tx_ring; -extern uint8_t usbd_control_buffer[128]; -extern usbd_device *usbd_dev; +extern const struct usb_interface_descriptor comm_iface; +extern const struct usb_interface_descriptor data_iface; +extern const struct usb_iface_assoc_descriptor cdc_iface_assoc; +extern int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete); extern void cdcacm_tick(void); -extern void usb_init(void); +extern int cdcacm_write(char *ptr, int len); +extern void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue); +extern void cdcacm_rings_init(void); /* dfu.c */ extern const struct usb_dfu_descriptor dfu_function; extern const struct usb_interface_descriptor dfu_iface; +extern const struct usb_iface_assoc_descriptor dfu_iface_assoc; extern int dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete); /* i2c_bb.c */ extern void i2c_bb_init(void); @@ -42,3 +47,12 @@ extern void sys_tick_handler(void); extern void ticker_init(void); /* ddc.c */ extern uint8_t ddc_read(uint8_t v); +/* dummy_kb.c */ +extern const struct usb_interface_descriptor dummy_kb_iface; +extern const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc; +/* usb.c */ +extern uint8_t usbd_control_buffer[128]; +extern usbd_device *usb_device; +extern void usb_hp_can_tx_isr(void); +extern void usb_lp_can_rx0_isr(void); +extern void usb_init(void); diff --git a/app/ring.c b/app/ring.c index e3a6209..26bba3a 100644 --- a/app/ring.c +++ b/app/ring.c @@ -6,9 +6,8 @@ ring_next (ring_t *r, size_t p) { p++; - if (p >= r->size) { + if (p >= r->size) p -= r->size; - } return p; } @@ -27,9 +26,8 @@ ring_write_byte (ring_t *r, uint8_t c) { size_t n = ring_next (r, r->write); - if (n == r->read) { + if (n == r->read) return -1; - } r->data[r->write] = c; r->write = n; @@ -46,9 +44,8 @@ ring_read_byte (ring_t *r, uint8_t *c) { size_t n = ring_next (r, r->read); - if (r->read == r->write) { + if (r->read == r->write) return -1; - } *c = r->data[r->read]; r->read = n; @@ -59,9 +56,8 @@ int ring_write (ring_t *r, uint8_t *buf, size_t len) { while (len--) { - if (ring_write_byte (r, * (buf++))) { + if (ring_write_byte (r, * (buf++))) return -1; - } } return 0; diff --git a/app/ticker.c b/app/ticker.c index 05990d2..a28824c 100644 --- a/app/ticker.c +++ b/app/ticker.c @@ -13,9 +13,8 @@ delay_us (uint32_t d) { d *= scale; - while (d--) { + while (d--) __asm__ ("nop"); - } } void @@ -24,25 +23,23 @@ sys_tick_handler (void) ticks++; cdcacm_tick(); - if (led1) { + if (led1) led1--; - } - if (led2) { + if (led2) led2--; - } - if (led1) { + if (led1) gpio_clear (LED1_BANK, LED1_GPIO); - } else { + + else gpio_set (LED1_BANK, LED1_GPIO); - } - if (led2) { + if (led2) gpio_clear (LED2_BANK, LED2_GPIO); - } else { + + else gpio_set (LED2_BANK, LED2_GPIO); - } } @@ -63,9 +60,8 @@ ticker_init (void) scale--; v = ticks; - while (v == ticks) { + while (v == ticks) ; - } delay_us (1000); w = ticks; diff --git a/app/usart.c b/app/usart.c index ecd8e56..8659ab0 100644 --- a/app/usart.c +++ b/app/usart.c @@ -14,30 +14,28 @@ usart1_isr (void) uint8_t data; /* Check if we were called because of RXNE. */ - if ( ( (USART_CR1 (USART1) & USART_CR1_RXNEIE) != 0) && - ( (USART_SR (USART1) & USART_SR_RXNE) != 0)) { + if (((USART_CR1 (USART1) & USART_CR1_RXNEIE) != 0) && + ((USART_SR (USART1) & USART_SR_RXNE) != 0)) { /* Retrieve the data from the peripheral. */ data = usart_recv (USART1); ring_write_byte (&usart_rx_ring, data); } /* Check if we were called because of TXE. */ - if ( ( (USART_CR1 (USART1) & USART_CR1_TXEIE) != 0) && - ( (USART_SR (USART1) & USART_SR_TXE) != 0)) { + if (((USART_CR1 (USART1) & USART_CR1_TXEIE) != 0) && + ((USART_SR (USART1) & USART_SR_TXE) != 0)) { if (ring_read_byte (&usart_tx_ring, &data)) { /*No more data, Disable the TXE interrupt, it's no longer needed. */ USART_CR1 (USART1) &= ~USART_CR1_TXEIE; - } else { + } else usart_send (USART1, data); - } } } void usart_kick (void) { - if (!ring_empty (&usart_tx_ring)) { + if (!ring_empty (&usart_tx_ring)) USART_CR1 (USART1) |= USART_CR1_TXEIE; - } } @@ -49,10 +47,10 @@ _write (int file, char *ptr, int len) if (file == 1) { ret = ring_write (&usart_tx_ring, (uint8_t *) ptr, len); usart_kick(); + ring_write (&cdcacm_tx_ring, (uint8_t *) ptr, len); - if (ret < 0) { + if (ret < 0) ret = -ret; - } return ret; } diff --git a/app/usb.c b/app/usb.c new file mode 100644 index 0000000..8023ea3 --- /dev/null +++ b/app/usb.c @@ -0,0 +1,139 @@ +#include "project.h" + +#define USB_DM GPIO11 +#define USB_DM_PORT GPIOA +#define USB_DP GPIO12 +#define USB_DP_PORT GPIOA + +/* Buffer to be used for control requests. */ +uint8_t usbd_control_buffer[128]; +usbd_device *usb_device; + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xef, + .bDeviceSubClass = 0x02, + .bDeviceProtocol = 0x01, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0xff03, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + + +static const struct usb_interface ifaces[] = { + { + .num_altsetting = 1, + .altsetting = &dummy_kb_iface, + .iface_assoc = &dummy_kb_iface_assoc, + }, + { + .num_altsetting = 1, + .altsetting = &dfu_iface, + .iface_assoc = &dfu_iface_assoc, + }, + { + .num_altsetting = 1, + .altsetting = &comm_iface, + .iface_assoc = &cdc_iface_assoc, + }, + { + .num_altsetting = 1, + .altsetting = &data_iface, + }, +}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 4, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + .interface = ifaces, +}; + +static const char *usb_strings[] = { + VENDOR_NAME, /*1*/ + PRODUCT_NAME, /*2*/ + SERIAL_NUMBER, /*3*/ + "dummy device", /*4*/ + "DFU interface", /*5*/ + "Debug interface", /*6*/ +}; +#define N_USB_STRINGS (sizeof(usb_strings)/sizeof(usb_strings[0])) + +void usb_hp_can_tx_isr (void) +{ + usbd_poll (usb_device); +} + +void usb_lp_can_rx0_isr (void) +{ + usbd_poll (usb_device); +} + +static int control_request (usbd_device *usbd_dev, + struct usb_setup_data *req, + uint8_t **buf, + uint16_t *len, + usbd_control_complete_callback *complete) +{ + if (dfu_control_request (usbd_dev, req, buf, len, complete)) + return 1; + + return cdcacm_control_request (usbd_dev, req, buf, len, complete); +} + +static void set_config (usbd_device *usbd_dev, uint16_t wValue) +{ + + cdcacm_set_config (usbd_dev, wValue); + + usbd_register_control_callback (usbd_dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + control_request); + +} + + + +void usb_init (void) +{ + /*Force USB reset */ + gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_clear (GPIOA, GPIO12); + gpio_clear (GPIOA, GPIO13); + delay_us (50000); + gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO12); + gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO13); + + + usb_device = usbd_init (&stm32f103_usb_driver, + &dev, + &config, + usb_strings, + N_USB_STRINGS, + usbd_control_buffer, + sizeof (usbd_control_buffer)); + + usbd_register_set_config_callback (usb_device, set_config); + + nvic_enable_irq (NVIC_USB_HP_CAN_TX_IRQ); + nvic_enable_irq (NVIC_USB_LP_CAN_RX0_IRQ); + + + +} + + diff --git a/app/vuart.c b/app/vuart.c index 5aaf2d3..3c4ab79 100644 --- a/app/vuart.c +++ b/app/vuart.c @@ -82,25 +82,18 @@ static void vuart_xmit (uint8_t c) led1 = 100; ring_write_byte (&usart_tx_ring, c); usart_kick(); -#ifdef USB ring_write_byte (&cdcacm_tx_ring, c); -#endif } static int vuart_recv_empty (void) { - if (!ring_empty (&usart_rx_ring)) { + if (!ring_empty (&usart_rx_ring)) return 0; - } - -#ifdef USB - if (!ring_empty (&cdcacm_rx_ring)) { + if (!ring_empty (&cdcacm_rx_ring)) return 0; - } -#endif return 1; } @@ -114,25 +107,22 @@ static int vuart_recv (uint8_t *c) return 0; } -#ifdef USB - if (!ring_read_byte (&cdcacm_rx_ring, c)) { led2 = 100; return 0; } -#endif return -1; } static void update_lsr (void) { - if (vuart_recv_empty()) { + if (vuart_recv_empty()) lsr &= ~LSR_DA; - } else { + + else lsr |= LSR_DA; - } } uint8_t vuart_read (unsigned reg) @@ -147,28 +137,33 @@ uint8_t vuart_read (unsigned reg) vuart_recv (&val); update_lsr(); return val; - } else { + } else return dllr; - } case IER: //case DLLH: return (lcr & LCR_DLAB) ? dlhr : ier; + case IIR: return iir; + case LCR: return lcr; + case MCR: return mcr; + case LSR: update_lsr(); val = lsr; lsr &= 0xe1; return val; + case MSR: val = msr; msr &= 0xf0; return val; + case SR: return sr; } @@ -183,29 +178,33 @@ void vuart_write (unsigned reg, uint8_t val) case RXR: //case DLLR: - if (! (lcr & LCR_DLAB)) { + if (! (lcr & LCR_DLAB)) vuart_xmit (val); - } else { + + else dllr = val; - } break; + case IER: //case DLHR: - if (! (lcr & LCR_DLAB)) { + if (! (lcr & LCR_DLAB)) ier = val & 0xf; - } else { + + else dlhr = val; - } break; + case LCR: lcr = val; break; + case MCR: mcr = val & 0x1f; break; + case SR: sr = val; break; diff --git a/boot/Makefile b/boot/Makefile index 86d4d2c..4891184 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -30,3 +30,19 @@ include ../Makefile.include CFLAGS += -I.. +ds: + $(Q)$(OOCD) -f $(OOCD_INTERFACE) \ + -f $(OOCD_BOARD) \ + +debug: ${PROG}.elf + ${PREFIX}-gdb -x gdb.script ${PROG}.elf + +reset: + $(Q)$(OOCD) -f $(OOCD_INTERFACE) \ + -f $(OOCD_BOARD) \ + -c "init" -c "reset run" \ + -c shutdown + +tidy: + astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS} || astyle -A3 -s2 -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS} + diff --git a/boot/gdb.script b/boot/gdb.script new file mode 100644 index 0000000..7cf9d09 --- /dev/null +++ b/boot/gdb.script @@ -0,0 +1,2 @@ +target remote localhost:3333 +cont diff --git a/boot/usbdfu.c b/boot/usbdfu.c index d538234..9287f57 100644 --- a/boot/usbdfu.c +++ b/boot/usbdfu.c @@ -27,13 +27,13 @@ #include -#define APP_ADDRESS 0x08002000 +#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 -void usb_set_config (usbd_device * usbd_dev, uint16_t wValue); +void usb_set_config (usbd_device *usbd_dev, uint16_t wValue); /* We need a special large control buffer for this device: */ uint8_t usbd_control_buffer[1024]; @@ -43,248 +43,294 @@ static enum dfu_state usbdfu_state = STATE_DFU_IDLE; extern uint32_t dfu_flag; static struct { - uint8_t buf[sizeof(usbd_control_buffer)]; - uint16_t len; - uint32_t addr; - uint16_t blocknum; + uint8_t buf[sizeof (usbd_control_buffer)]; + uint16_t len; + uint32_t addr; + uint16_t blocknum; } prog; const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = 64, - .idVendor = ID_VENDOR, - .idProduct = ID_PRODUCT, - .bcdDevice = 0x0200, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0xdf11, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, }; const struct usb_dfu_descriptor dfu_function = { - .bLength = sizeof(struct usb_dfu_descriptor), - .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD, - .wDetachTimeout = 255, - .wTransferSize = 1024, - .bcdDFUVersion = 0x011A, + .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 iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, /* Device Firmware Upgrade */ - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 2, - - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ - .iInterface = 4, - - .extra = &dfu_function, - .extralen = sizeof(dfu_function), + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, /* Device Firmware Upgrade */ + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 2, + + /* The ST Microelectronics DfuSe application needs this string. + * The format isn't documented... */ + .iInterface = 4, + + .extra = &dfu_function, + .extralen = sizeof (dfu_function), }; const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .altsetting = &iface, -}}; + .num_altsetting = 1, + .altsetting = &iface, + } +}; const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, - .bNumInterfaces = 1, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0xC0, - .bMaxPower = 0x32, - - .interface = ifaces, + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 0x32, + + .interface = ifaces, }; static const char *usb_strings[] = { - "Cabbages are good for you", - "fish", - "soup", - /* This string is used by ST Microelectronics' DfuSe utility. */ - "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + VENDOR_NAME, + PRODUCT_NAME " (dfu mode)", + SERIAL_NUMBER, + /* This string is used by ST Microelectronics' DfuSe utility. */ + "@Internal Flash /0x08000000/8*001Ka,56*001Kg", }; +#define N_USB_STRINGS (sizeof(usb_strings)/sizeof(usb_strings[0])) -static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout) +static void +delay_us (uint32_t d) { - (void)usbd_dev; - - switch (usbdfu_state) { - case STATE_DFU_DNLOAD_SYNC: - usbdfu_state = STATE_DFU_DNBUSY; - *bwPollTimeout = 100; - return DFU_STATUS_OK; - case STATE_DFU_MANIFEST_SYNC: - /* Device will reset when read is complete. */ - usbdfu_state = STATE_DFU_MANIFEST; - return DFU_STATUS_OK; - default: - return DFU_STATUS_OK; - } + d *= 7; + + while (d--) + __asm__ ("nop"); } -static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req) + +static uint8_t usbdfu_getstatus (usbd_device *usbd_dev, uint32_t *bwPollTimeout) { - int i; - (void)req; - (void)usbd_dev; - - switch (usbdfu_state) { - case STATE_DFU_DNBUSY: - flash_unlock(); - if (prog.blocknum == 0) { - switch (prog.buf[0]) { - case CMD_ERASE: - { - uint32_t *dat = (uint32_t *)(prog.buf + 1); - flash_erase_page(*dat); - } - case CMD_SETADDR: - { - uint32_t *dat = (uint32_t *)(prog.buf + 1); - prog.addr = *dat; - } - } - } else { - uint32_t baseaddr = prog.addr + ((prog.blocknum - 2) * - dfu_function.wTransferSize); - for (i = 0; i < prog.len; i += 2) { - uint16_t *dat = (uint16_t *)(prog.buf + i); - flash_program_half_word(baseaddr + i, - *dat); - } - } - flash_lock(); - - /* Jump straight to dfuDNLOAD-IDLE, skipping dfuDNLOAD-SYNC. */ - usbdfu_state = STATE_DFU_DNLOAD_IDLE; - return; - case STATE_DFU_MANIFEST: - /* USB device must detach, we just reset... */ - scb_reset_system(); - return; /* Will never return. */ - default: - return; - } + (void)usbd_dev; + + switch (usbdfu_state) { + case STATE_DFU_DNLOAD_SYNC: + usbdfu_state = STATE_DFU_DNBUSY; + *bwPollTimeout = 100; + return DFU_STATUS_OK; + + case STATE_DFU_MANIFEST_SYNC: + /* Device will reset when read is complete. */ + usbdfu_state = STATE_DFU_MANIFEST; + return DFU_STATUS_OK; + + default: + return DFU_STATUS_OK; + } } -static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, - uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)) +static int usbdfu_getstatus_complete (usbd_device *usbd_dev, struct usb_setup_data *req) { + int i; + (void)req; + (void)usbd_dev; + + switch (usbdfu_state) { + case STATE_DFU_DNBUSY: + flash_unlock(); + + if (prog.blocknum == 0) { + switch (prog.buf[0]) { + case CMD_ERASE: { + uint32_t *dat = (uint32_t *) (prog.buf + 1); + flash_erase_page (*dat); + } + break; + + case CMD_SETADDR: { + uint32_t *dat = (uint32_t *) (prog.buf + 1); + prog.addr = *dat; + } + } + } else { + uint32_t baseaddr = prog.addr + ((prog.blocknum - 2) * + dfu_function.wTransferSize); + + for (i = 0; i < prog.len; i += 2) { + uint16_t *dat = (uint16_t *) (prog.buf + i); + flash_program_half_word (baseaddr + i, + *dat); + } + } + + flash_lock(); + + /* Jump straight to dfuDNLOAD-IDLE, skipping dfuDNLOAD-SYNC. */ + usbdfu_state = STATE_DFU_DNLOAD_IDLE; + return 0; + + case STATE_DFU_MANIFEST: + /* USB device must detach, we just reset... */ + scb_reset_system(); + return 0; /* Will never return. */ + + default: + ; + } + + return 0; +} - if ((req->bmRequestType & 0x7F) != 0x21) - return 0; /* Only accept class request. */ - - switch (req->bRequest) { - case DFU_DNLOAD: - if ((len == NULL) || (*len == 0)) { - usbdfu_state = STATE_DFU_MANIFEST_SYNC; - return 1; - } else { - /* Copy download data for use on GET_STATUS. */ - prog.blocknum = req->wValue; - prog.len = *len; - memcpy(prog.buf, *buf, *len); - usbdfu_state = STATE_DFU_DNLOAD_SYNC; - return 1; - } - case DFU_CLRSTATUS: - /* Clear error and return to dfuIDLE. */ - if (usbdfu_state == STATE_DFU_ERROR) - usbdfu_state = STATE_DFU_IDLE; - return 1; - case DFU_ABORT: - /* Abort returns to dfuIDLE state. */ - usbdfu_state = STATE_DFU_IDLE; - return 1; - case DFU_UPLOAD: - /* Upload not supported for now. */ - return 0; - case DFU_GETSTATUS: { - uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ - (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout); - (*buf)[1] = bwPollTimeout & 0xFF; - (*buf)[2] = (bwPollTimeout >> 8) & 0xFF; - (*buf)[3] = (bwPollTimeout >> 16) & 0xFF; - (*buf)[4] = usbdfu_state; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - *complete = usbdfu_getstatus_complete; - return 1; - } - case DFU_GETSTATE: - /* Return state with no state transision. */ - *buf[0] = usbdfu_state; - *len = 1; - return 1; - } - - return 0; +static int usbdfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, + uint16_t *len, usbd_control_complete_callback *complete) +{ + + if ((req->bmRequestType & 0x7F) != 0x21) + return 0; /* Only accept class request. */ + + switch (req->bRequest) { + case DFU_DNLOAD: + if ((len == NULL) || (*len == 0)) { + usbdfu_state = STATE_DFU_MANIFEST_SYNC; + return 1; + } else { + /* Copy download data for use on GET_STATUS. */ + prog.blocknum = req->wValue; + prog.len = *len; + memcpy (prog.buf, *buf, *len); + usbdfu_state = STATE_DFU_DNLOAD_SYNC; + return 1; + } + + case DFU_CLRSTATUS: + + /* Clear error and return to dfuIDLE. */ + if (usbdfu_state == STATE_DFU_ERROR) + usbdfu_state = STATE_DFU_IDLE; + + return 1; + + case DFU_ABORT: + /* Abort returns to dfuIDLE state. */ + usbdfu_state = STATE_DFU_IDLE; + return 1; + + case DFU_UPLOAD: + /* Upload not supported for now. */ + return 0; + + case DFU_GETSTATUS: { + uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ + (*buf)[0] = usbdfu_getstatus (usbd_dev, &bwPollTimeout); + (*buf)[1] = bwPollTimeout & 0xFF; + (*buf)[2] = (bwPollTimeout >> 8) & 0xFF; + (*buf)[3] = (bwPollTimeout >> 16) & 0xFF; + (*buf)[4] = usbdfu_state; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + *complete = usbdfu_getstatus_complete; + return 1; + } + + case DFU_GETSTATE: + /* Return state with no state transision. */ + *buf[0] = usbdfu_state; + *len = 1; + return 1; + } + + return 0; } +static void usb_reset (void) +{ + /*Force USB reset */ + gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_clear (GPIOA, GPIO12); + gpio_clear (GPIOA, GPIO13); + + delay_us (5000); + gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO12); + gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO13); +} + + void -usb_set_config (usbd_device * usbd_dev, uint16_t wValue) +usb_set_config (usbd_device *usbd_dev, uint16_t wValue) { (void) wValue; (void) usbd_dev; - - usbd_register_control_callback( - usbd_dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - usbdfu_control_request); + + usbd_register_control_callback ( + usbd_dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + usbdfu_control_request); } -int main(void) +int main (void) { - usbd_device *usbd_dev; + usbd_device *usbd_dev; + + rcc_periph_clock_enable (RCC_GPIOA); + rcc_periph_reset_pulse (RST_USB); + + if (dfu_flag != 0xfee1dead) { + /* Boot the application if it's valid. */ + if ((* (volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { + /* Set vector table base address. */ + SCB_VTOR = APP_ADDRESS & 0xFFFF; + /* Initialise master stack pointer. */ + asm volatile ("msr msp, %0"::"g" + (* (volatile uint32_t *)APP_ADDRESS)); + /* Jump to application. */ + (* (void (* *)()) (APP_ADDRESS + 4))(); + } + } - rcc_periph_clock_enable(RCC_GPIOA); + usb_reset(); - if (dfu_flag!=0xfee1dead) { - /* Boot the application if it's valid. */ - if ((*(volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { - /* Set vector table base address. */ - SCB_VTOR = APP_ADDRESS & 0xFFFF; - /* Initialise master stack pointer. */ - asm volatile("msr msp, %0"::"g" - (*(volatile uint32_t *)APP_ADDRESS)); - /* Jump to application. */ - (*(void (**)())(APP_ADDRESS + 4))(); - } - } + dfu_flag = 0; - dfu_flag=0; + rcc_clock_setup_in_hsi_out_48mhz(); - rcc_clock_setup_in_hsi_out_48mhz(); + rcc_periph_clock_enable (RCC_GPIOC); - rcc_periph_clock_enable(RCC_GPIOC); + gpio_set_mode (GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); + gpio_set (GPIOC, GPIO11); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); - gpio_set(GPIOC, GPIO11); - usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings, 4, usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_dev = usbd_init (&stm32f103_usb_driver, &dev, &config, usb_strings, N_USB_STRINGS, usbd_control_buffer, sizeof (usbd_control_buffer)); - usbd_register_set_config_callback (usbd_dev, usb_set_config); + usbd_register_set_config_callback (usbd_dev, usb_set_config); - gpio_clear(GPIOC, GPIO11); + gpio_clear (GPIOC, GPIO11); - while (1) - usbd_poll(usbd_dev); + while (1) + usbd_poll (usbd_dev); } diff --git a/id.h b/id.h index c65f067..d27ecf7 100644 --- a/id.h +++ b/id.h @@ -1,3 +1,4 @@ -#define ID_VENDOR 0x1234 -#define ID_PRODUCT 0x5678 +#define VENDOR_NAME "HP" +#define PRODUCT_NAME "DDC Debug Dongle" +#define SERIAL_NUMBER "Serialy McSerialFace" diff --git a/tools/dfuse-pack.py b/tools/dfuse-pack.py new file mode 100755 index 0000000..c0a5f0a --- /dev/null +++ b/tools/dfuse-pack.py @@ -0,0 +1,256 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +import binascii +from optparse import OptionParser + +try: + from intelhex import IntelHex +except ImportError: + IntelHex = None + +DEFAULT_DEVICE="0x0483:0xdf11" +DEFAULT_NAME=b'ST...' + +# Prefix and Suffix sizes are derived from ST's DfuSe File Format Specification (UM0391), DFU revision 1.1a +PREFIX_SIZE=11 +SUFFIX_SIZE=16 + +def named(tuple,names): + return dict(list(zip(names.split(),tuple))) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(bytestring): + return bytestring.partition(b'\0')[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print('File: "%s"' % file) + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix) + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix) + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print(' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix) + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print(' DUMPED IMAGE TO "%s"' % out) + if len(target): + print("target %d: PARSE ERROR" % t) + suffix = named(struct.unpack('<4H3sBI',data[:SUFFIX_SIZE]),'device product vendor dfu ufd len crc') + print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) + if crc != suffix['crc']: + print("CRC ERROR: computed crc32 is 0x%08x" % crc) + data = data[SUFFIX_SIZE:] + if data: + print("PARSE ERROR") + +def checkbin(binfile): + data = open(binfile,'rb').read() + if (len(data) < SUFFIX_SIZE): + return + crc = compute_crc(data[:-4]) + suffix = named(struct.unpack('<4H3sBI',data[-SUFFIX_SIZE:]),'device product vendor dfu ufd len crc') + if crc == suffix['crc'] and suffix['ufd'] == b'UFD': + print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) + print("It looks like the file %s has a DFU suffix!" % binfile) + print("Please remove any DFU suffix and retry.") + sys.exit(1) + +def build(file,targets,name=DEFAULT_NAME,device=DEFAULT_DEVICE): + data = b'' + for t,target in enumerate(targets): + tdata = b'' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + ealt = image['alt'] + tdata = struct.pack('<6sBI255s2I',b'Target',ealt,1,name,len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB',b'DfuSe',1,PREFIX_SIZE + len(data) + SUFFIX_SIZE,len(targets)) + data + v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)] + data += struct.pack('<4H3sB',0,d,v,0x011a,b'UFD',SUFFIX_SIZE) + crc = compute_crc(data) + data += struct.pack('