26 #include <libopencmsis/core_cm3.h> 27 #include <libopencm3/cm3/scb.h> 28 #include <libopencm3/cm3/nvic.h> 29 #include <libopencm3/stm32/rcc.h> 30 #include <libopencm3/stm32/gpio.h> 31 #include <libopencm3/usb/usbd.h> 32 #include <libopencm3/usb/cdc.h> 33 #include <libopencm3/usb/dfu.h> 40 #define USB_DATA_TRANSFER_SIZE 64 // 64 is the maximum for full speed devices 50 static volatile uint16_t
tx_i = 0;
58 .bLength = USB_DT_DEVICE_SIZE,
59 .bDescriptorType = USB_DT_DEVICE,
61 .bDeviceClass = USB_CLASS_CDC,
64 .bMaxPacketSize0 = 64,
71 .bNumConfigurations = 1,
78 .bLength = USB_DT_ENDPOINT_SIZE,
79 .bDescriptorType = USB_DT_ENDPOINT,
80 .bEndpointAddress = 0x02,
81 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
85 .bLength = USB_DT_ENDPOINT_SIZE,
86 .bDescriptorType = USB_DT_ENDPOINT,
87 .bEndpointAddress = 0x82,
88 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
97 .bLength = USB_DT_ENDPOINT_SIZE,
98 .bDescriptorType = USB_DT_ENDPOINT,
99 .bEndpointAddress = 0x81,
100 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
101 .wMaxPacketSize = 16,
109 static const struct {
112 struct usb_cdc_acm_descriptor
acm;
116 .bFunctionLength =
sizeof(
struct usb_cdc_header_descriptor),
117 .bDescriptorType = CS_INTERFACE,
118 .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
122 .bFunctionLength =
sizeof(
struct usb_cdc_call_management_descriptor),
123 .bDescriptorType = CS_INTERFACE,
124 .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
129 .bFunctionLength =
sizeof(
struct usb_cdc_acm_descriptor),
130 .bDescriptorType = CS_INTERFACE,
131 .bDescriptorSubtype = USB_CDC_TYPE_ACM,
135 .bFunctionLength =
sizeof(
struct usb_cdc_union_descriptor),
136 .bDescriptorType = CS_INTERFACE,
137 .bDescriptorSubtype = USB_CDC_TYPE_UNION,
138 .bControlInterface = 0,
139 .bSubordinateInterface0 = 1,
147 .bLength = USB_DT_INTERFACE_SIZE,
148 .bDescriptorType = USB_DT_INTERFACE,
149 .bInterfaceNumber = 0,
150 .bAlternateSetting = 0,
152 .bInterfaceClass = USB_CLASS_CDC,
153 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
154 .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,
159 .extra = &usb_cdcacm_functional_descriptors,
160 .extralen =
sizeof(usb_cdcacm_functional_descriptors),
167 .bLength = USB_DT_INTERFACE_SIZE,
168 .bDescriptorType = USB_DT_INTERFACE,
169 .bInterfaceNumber = 1,
170 .bAlternateSetting = 0,
172 .bInterfaceClass = USB_CLASS_DATA,
173 .bInterfaceSubClass = 0,
174 .bInterfaceProtocol = 0,
184 .bLength =
sizeof(
struct usb_dfu_descriptor),
185 .bDescriptorType = DFU_FUNCTIONAL,
186 .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
187 .wDetachTimeout = 200,
189 .bcdDFUVersion = 0x0110,
196 .bLength = USB_DT_INTERFACE_SIZE,
197 .bDescriptorType = USB_DT_INTERFACE,
198 .bInterfaceNumber = 2,
199 .bAlternateSetting = 0,
201 .bInterfaceClass = 0xFE,
202 .bInterfaceSubClass = 1,
203 .bInterfaceProtocol = 1,
224 .bLength = USB_DT_CONFIGURATION_SIZE,
225 .bDescriptorType = USB_DT_CONFIGURATION,
228 .bConfigurationValue = 1,
230 .bmAttributes = 0x80,
241 "BusVoodoo multi-protocol debugging adapter",
242 #if BUSVOODOO_HARDWARE_VERSION==0 245 (
char[]){
'A'+BUSVOODOO_HARDWARE_VERSION-1, 0},
247 "DFU bootloader (runtime mode)",
253 #if defined(MAPLE_MINI) 255 rcc_periph_clock_enable(RCC_GPIOB);
256 gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO9);
257 gpio_set(GPIOB, GPIO9);
258 for (uint32_t i = 0; i < 0x2000; i++) {
263 rcc_periph_clock_enable(RCC_GPIOA);
264 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
265 gpio_clear(GPIOA, GPIO12);
266 for (uint32_t i = 0; i < 0x2000; i++) {
280 RCC_CSR |= RCC_CSR_RMVF;
295 static enum usbd_request_return_codes
usb_cdcacm_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))
298 switch (req->bRequest) {
303 (*buf)[0] = DFU_STATUS_OK;;
307 (*buf)[4] = STATE_APP_IDLE;
312 return USBD_REQ_NOTSUPP;
315 switch (req->bRequest) {
316 case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
324 uint8_t reply[10] = {0};
325 struct usb_cdc_notification *notif = (
void *)reply;
327 notif->bmRequestType = 0xA1;
328 notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
332 reply[8] = req->wValue & 3;
336 case USB_CDC_REQ_SET_LINE_CODING:
338 if (*len <
sizeof(
struct usb_cdc_line_coding)) {
339 return USBD_REQ_NOTSUPP;
346 return USBD_REQ_NOTSUPP;
349 return USBD_REQ_HANDLED;
362 uint16_t usb_length = 0;
367 for (uint16_t i=0; i<usb_length && i<
LENGTH(usb_data); i++) {
381 static bool usb_tx_ongoing =
false;
383 if (!usbd_dev && usb_tx_ongoing) {
387 usb_tx_ongoing =
false;
392 usb_tx_ongoing =
true;
433 usbd_register_control_callback(usbd_dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usb_cdcacm_control_request);
439 rcc_periph_reset_pulse(RST_USB);
441 rcc_periph_clock_enable(RCC_GPIOA);
442 rcc_periph_clock_enable(RCC_USB);
445 nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
#define USB_DATA_TRANSFER_SIZE
maximum packet size for USB data transfer
static void usb_cdcacm_communication_cb(usbd_device *usbd_dev, uint8_t ep)
USB CDC ACM communication callback.
struct usb_cdc_header_descriptor header
header
static volatile uint16_t tx_used
how much data needs to be transmitted
struct usb_cdc_union_descriptor cdc_union
descriptor
static const struct usb_interface_descriptor usb_dfu_interface
USB DFU interface descriptor.
static const struct usb_interface_descriptor usb_cdcacm_communication_interface
USB CDC interface descriptor.
static const struct usb_config_descriptor usb_cdcacm_configuration_descriptor
USB CDC ACM configuration descriptor.
void user_input_store(char c)
store user input
volatile bool usb_cdcacm_connecting
flag set to true when user is connected to USB CDC ACM port (e.g.
void usb_cdcacm_putchar(char c)
send character over USB (non-blocking)
static const struct usb_endpoint_descriptor usb_cdcacm_communication_endpoints[]
USB CDC ACM communication endpoints.
static const struct @1 __attribute__((packed))
USB CDC ACM functional descriptor.
static volatile bool first_connection
used to detect when the first connection occurred
global definitions and methods (API)
static void usb_dfu_detach(usbd_device *usbd_dev, struct usb_setup_data *req)
DFU detach (disconnect USB and perform core reset)
static const struct usb_interface_descriptor usb_cdcacm_data_interface
USB CDC ACM data class interface descriptor.
static uint8_t usbd_control_buffer[128]
buffer to be used for control requests
void usb_cdcacm_setup(void)
setup USB CDC ACM peripheral
static enum usbd_request_return_codes usb_cdcacm_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))
incoming USB CDC ACM control request
static const struct usb_dfu_descriptor usb_dfu_functional
USB DFU functional descriptor.
struct usb_cdc_acm_descriptor acm
descriptor
static volatile bool tx_lock
if the transmit buffer is currently being written
static const char * usb_strings[]
USB string table.
static const struct usb_device_descriptor usb_cdcacm_device_descriptor
USB CDC ACM device descriptor.
static void usb_disconnect(void)
disconnect USB by pulling down D+ to for re-enumerate
static volatile uint16_t tx_i
current position if transmitted data
void usb_lp_can_rx0_isr(void)
USB interrupt service routine called when data is received.
struct usb_cdc_call_management_descriptor call_mgmt
call management descriptor
static uint8_t tx_buffer[256]
ring buffer for data to transmit
library for USB CDC ACM communication (API)
#define LENGTH(x)
get the length of an array
static const struct usb_endpoint_descriptor usb_cdcacm_data_endpoints[]
USB CDC ACM data endpoints.
static usbd_device * usb_device
structure holding all the info related to the USB device
static const struct usb_interface usb_cdcacm_interfaces[]
USB CDC ACM interface descriptor.
static void usb_cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
USB CDC ACM data received callback.
static void usb_cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep)
USB CDC ACM data transmitted callback.
static void usb_cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
set USB CDC ACM configuration