Hello!
I have recently begun learning freeRTOS. Everything has been going quite good except the following:
When I try to use USB provided by libopencm3, my program hangs without explanation. I have seen discussion of removing or adding “-fstack-protector-all”
When I add this, my compiling crashes on ‘flash.o’.
Attempts to trace the crash have failed so far, but this is probably due to my inexperience. The same HID code works fine when run on it’s own.
Any advice getting a USB HID composite device working in freeRTOS would be great.
One last note: I also have not been able to get USART code to work alongside the libopenCM3 HID firmware without FreeRTOS. It also fails without any warnings.
Pasted below is my failing code. Huge thank you in advance to anyone with some advice for me!
I would switch to cube, but there is no working composite USB examples. I am open to switching to the ST HAL or CMSIS platform, but again finding good USB examples has been challenging.
/* Simple LED task demo, using timed delays:
*
* The LED on PC13 is toggled in task1.
*/
#include "FreeRTOS.h"
#include "task.h"
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/hid.h>
#include "myGPIO.h"
#include "usbtimer.h"
static usbd_device *usbd_dev;
// The device descriptor of a USB device represents the entire device. As a result a USB device can only have one device
// descriptor. It specifies some basic, yet important information about the device such as the supported USB version,
// maximum packet size, vendor and product IDs and the number of possible configurations the device can have. The format
// of the device descriptor is shown below.
const struct usb_device_descriptor dev_descr = {
.bLength = USB_DT_DEVICE_SIZE, // Size of the Descriptor in Bytes (18 bytes)
.bDescriptorType = USB_DT_DEVICE, // Device Descriptor (0x01)
.bcdUSB = 0x0200, // USB Specification Number which device complies too.
.bDeviceClass = 0, // Class Code (Assigned by USB Org), If equal to Zero, each interface specifies it’s own class code, If equal to 0xFF, the class code is vendor specified. Otherwise field is valid Class Code.
.bDeviceSubClass = 0, // Subclass Code (Assigned by USB Org)
.bDeviceProtocol = 0, // Protocol Code (Assigned by USB Org)
.bMaxPacketSize0 = 64, // Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
.idVendor = 0x0483, // Vendor ID (Assigned by USB Org)
.idProduct = 0x5710, // Product ID (Assigned by Manufacturer)
.bcdDevice = 0x0200, // Device Release Number
.iManufacturer = 1, // Index of Manufacturer String Descriptor
.iProduct = 2, // Index of Product String Descriptor
.iSerialNumber = 3, // Index of Serial Number String Descriptor
.bNumConfigurations = 1, // Number of Possible Configurations
};
static const uint8_t hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x08, // USAGE_MAXIMUM (Button 8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0x00, 0x19, // LOGICAL_MAXIMUM (6400 = 0x1900)
0x75, 0x10, // REPORT_SIZE
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x09, 0x35, // USAGE (Rz)
0x09, 0x36, // USAGE (Throttle)
0x09, 0x37, // USAGE (Rudder)
0x95, 0x08, // REPORT_COUNT
0x81, 0x82, // INPUT (Data,Var,Abs,Vol)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
static const struct {
struct usb_hid_descriptor hid_descriptor;
struct {
uint8_t bReportDescriptorType;
uint16_t wDescriptorLength;
} __attribute__((packed)) hid_report;
} __attribute__((packed)) hid_function = {
.hid_descriptor = {
.bLength = sizeof(hid_function),
.bDescriptorType = USB_DT_HID,
.bcdHID = 0x0100,
.bCountryCode = 0,
.bNumDescriptors = 1,
},
.hid_report = {
.bReportDescriptorType = USB_DT_REPORT,
.wDescriptorLength = sizeof(hid_report_descriptor),
}
};
// Endpoint Address
// Bits 0..3b Endpoint Number.
// Bits 4..6b Reserved. Set to Zero
// Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
const struct usb_endpoint_descriptor hid_endpoint = {
.bLength = USB_DT_ENDPOINT_SIZE, // Size of Descriptor in Bytes (7 bytes)
.bDescriptorType = USB_DT_ENDPOINT, // Endpoint Descriptor (0x05)
.bEndpointAddress = 0x81, // 10000001
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 17, // Maximum Packet Size this endpoint is capable of sending or receiving
.bInterval = 0x02, // Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints.
};
const struct usb_interface_descriptor hid_iface = {
.bLength = USB_DT_INTERFACE_SIZE, // Size of Descriptor in Bytes (9 Bytes)
.bDescriptorType = USB_DT_INTERFACE, // Interface Descriptor (0x04)
.bInterfaceNumber = 0, // Number of Interface
.bAlternateSetting = 0, // Value used to select alternative setting
.bNumEndpoints = 1, // Number of Endpoints used for this interface
.bInterfaceClass = USB_CLASS_HID, // Class Code (Assigned by USB Org)
.bInterfaceSubClass = 1, /* boot */ // Subclass Code (Assigned by USB Org)
.bInterfaceProtocol = 0, /* mouse */ // Protocol Code (Assigned by USB Org)
.iInterface = 0, // Index of String Descriptor Describing this interface
.endpoint = &hid_endpoint,
.extra = &hid_function,
.extralen = sizeof(hid_function),
};
const struct usb_interface ifaces[] = {{
.num_altsetting = 1,
.altsetting = &hid_iface,
}};
const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE, // Size of Descriptor in Bytes
.bDescriptorType = USB_DT_CONFIGURATION, // Configuration Descriptor (0x02)
.wTotalLength = 0, // Total length in bytes of data returned
.bNumInterfaces = 1, // Number of Interfaces
.bConfigurationValue = 1, // Value to use as an argument to select this configuration
.iConfiguration = 0, // Index of String Descriptor describing this configuration
.bmAttributes = 0xC0, // 11000000
.bMaxPower = 0x32, // Maximum Power Consumption in 2mA units
.interface = ifaces,
};
static const char *usb_strings[] = {
"Black Sphere Technologies",
"HID Demo",
"DEMO",
};
/* Buffer to be used for control requests. */
uint8_t usbd_control_buffer[128];
static enum usbd_request_return_codes hid_control_request(usbd_device *dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
void (**complete)(usbd_device *, struct usb_setup_data *))
{
(void)complete;
(void)dev;
if((req->bmRequestType != 0x81) ||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
(req->wValue != 0x2200))
return USBD_REQ_NOTSUPP;
/* Handle the HID report descriptor. */
*buf = (uint8_t *)hid_report_descriptor;
*len = sizeof(hid_report_descriptor);
return USBD_REQ_HANDLED;
}
static void hid_set_config(usbd_device *dev, uint16_t wValue)
{
(void)wValue;
(void)dev;
usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL);
usbd_register_control_callback(
dev,
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
hid_control_request);
}
extern void vApplicationStackOverflowHook(xTaskHandle *pxTask,signed portCHAR *pcTaskName);
void vApplicationStackOverflowHook(xTaskHandle *pxTask,signed portCHAR *pcTaskName) {
(void)pxTask;
(void)pcTaskName;
for(;;);
}
static void task1(void *args __attribute((unused)))
{
for (;;) {
toggleLED();
vTaskDelay(pdMS_TO_TICKS(500));
}
}
void tim2_isr(void)
{
TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */
//toggleLED();
}
int main(void) {
rcc_clock_setup_in_hse_8mhz_out_72mhz(); // For "blue pill"
gpio_setup();
timer_setup();
rcc_periph_clock_enable(RCC_GPIOA);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
gpio_clear(GPIOA, GPIO12);
usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &dev_descr, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
usbd_register_set_config_callback(usbd_dev, hid_set_config);
xTaskCreate(task1,"LED",100,NULL,configMAX_PRIORITIES-1,NULL);
vTaskStartScheduler();
for (;;)
usbd_poll(usbd_dev);
return 0;
}