diff options
Diffstat (limited to 'testhal/STM32/USB_CDC/main.c')
-rw-r--r-- | testhal/STM32/USB_CDC/main.c | 420 |
1 files changed, 235 insertions, 185 deletions
diff --git a/testhal/STM32/USB_CDC/main.c b/testhal/STM32/USB_CDC/main.c index 70a27a8f2..6d8994c8d 100644 --- a/testhal/STM32/USB_CDC/main.c +++ b/testhal/STM32/USB_CDC/main.c @@ -1,5 +1,6 @@ /*
- ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
@@ -17,142 +18,133 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
+#include <string.h>
+
#include "ch.h"
#include "hal.h"
#include "test.h"
+#include "usb_cdc.h"
+#include "shell.h"
+
/*===========================================================================*/
/* USB related stuff. */
/*===========================================================================*/
-#define DATA_REQUEST_EP 1
-#define INTERRUPT_REQUEST_EP 2
-#define DATA_AVAILABLE_EP 3
-
/*
- * USB driver structure.
+ * USB Driver structure.
*/
static SerialUSBDriver SDU1;
/*
* USB Device Descriptor.
*/
-static const uint8_t vcom_device_descriptor_data[] = {
- 18, /* bLength. */
- USB_DESCRIPTOR_DEVICE, /* bDescriptorType. */
- 0x10, 0x01, /* bcdUSB (1.1). */
- 0x02, /* bDeviceClass (CDC). */
- 0x00, /* bDeviceSubClass. */
- 0x00, /* bDeviceProtocol. */
- 0x40, /* bMaxPacketSize. */
- 0x83, 0x04, /* idVendor (0x0483). */
- 0x40, 0x57, /* idProduct (0x7540). */
- 0x00, 0x02, /* bcdDevice (2.00). */
- 1, /* iManufacturer. */
- 2, /* iProduct. */
- 3, /* IiSerialNumber. */
- 1 /* bNumConfigurations. */
+static const uint8_t vcom_device_descriptor_data[18] = {
+ USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */
+ 0x02, /* bDeviceClass (CDC). */
+ 0x00, /* bDeviceSubClass. */
+ 0x00, /* bDeviceProtocol. */
+ 0x40, /* bMaxPacketSize. */
+ 0x0483, /* idVendor (ST). */
+ 0x5740, /* idProduct. */
+ 0x0200, /* bcdDevice. */
+ 1, /* iManufacturer. */
+ 2, /* iProduct. */
+ 3, /* iSerialNumber. */
+ 1) /* bNumConfigurations. */
};
/*
- * Device descriptor wrapper.
+ * Device Descriptor wrapper.
*/
static const USBDescriptor vcom_device_descriptor = {
- sizeof (vcom_device_descriptor_data),
+ sizeof vcom_device_descriptor_data,
vcom_device_descriptor_data
};
-/* Configuration Descriptor tree for a VCOM.*/
-static const uint8_t vcom_configuration_descriptor_data[] = {
- /* Configuration descriptor.*/
- 9, /* bLength. */
- USB_DESCRIPTOR_CONFIGURATION, /* bDescriptorType. */
- 67, 0, /* wTotalLength. */
- 0x02, /* bNumInterfaces. */
- 0x01, /* bConfigurationValue. */
- 0, /* iConfiguration. */
- 0xC0, /* bmAttributes (self powered). */
- 50, /* MaxPower (100mA). */
+/* Configuration Descriptor tree for a CDC.*/
+static const uint8_t vcom_configuration_descriptor_data[67] = {
+ /* Configuration Descriptor.*/
+ USB_DESC_CONFIGURATION(67, /* wTotalLength. */
+ 0x02, /* bNumInterfaces. */
+ 0x01, /* bConfigurationValue. */
+ 0, /* iConfiguration. */
+ 0xC0, /* bmAttributes (self powered). */
+ 50), /* bMaxPower (100mA). */
/* Interface Descriptor.*/
- 9, /* bLength. */
- USB_DESCRIPTOR_INTERFACE, /* bDescriptorType. */
- 0x00, /* bInterfaceNumber. */
- 0x00, /* bAlternateSetting. */
- 0x01, /* bNumEndpoints. */
- 0x02, /* bInterfaceClass (Communications
- Interface Class, CDC section 4.2). */
- 0x02, /* bInterfaceSubClass (Abstract Control
- Model, CDC section 4.3). */
- 0x01, /* bInterfaceProtocol (AT commands, CDC
- section 4.4). */
- 0, /* iInterface. */
+ USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
+ 0x00, /* bAlternateSetting. */
+ 0x01, /* bNumEndpoints. */
+ 0x02, /* bInterfaceClass (Communications
+ Interface Class, CDC section
+ 4.2). */
+ 0x02, /* bInterfaceSubClass (Abstract
+ Control Model, CDC section 4.3). */
+ 0x01, /* bInterfaceProtocol (AT commands,
+ CDC section 4.4). */
+ 0), /* iInterface. */
/* Header Functional Descriptor (CDC section 5.2.3).*/
- 5, /* bLength. */
- 0x24, /* bDescriptorType (CS_INTERFACE). */
- 0x00, /* bDescriptorSubtype (Header Functional
- Descriptor. */
- 0x10, 0x01, /* bcdCDC (1.10). */
- /* Call Managment Functional Descriptor. */
- 5, /* bFunctionLength. */
- 0x24, /* bDescriptorType (CS_INTERFACE). */
- 0x01, /* bDescriptorSubtype (Call Management
- Functional Descriptor). */
- 0x00, /* bmCapabilities (D0+D1). */
- 0x01, /* bDataInterface. */
+ USB_DESC_BYTE (5), /* bLength. */
+ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
+ USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header
+ Functional Descriptor. */
+ USB_DESC_BCD (0x0110), /* bcdCDC. */
+ /* Call Management Functional Descriptor. */
+ USB_DESC_BYTE (5), /* bFunctionLength. */
+ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
+ USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management
+ Functional Descriptor). */
+ USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */
+ USB_DESC_BYTE (0x01), /* bDataInterface. */
/* ACM Functional Descriptor.*/
- 4, /* bFunctionLength. */
- 0x24, /* bDescriptorType (CS_INTERFACE). */
- 0x02, /* bDescriptorSubtype (Abstract Control
- Management Descriptor). */
- 0x02, /* bmCapabilities. */
+ USB_DESC_BYTE (4), /* bFunctionLength. */
+ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
+ USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract
+ Control Management Descriptor). */
+ USB_DESC_BYTE (0x02), /* bmCapabilities. */
/* Union Functional Descriptor.*/
- 5, /* bFunctionLength. */
- 0x24, /* bDescriptorType (CS_INTERFACE). */
- 0x06, /* bDescriptorSubtype (Union Functional
- Descriptor). */
- 0x00, /* bMasterInterface (Communication Class
- Interface). */
- 0x01, /* bSlaveInterface0 (Data Class
- Interface). */
+ USB_DESC_BYTE (5), /* bFunctionLength. */
+ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */
+ USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union
+ Functional Descriptor). */
+ USB_DESC_BYTE (0x00), /* bMasterInterface (Communication
+ Class Interface). */
+ USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class
+ Interface). */
/* Endpoint 2 Descriptor.*/
- 7, /* bLength. */
- USB_DESCRIPTOR_ENDPOINT, /* bDescriptorType. */
- INTERRUPT_REQUEST_EP | 0x80, /* bEndpointAddress (IN). */
- 0x03, /* bmAttributes (Interrupt). */
- 0x08, 0x00, /* wMaxPacketSize. */
- 0xFF, /* bInterval. */
+ USB_DESC_ENDPOINT (INTERRUPT_REQUEST_EP|0x80, /* bEndpointAddress. */
+ 0x03, /* bmAttributes (Interrupt). */
+ 0x0008, /* wMaxPacketSize. */
+ 0xFF), /* bInterval. */
/* Interface Descriptor.*/
- 9, /* bLength. */
- USB_DESCRIPTOR_INTERFACE, /* bDescriptorType. */
- 0x01, /* bInterfaceNumber. */
- 0x00, /* bAlternateSetting. */
- 0x02, /* bNumEndpoints. */
- 0x0A, /* bInterfaceClass (Data Class
- Interface, CDC section 4.5). */
- 0x00, /* bInterfaceSubClass (CDC section 4.6).*/
- 0x00, /* bInterfaceProtocol (CDC section 4.7).*/
- 0x00, /* iInterface. */
+ USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */
+ 0x00, /* bAlternateSetting. */
+ 0x02, /* bNumEndpoints. */
+ 0x0A, /* bInterfaceClass (Data Class
+ Interface, CDC section 4.5). */
+ 0x00, /* bInterfaceSubClass (CDC section
+ 4.6). */
+ 0x00, /* bInterfaceProtocol (CDC section
+ 4.7). */
+ 0x00), /* iInterface. */
/* Endpoint 3 Descriptor.*/
- 7, /* bLength. */
- USB_DESCRIPTOR_ENDPOINT, /* bDescriptorType. */
- DATA_AVAILABLE_EP, /* bEndpointAddress (OUT). */
- 0x02, /* bmAttributes (Bulk). */
- 0x40, 0x00, /* wMaxPacketSize. */
- 0x00, /* bInterval (ignored for bulk. */
+ USB_DESC_ENDPOINT (DATA_AVAILABLE_EP, /* bEndpointAddress. */
+ 0x02, /* bmAttributes (Bulk). */
+ 0x0040, /* wMaxPacketSize. */
+ 0x00), /* bInterval. */
/* Endpoint 1 Descriptor.*/
- 7, /* bLength. */
- USB_DESCRIPTOR_ENDPOINT, /* bDescriptorType. */
- DATA_REQUEST_EP | 0x80, /* bEndpointAddress (IN). */
- 0x02, /* bmAttributes (Bulk). */
- 0x40, 0x00, /* wMaxPacketSize. */
- 0x00 /* bInterval (ignored for bulk. */
+ USB_DESC_ENDPOINT (DATA_REQUEST_EP|0x80, /* bEndpointAddress. */
+ 0x02, /* bmAttributes (Bulk). */
+ 0x0040, /* wMaxPacketSize. */
+ 0x00) /* bInterval. */
};
/*
- * Configuration descriptor wrapper.
+ * Configuration Descriptor wrapper.
*/
static const USBDescriptor vcom_configuration_descriptor = {
- sizeof (vcom_configuration_descriptor_data),
+ sizeof vcom_configuration_descriptor_data,
vcom_configuration_descriptor_data
};
@@ -160,28 +152,28 @@ static const USBDescriptor vcom_configuration_descriptor = { * U.S. English language identifier.
*/
static const uint8_t vcom_string0[] = {
- 4, /* bLength. */
- USB_DESCRIPTOR_STRING, /* bDescriptorType. */
- 0x09, 0x04 /* wLANGID (0x0409, U.S. English). */
+ USB_DESC_BYTE(4), /* bLength. */
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
+ USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
};
/*
* Vendor string.
*/
static const uint8_t vcom_string1[] = {
- 38, /* bLength. */
- USB_DESCRIPTOR_STRING, /* bDescriptorType. */
+ USB_DESC_BYTE(38), /* bLength. */
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
/*
- * Device description string.
+ * Device Description string.
*/
static const uint8_t vcom_string2[] = {
- 56, /* bLength. */
- USB_DESCRIPTOR_STRING, /* bDescriptorType. */
+ USB_DESC_BYTE(56), /* bLength. */
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
@@ -189,11 +181,11 @@ static const uint8_t vcom_string2[] = { };
/*
- * Serial number string.
+ * Serial Number string.
*/
static const uint8_t vcom_string3[] = {
- 8, /* bLength. */
- USB_DESCRIPTOR_STRING, /* bDescriptorType. */
+ USB_DESC_BYTE(8), /* bLength. */
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'0' + CH_KERNEL_MAJOR, 0,
'0' + CH_KERNEL_MINOR, 0,
'0' + CH_KERNEL_PATCH, 0
@@ -203,10 +195,10 @@ static const uint8_t vcom_string3[] = { * Strings wrappers array.
*/
static const USBDescriptor vcom_strings[] = {
- {sizeof(vcom_string0), vcom_string0},
- {sizeof(vcom_string1), vcom_string1},
- {sizeof(vcom_string2), vcom_string2},
- {sizeof(vcom_string3), vcom_string3}
+ {sizeof vcom_string0, vcom_string0},
+ {sizeof vcom_string1, vcom_string1},
+ {sizeof vcom_string2, vcom_string2},
+ {sizeof vcom_string3, vcom_string3}
};
/*
@@ -233,57 +225,45 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, }
/**
- * @brief EP1 state.
- */
-USBEndpointState ep1state;
-
-/**
- * @brief EP2 state.
- */
-USBEndpointState ep2state;
-
-/**
- * @brief EP3 state.
- */
-USBEndpointState ep3state;
-
-/**
* @brief EP1 initialization structure (IN only).
*/
static const USBEndpointConfig ep1config = {
- sduDataRequest,
+ USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET,
+ NULL,
+ sduDataTransmitted,
NULL,
0x0040,
0x0000,
- EPR_EP_TYPE_BULK | EPR_STAT_TX_NAK | EPR_STAT_RX_DIS,
- 0x00C0,
- 0x0000
+ NULL,
+ NULL
};
/**
* @brief EP2 initialization structure (IN only).
*/
static const USBEndpointConfig ep2config = {
- sduInterruptRequest,
+ USB_EP_MODE_TYPE_INTR | USB_EP_MODE_PACKET,
+ NULL,
+ sduInterruptTransmitted,
NULL,
0x0010,
0x0000,
- EPR_EP_TYPE_INTERRUPT | EPR_STAT_TX_NAK | EPR_STAT_RX_DIS,
- 0x0100,
- 0x0000
+ NULL,
+ NULL
};
/**
* @brief EP3 initialization structure (OUT only).
*/
static const USBEndpointConfig ep3config = {
+ USB_EP_MODE_TYPE_BULK | USB_EP_MODE_PACKET,
+ NULL,
NULL,
- sduDataAvailable,
+ sduDataReceived,
0x0000,
0x0040,
- EPR_EP_TYPE_BULK | EPR_STAT_TX_DIS | EPR_STAT_RX_VALID,
- 0x0000,
- 0x0110
+ NULL,
+ NULL
};
/*
@@ -297,16 +277,18 @@ static void usb_event(USBDriver *usbp, usbevent_t event) { case USB_EVENT_ADDRESS:
return;
case USB_EVENT_CONFIGURED:
- /* Enables the endpoints specified into the configuration.*/
- chSysLock();
- usbInitEndpointI(usbp, DATA_REQUEST_EP, &ep1state, &ep1config);
- usbInitEndpointI(usbp, INTERRUPT_REQUEST_EP, &ep2state, &ep2config);
- usbInitEndpointI(usbp, DATA_AVAILABLE_EP, &ep3state, &ep3config);
- chSysUnlock();
+ /* Enables the endpoints specified into the configuration.
+ Note, this callback is invoked from an ISR so I-Class functions
+ must be used.*/
+ chSysLockFromIsr();
+ usbInitEndpointI(usbp, DATA_REQUEST_EP, &ep1config);
+ usbInitEndpointI(usbp, INTERRUPT_REQUEST_EP, &ep2config);
+ usbInitEndpointI(usbp, DATA_AVAILABLE_EP, &ep3config);
+ chSysUnlockFromIsr();
return;
case USB_EVENT_SUSPEND:
return;
- case USB_EVENT_RESUME:
+ case USB_EVENT_WAKEUP:
return;
case USB_EVENT_STALLED:
return;
@@ -324,10 +306,98 @@ static const SerialUSBConfig serusbcfg = { get_descriptor,
sduRequestsHook,
NULL
- },
- DATA_REQUEST_EP,
- DATA_AVAILABLE_EP,
- INTERRUPT_REQUEST_EP
+ }
+};
+
+/*===========================================================================*/
+/* Command line related. */
+/*===========================================================================*/
+
+#define SHELL_WA_SIZE THD_WA_SIZE(2048)
+#define TEST_WA_SIZE THD_WA_SIZE(256)
+
+static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
+ size_t n, size;
+ char buf[52];
+
+ (void)argv;
+ if (argc > 0) {
+ shellPrintLine(chp, "Usage: mem");
+ return;
+ }
+ n = chHeapStatus(NULL, &size);
+ siprintf(buf, "core free memory : %u bytes", chCoreStatus());
+ shellPrintLine(chp, buf);
+ siprintf(buf, "heap fragments : %u", n);
+ shellPrintLine(chp, buf);
+ siprintf(buf, "heap free total : %u bytes", size);
+ shellPrintLine(chp, buf);
+}
+
+static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
+ static const char *states[] = {
+ "READY",
+ "CURRENT",
+ "SUSPENDED",
+ "WTSEM",
+ "WTMTX",
+ "WTCOND",
+ "SLEEPING",
+ "WTEXIT",
+ "WTOREVT",
+ "WTANDEVT",
+ "SNDMSGQ",
+ "SNDMSG",
+ "WTMSG",
+ "FINAL"
+ };
+ Thread *tp;
+ char buf[60];
+
+ (void)argv;
+ if (argc > 0) {
+ shellPrintLine(chp, "Usage: threads");
+ return;
+ }
+ shellPrintLine(chp, " addr stack prio refs state time");
+ tp = chRegFirstThread();
+ do {
+ siprintf(buf, "%8lx %8lx %4u %4i %9s %u",
+ (uint32_t)tp, (uint32_t)tp->p_ctx.r13,
+ (unsigned int)tp->p_prio, tp->p_refs - 1,
+ states[tp->p_state], (unsigned int)tp->p_time);
+ shellPrintLine(chp, buf);
+ tp = chRegNextThread(tp);
+ } while (tp != NULL);
+}
+
+static void cmd_test(BaseChannel *chp, int argc, char *argv[]) {
+ Thread *tp;
+
+ (void)argv;
+ if (argc > 0) {
+ shellPrintLine(chp, "Usage: test");
+ return;
+ }
+ tp = chThdCreateFromHeap(NULL, TEST_WA_SIZE, chThdGetPriority(),
+ TestThread, chp);
+ if (tp == NULL) {
+ shellPrintLine(chp, "out of memory");
+ return;
+ }
+ chThdWait(tp);
+}
+
+static const ShellCommand commands[] = {
+ {"mem", cmd_mem},
+ {"threads", cmd_threads},
+ {"test", cmd_test},
+ {NULL, NULL}
+};
+
+static const ShellConfig shell_cfg1 = {
+ (BaseChannel *)&SDU1,
+ commands
};
/*===========================================================================*/
@@ -350,29 +420,10 @@ static msg_t Thread1(void *arg) { }
/*
- * USB CDC loopback thread.
- */
-static WORKING_AREA(waThread2, 256);
-static msg_t Thread2(void *arg) {
- SerialUSBDriver *sdup = arg;
- EventListener el;
-
- chEvtRegisterMask(chIOGetEventSource(&SDU1), &el, 1);
- while (TRUE) {
- chEvtWaitAny(ALL_EVENTS);
- if (chOQIsEmptyI(&SDU1.oqueue)) {
- uint8_t buffer[0x40];
- size_t n = chIQReadTimeout(&sdup->iqueue, buffer,
- sizeof(buffer), TIME_IMMEDIATE);
- chOQWriteTimeout(&sdup->oqueue, buffer, n, TIME_IMMEDIATE);
- }
- }
-}
-
-/*
* Application entry point.
*/
int main(void) {
+ Thread *shelltp = NULL;
/*
* System initializations.
@@ -385,16 +436,16 @@ int main(void) { chSysInit();
/*
- * Activates the USB bus and then the USB driver.
+ * Activates the USB driver and then the USB bus pull-up on D+.
*/
- palClearPad(GPIOC, GPIOC_USB_DISC);
sduObjectInit(&SDU1);
sduStart(&SDU1, &serusbcfg);
+ palClearPad(GPIOC, GPIOC_USB_DISC);
/*
- * Activates the serial driver 2 using the driver default configuration.
+ * Shell manager initialization.
*/
- sdStart(&SD2, NULL);
+ shellInit();
/*
* Creates the blinker thread.
@@ -402,17 +453,16 @@ int main(void) { chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
/*
- * Creates the USB CDC loopback thread.
- */
- chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, &SDU1);
-
- /*
* Normal main() thread activity, in this demo it does nothing except
* sleeping in a loop and check the button state.
*/
while (TRUE) {
- if (palReadPad(IOPORT1, GPIOA_BUTTON))
- TestThread(&SD2);
+ if (!shelltp && (SDU1.config->usbp->state == USB_ACTIVE))
+ shelltp = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
+ else if (chThdTerminated(shelltp)) {
+ chThdRelease(shelltp); /* Recovers memory of the previous shell. */
+ shelltp = NULL; /* Triggers spawning of a new shell. */
+ }
chThdSleepMilliseconds(1000);
}
}
|