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 51 static volatile uint16_t
tx_i = 0;
59 .bLength = USB_DT_DEVICE_SIZE,
60 .bDescriptorType = USB_DT_DEVICE,
62 .bDeviceClass = USB_CLASS_CDC,
65 .bMaxPacketSize0 = 64,
72 .bNumConfigurations = 1,
79 .bLength = USB_DT_ENDPOINT_SIZE,
80 .bDescriptorType = USB_DT_ENDPOINT,
81 .bEndpointAddress = 0x02,
82 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
86 .bLength = USB_DT_ENDPOINT_SIZE,
87 .bDescriptorType = USB_DT_ENDPOINT,
88 .bEndpointAddress = 0x82,
89 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
98 .bLength = USB_DT_ENDPOINT_SIZE,
99 .bDescriptorType = USB_DT_ENDPOINT,
100 .bEndpointAddress = 0x81,
101 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
102 .wMaxPacketSize = 16,
110 static const struct {
113 struct usb_cdc_acm_descriptor
acm;
117 .bFunctionLength =
sizeof(
struct usb_cdc_header_descriptor),
118 .bDescriptorType = CS_INTERFACE,
119 .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
123 .bFunctionLength =
sizeof(
struct usb_cdc_call_management_descriptor),
124 .bDescriptorType = CS_INTERFACE,
125 .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
130 .bFunctionLength =
sizeof(
struct usb_cdc_acm_descriptor),
131 .bDescriptorType = CS_INTERFACE,
132 .bDescriptorSubtype = USB_CDC_TYPE_ACM,
136 .bFunctionLength =
sizeof(
struct usb_cdc_union_descriptor),
137 .bDescriptorType = CS_INTERFACE,
138 .bDescriptorSubtype = USB_CDC_TYPE_UNION,
139 .bControlInterface = 0,
140 .bSubordinateInterface0 = 1,
148 .bLength = USB_DT_INTERFACE_SIZE,
149 .bDescriptorType = USB_DT_INTERFACE,
150 .bInterfaceNumber = 0,
151 .bAlternateSetting = 0,
153 .bInterfaceClass = USB_CLASS_CDC,
154 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
155 .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,
160 .extra = &usb_cdcacm_functional_descriptors,
161 .extralen =
sizeof(usb_cdcacm_functional_descriptors),
168 .bLength = USB_DT_INTERFACE_SIZE,
169 .bDescriptorType = USB_DT_INTERFACE,
170 .bInterfaceNumber = 1,
171 .bAlternateSetting = 0,
173 .bInterfaceClass = USB_CLASS_DATA,
174 .bInterfaceSubClass = 0,
175 .bInterfaceProtocol = 0,
185 .bLength =
sizeof(
struct usb_dfu_descriptor),
186 .bDescriptorType = DFU_FUNCTIONAL,
187 .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
188 .wDetachTimeout = 200,
190 .bcdDFUVersion = 0x0110,
197 .bLength = USB_DT_INTERFACE_SIZE,
198 .bDescriptorType = USB_DT_INTERFACE,
199 .bInterfaceNumber = 2,
200 .bAlternateSetting = 0,
202 .bInterfaceClass = 0xFE,
203 .bInterfaceSubClass = 1,
204 .bInterfaceProtocol = 1,
225 .bLength = USB_DT_CONFIGURATION_SIZE,
226 .bDescriptorType = USB_DT_CONFIGURATION,
229 .bConfigurationValue = 1,
231 .bmAttributes = 0x80,
242 "BusVoodoo multi-protocol debugging adapter",
243 "DFU bootloader (runtime mode)",
249 #if defined(MAPLE_MINI) 251 rcc_periph_clock_enable(RCC_GPIOB);
252 gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO9);
253 gpio_set(GPIOB, GPIO9);
254 for (uint32_t i = 0; i < 0x2000; i++) {
259 rcc_periph_clock_enable(RCC_GPIOA);
260 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
261 gpio_clear(GPIOA, GPIO12);
262 for (uint32_t i = 0; i < 0x2000; i++) {
272 static void usb_reset(usbd_device *usbd_dev,
struct usb_setup_data *req)
290 RCC_CSR |= RCC_CSR_RMVF;
305 usbd_ep_write_packet(usbd_dev, 0x82, NULL, 0);
318 static int 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))
321 switch (req->bRequest) {
326 (*buf)[0] = DFU_STATUS_OK;;
330 (*buf)[4] = STATE_APP_IDLE;
338 switch (req->bRequest) {
339 case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
347 uint8_t reply[10] = {0};
348 struct usb_cdc_notification *notif = (
void *)reply;
350 notif->bmRequestType = 0xA1;
351 notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
355 reply[8] = req->wValue & 3;
357 usbd_ep_write_packet(usbd_dev, 0x81, reply,
LENGTH(reply));
360 case USB_CDC_REQ_SET_LINE_CODING:
362 if (*len <
sizeof(
struct usb_cdc_line_coding)) {
366 struct usb_cdc_line_coding *coding = (
struct usb_cdc_line_coding *)*buf;
370 if (coding->bDataBits==5) {
391 uint16_t usb_length = 0;
394 usb_length = usbd_ep_read_packet(usbd_dev, 0x02, usb_data,
sizeof(usb_data));
396 for (uint16_t i=0; i<usb_length && i<
LENGTH(usb_data); i++) {
423 usbd_ep_write_packet(
usb_device, 0x82, NULL, 0);
440 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);
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);
478 usbd_ep_write_packet(
usb_device, 0x82, NULL, 0);
#define USB_DATA_TRANSFER_SIZE
maximum packet size for USB data transfer
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 const struct usb_dfu_descriptor usb_dfu_functional
USB DFU functional descriptor.
static void usb_cdcacm_control_cb(usbd_device *usbd_dev, struct usb_setup_data *req)
USB CDC ACM control callback.
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_reset(usbd_device *usbd_dev, struct usb_setup_data *req)
disconnect USB and perform system reset
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.
static int 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
struct usb_cdc_call_management_descriptor call_mgmt
call management descriptor
static volatile bool usb_tx_ongoing
if USB transmission is already ongoing
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
static uint8_t tx_buffer[512]
ring buffer for data to transmit