31 #include <libopencm3/stm32/rcc.h>
32 #include <libopencm3/stm32/gpio.h>
33 #include <libopencm3/cm3/nvic.h>
34 #include <libopencm3/cm3/systick.h>
35 #include <libopencm3/usb/usbd.h>
36 #include <libopencm3/usb/cdc.h>
37 #include <libopencm3/cm3/scb.h>
38 #include <libopencm3/stm32/desig.h>
39 #include <libopencm3/stm32/otg_fs.h>
43 #include "mcu_periph/sys_time_arch.h"
46 #define MAX_PACKET_SIZE 64
48 #define VCOM_FIFO_SIZE 256
50 #define TX_TIMEOUT_CNT 20 //TODO, make dynamic with event period
74 static const struct usb_device_descriptor
dev = {
75 .bLength = USB_DT_DEVICE_SIZE,
76 .bDescriptorType = USB_DT_DEVICE,
78 .bDeviceClass = USB_CLASS_CDC,
88 .bNumConfigurations = 1,
96 static const struct usb_endpoint_descriptor
comm_endp[] = {{
97 .bLength = USB_DT_ENDPOINT_SIZE,
98 .bDescriptorType = USB_DT_ENDPOINT,
99 .bEndpointAddress = 0x83,
100 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
101 .wMaxPacketSize = 16,
106 static const struct usb_endpoint_descriptor
data_endp[] = {{
107 .bLength = USB_DT_ENDPOINT_SIZE,
108 .bDescriptorType = USB_DT_ENDPOINT,
109 .bEndpointAddress = 0x01,
110 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
114 .bLength = USB_DT_ENDPOINT_SIZE,
115 .bDescriptorType = USB_DT_ENDPOINT,
116 .bEndpointAddress = 0x82,
117 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
123 static const struct {
124 struct usb_cdc_header_descriptor header;
125 struct usb_cdc_call_management_descriptor call_mgmt;
126 struct usb_cdc_acm_descriptor acm;
127 struct usb_cdc_union_descriptor cdc_union;
130 .bFunctionLength =
sizeof(
struct usb_cdc_header_descriptor),
132 .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
137 sizeof(
struct usb_cdc_call_management_descriptor),
139 .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
144 .bFunctionLength =
sizeof(
struct usb_cdc_acm_descriptor),
146 .bDescriptorSubtype = USB_CDC_TYPE_ACM,
150 .bFunctionLength =
sizeof(
struct usb_cdc_union_descriptor),
152 .bDescriptorSubtype = USB_CDC_TYPE_UNION,
153 .bControlInterface = 0,
154 .bSubordinateInterface0 = 1,
158 static const struct usb_interface_descriptor
comm_iface[] = {{
159 .bLength = USB_DT_INTERFACE_SIZE,
160 .bDescriptorType = USB_DT_INTERFACE,
161 .bInterfaceNumber = 0,
162 .bAlternateSetting = 0,
164 .bInterfaceClass = USB_CLASS_CDC,
165 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
166 .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
176 static const struct usb_interface_descriptor
data_iface[] = {{
177 .bLength = USB_DT_INTERFACE_SIZE,
178 .bDescriptorType = USB_DT_INTERFACE,
179 .bInterfaceNumber = 1,
180 .bAlternateSetting = 0,
182 .bInterfaceClass = USB_CLASS_DATA,
183 .bInterfaceSubClass = 0,
184 .bInterfaceProtocol = 0,
191 static const struct usb_interface
ifaces[] = {{
200 static const struct usb_config_descriptor
config = {
201 .bLength = USB_DT_CONFIGURATION_SIZE,
202 .bDescriptorType = USB_DT_CONFIGURATION,
205 .bConfigurationValue = 1,
207 .bmAttributes = 0x80,
234 uint16_t *len,
void (**complete)(usbd_device *usbd_dev,
struct usb_setup_data *req))
240 switch (req->bRequest) {
241 case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
248 struct usb_cdc_notification *notif = (
void *)local_buf;
251 notif->bmRequestType = 0xA1;
252 notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
256 local_buf[8] = req->wValue & 3;
258 usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
261 case USB_CDC_REQ_SET_LINE_CODING:
262 if (*len <
sizeof(
struct usb_cdc_line_coding)) {
285 for (
int i = 0; i < len; i++) {
308 usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK,
MAX_PACKET_SIZE, NULL);
309 usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
311 usbd_register_control_callback(usbd_dev,
312 USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
313 USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
318 usbd_register_suspend_callback(usbd_dev,
suspend_cb);
337 if (next == fifo->
tail) {
383 *pc = fifo->
buf[index];
427 static int result = 0;
440 static int result = 0;
514 #ifdef USE_USB_LINE_CODING
527 long *
fd __attribute__((unused)),
534 long fd __attribute__((unused)),
541 long fd __attribute__((unused)),
545 for (i = 0; i < len; i++) {
573 rcc_periph_clock_enable(RCC_GPIOA);
574 gpio_mode_setup(
GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
580 rcc_periph_clock_enable(RCC_OTGFS);
583 desig_get_unique_id_as_string(
serial_no, 25);
594 OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS | OTG_GCCFG_PWRDWN;