aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorPiotr Esden-Tempski2011-10-30 18:40:26 -0700
committerPiotr Esden-Tempski2011-10-31 14:10:47 -0700
commit30d1aa957e57a3487124648b3590c28f72815c34 (patch)
tree1e9ec627fe1aa8e1042e9a927dd8840df083acf1 /examples
parente0fe43357d1f2f986e7969a3d6efe723e6828fcf (diff)
Added cdcacm (usb serial) example for lisa-m with a small basic stresstesting python script.
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32/f1/lisa-m/usb_cdcacm/Makefile23
-rw-r--r--examples/stm32/f1/lisa-m/usb_cdcacm/README7
-rw-r--r--examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.c251
-rw-r--r--examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.ld31
-rw-r--r--examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm_test.py38
5 files changed, 350 insertions, 0 deletions
diff --git a/examples/stm32/f1/lisa-m/usb_cdcacm/Makefile b/examples/stm32/f1/lisa-m/usb_cdcacm/Makefile
new file mode 100644
index 0000000..38179e3
--- /dev/null
+++ b/examples/stm32/f1/lisa-m/usb_cdcacm/Makefile
@@ -0,0 +1,23 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+BINARY = cdcacm
+
+include ../../Makefile.include
+
diff --git a/examples/stm32/f1/lisa-m/usb_cdcacm/README b/examples/stm32/f1/lisa-m/usb_cdcacm/README
new file mode 100644
index 0000000..2f1ee4b
--- /dev/null
+++ b/examples/stm32/f1/lisa-m/usb_cdcacm/README
@@ -0,0 +1,7 @@
+------------------------------------------------------------------------------
+README
+------------------------------------------------------------------------------
+
+This example implements a USB CDC-ACM device (aka Virtual Serial Port)
+to demonstrate the use of the USB device stack.
+
diff --git a/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.c b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.c
new file mode 100644
index 0000000..cc72140
--- /dev/null
+++ b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.c
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <libopencm3/stm32/f1/rcc.h>
+#include <libopencm3/stm32/f1/gpio.h>
+#include <libopencm3/usb/usbd.h>
+#include <libopencm3/usb/cdc.h>
+
+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 = 0x0483,
+ .idProduct = 0x5740,
+ .bcdDevice = 0x0200,
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .iSerialNumber = 3,
+ .bNumConfigurations = 1,
+};
+
+/* This notification endpoint isn't implemented. According to CDC spec its
+ * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm
+ * driver. */
+static const struct usb_endpoint_descriptor comm_endp[] = {{
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x83,
+ .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
+ .wMaxPacketSize = 16,
+ .bInterval = 255,
+}};
+
+static const struct usb_endpoint_descriptor data_endp[] = {{
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x01,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 1,
+}, {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 0x82,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 1,
+}};
+
+static const struct {
+ struct usb_cdc_header_descriptor header;
+ 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 = {
+ .header = {
+ .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
+ .bcdCDC = 0x0110,
+ },
+ .call_mgmt = {
+ .bFunctionLength =
+ sizeof(struct usb_cdc_call_management_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
+ .bmCapabilities = 0,
+ .bDataInterface = 1,
+ },
+ .acm = {
+ .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_ACM,
+ .bmCapabilities = 0,
+ },
+ .cdc_union = {
+ .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_UNION,
+ .bControlInterface = 0,
+ .bSubordinateInterface0 = 1,
+ }
+};
+
+static const struct usb_interface_descriptor comm_iface[] = {{
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_CDC,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
+ .iInterface = 0,
+
+ .endpoint = comm_endp,
+
+ .extra = &cdcacm_functional_descriptors,
+ .extralen = sizeof(cdcacm_functional_descriptors)
+}};
+
+static const struct usb_interface_descriptor data_iface[] = {{
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0,
+
+ .endpoint = data_endp,
+}};
+
+static const struct usb_interface ifaces[] = {{
+ .num_altsetting = 1,
+ .altsetting = comm_iface,
+}, {
+ .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 = 2,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = 0x80,
+ .bMaxPower = 0x32,
+
+ .interface = ifaces,
+};
+
+static const char *usb_strings[] = {
+ "x",
+ "Black Sphere Technologies",
+ "CDC-ACM Demo",
+ "DEMO"
+};
+
+static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf,
+ u16 *len, void (**complete)(struct usb_setup_data *req))
+{
+ (void)complete;
+ (void)buf;
+
+ switch(req->bRequest) {
+ case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
+ /* This Linux cdc_acm driver requires this to be implemented
+ * even though it's optional in the CDC spec, and we don't
+ * advertise it in the ACM functional descriptor. */
+ char buf[10];
+ struct usb_cdc_notification *notif = (void*)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;
+ buf[8] = req->wValue & 3;
+ 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))
+ return 0;
+
+ return 1;
+ }
+ return 0;
+}
+
+static void cdcacm_data_rx_cb(u8 ep)
+{
+ (void)ep;
+
+ char buf[64];
+ int len = usbd_ep_read_packet(0x01, buf, 64);
+ if(len) {
+ usbd_ep_write_packet(0x82, buf, len);
+ buf[len] = 0;
+ }
+
+ gpio_toggle(GPIOC, GPIO5);
+}
+
+static void cdcacm_set_config(u16 wValue)
+{
+ (void)wValue;
+
+ usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
+ usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
+ usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
+
+ usbd_register_control_callback(
+ USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
+ USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
+ cdcacm_control_request);
+}
+
+int main(void)
+{
+ int i;
+
+ rcc_clock_setup_in_hsi_out_48mhz();
+
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
+
+ gpio_set(GPIOC, GPIO2);
+ gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
+ gpio_set(GPIOC, GPIO5);
+ gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
+
+ usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
+ usbd_register_set_config_callback(cdcacm_set_config);
+
+ for (i = 0; i < 0x800000; i++)
+ __asm__("nop");
+ gpio_clear(GPIOC, GPIO2);
+
+ while (1)
+ usbd_poll();
+}
diff --git a/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.ld b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.ld
new file mode 100644
index 0000000..d0df9e6
--- /dev/null
+++ b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm.ld
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
+}
+
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32f1.ld
+
diff --git a/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm_test.py b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm_test.py
new file mode 100644
index 0000000..4a9f491
--- /dev/null
+++ b/examples/stm32/f1/lisa-m/usb_cdcacm/cdcacm_test.py
@@ -0,0 +1,38 @@
+#! /usr/bin/env python
+
+import serial
+import signal
+import sys
+import time
+
+def signal_handler(signal, frame):
+ print 'You pressed Ctrl+C!'
+ ser.close();
+ sys.exit(0)
+
+signal.signal(signal.SIGINT, signal_handler);
+
+ser = serial.Serial('/dev/cu.usbmodemDEM1', 115200, timeout=1);
+
+error = 0
+
+tim = time.time();
+
+cycles = 0
+
+while 1==1:
+
+ ser.write("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(){}");
+
+ buf = ser.read(75);
+
+ cycles += 1
+
+ if buf != "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(){}" :
+ error+=1
+
+ print "received " + buf + " errors: " + str(error) + " cycles: " + str(cycles) + " runtime: " + str(time.time() - tim)
+
+ #time.sleep(0.1);
+
+ser.close();