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> 42 #define USB_DATA_TRANSFER_SIZE 64 // 64 is the maximum for full speed devices 52 static volatile uint16_t
tx_i = 0;
60 .bLength = USB_DT_DEVICE_SIZE,
61 .bDescriptorType = USB_DT_DEVICE,
63 .bDeviceClass = USB_CLASS_CDC,
66 .bMaxPacketSize0 = 64,
73 .bNumConfigurations = 1,
80 .bLength = USB_DT_ENDPOINT_SIZE,
81 .bDescriptorType = USB_DT_ENDPOINT,
82 .bEndpointAddress = 0x02,
83 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
87 .bLength = USB_DT_ENDPOINT_SIZE,
88 .bDescriptorType = USB_DT_ENDPOINT,
89 .bEndpointAddress = 0x82,
90 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
99 .bLength = USB_DT_ENDPOINT_SIZE,
100 .bDescriptorType = USB_DT_ENDPOINT,
101 .bEndpointAddress = 0x81,
102 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
103 .wMaxPacketSize = 16,
111 static const struct {
114 struct usb_cdc_acm_descriptor
acm;
118 .bFunctionLength =
sizeof(
struct usb_cdc_header_descriptor),
119 .bDescriptorType = CS_INTERFACE,
120 .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
124 .bFunctionLength =
sizeof(
struct usb_cdc_call_management_descriptor),
125 .bDescriptorType = CS_INTERFACE,
126 .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
131 .bFunctionLength =
sizeof(
struct usb_cdc_acm_descriptor),
132 .bDescriptorType = CS_INTERFACE,
133 .bDescriptorSubtype = USB_CDC_TYPE_ACM,
137 .bFunctionLength =
sizeof(
struct usb_cdc_union_descriptor),
138 .bDescriptorType = CS_INTERFACE,
139 .bDescriptorSubtype = USB_CDC_TYPE_UNION,
140 .bControlInterface = 0,
141 .bSubordinateInterface0 = 1,
149 .bLength = USB_DT_INTERFACE_SIZE,
150 .bDescriptorType = USB_DT_INTERFACE,
151 .bInterfaceNumber = 0,
152 .bAlternateSetting = 0,
154 .bInterfaceClass = USB_CLASS_CDC,
155 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
156 .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,
161 .extra = &usb_cdcacm_functional_descriptors,
162 .extralen =
sizeof(usb_cdcacm_functional_descriptors),
169 .bLength = USB_DT_INTERFACE_SIZE,
170 .bDescriptorType = USB_DT_INTERFACE,
171 .bInterfaceNumber = 1,
172 .bAlternateSetting = 0,
174 .bInterfaceClass = USB_CLASS_DATA,
175 .bInterfaceSubClass = 0,
176 .bInterfaceProtocol = 0,
186 .bLength =
sizeof(
struct usb_dfu_descriptor),
187 .bDescriptorType = DFU_FUNCTIONAL,
188 .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
189 .wDetachTimeout = 200,
191 .bcdDFUVersion = 0x0110,
198 .bLength = USB_DT_INTERFACE_SIZE,
199 .bDescriptorType = USB_DT_INTERFACE,
200 .bInterfaceNumber = 2,
201 .bAlternateSetting = 0,
203 .bInterfaceClass = 0xFE,
204 .bInterfaceSubClass = 1,
205 .bInterfaceProtocol = 1,
226 .bLength = USB_DT_CONFIGURATION_SIZE,
227 .bDescriptorType = USB_DT_CONFIGURATION,
230 .bConfigurationValue = 1,
232 .bmAttributes = 0x80,
243 "BusVoodoo multi-protocol debugging adapter",
244 #if BUSVOODOO_HARDWARE_VERSION==0 247 (
char[]){
'A'+BUSVOODOO_HARDWARE_VERSION-1, 0},
249 "DFU bootloader (runtime mode)",
255 #if defined(MAPLE_MINI) 257 rcc_periph_clock_enable(RCC_GPIOB);
258 gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO9);
259 gpio_set(GPIOB, GPIO9);
260 for (uint32_t i = 0; i < 0x2000; i++) {
265 rcc_periph_clock_enable(RCC_GPIOA);
266 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
267 gpio_clear(GPIOA, GPIO12);
268 for (uint32_t i = 0; i < 0x2000; i++) {
282 RCC_CSR |= RCC_CSR_RMVF;
297 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))
300 switch (req->bRequest) {
305 (*buf)[0] = DFU_STATUS_OK;;
309 (*buf)[4] = STATE_APP_IDLE;
314 return USBD_REQ_NOTSUPP;
317 switch (req->bRequest) {
318 case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
326 uint8_t reply[10] = {0};
327 struct usb_cdc_notification *notif = (
void *)reply;
329 notif->bmRequestType = 0xA1;
330 notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
334 reply[8] = req->wValue & 3;
338 case USB_CDC_REQ_SET_LINE_CODING:
340 if (*len <
sizeof(
struct usb_cdc_line_coding)) {
341 return USBD_REQ_NOTSUPP;
348 return USBD_REQ_NOTSUPP;
351 return USBD_REQ_HANDLED;
364 uint16_t usb_length = 0;
369 for (uint16_t i=0; i<usb_length && i<
LENGTH(usb_data); i++) {
383 static bool usb_tx_ongoing =
false;
385 if (!usbd_dev && usb_tx_ongoing) {
389 usb_tx_ongoing =
false;
394 usb_tx_ongoing =
true;
435 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);
441 static char serial[] =
"H_YYYY-MM-DD_AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
446 rcc_periph_reset_pulse(RST_USB);
448 rcc_periph_clock_enable(RCC_GPIOA);
449 rcc_periph_clock_enable(RCC_USB);
452 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
BusVoodoo global definitions and methods (API)
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.
#define BUILD_MONTH
build month as number if known, or 0 if unknown
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
size_t snprintf(char *str, size_t size, const char *format,...)
print format string on string or user output
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
printing utilities to replace the large printf from the standard library (API)
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.
#define BUILD_YEAR
build year as number if known, or 0 if unknown
static void usb_cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
USB CDC ACM data received callback.
char busvoodoo_version
version of the hardware board
static void usb_cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep)
USB CDC ACM data transmitted callback.
#define BUILD_DAY
build day as number if known, or 0 if unknown
static void usb_cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
set USB CDC ACM configuration