- CMake target on generating descriptors from JSON

added
- basic flatUSB_config.h concept added
- example JSONs added
- CDC request replies fixed
This commit is contained in:
Wiesner András 2024-11-14 13:19:09 +01:00
parent 6edf06c2ca
commit dcf2c2b808
21 changed files with 371 additions and 320 deletions

View File

@ -22,13 +22,24 @@ if ("CDC_EEM" IN_LIST FLATUSB_CLASSES)
) )
endif() endif()
if (FLATUSB_DESC_DIR)
AUX_SOURCE_DIRECTORY(${FLATUSB_DESC_DIR} FLATUSB_DESC_SRC)
set(FLATUSB_DESC_HEADER ${FLATUSB_DESC_DIR}/usb_desc.h)
if (FLATUSB_DESC_SRC)
message("flatUSB descriptors: " ${FLATUSB_DESC_SRC})
else()
message("flatUSB descriptors: (empty)")
endif()
elseif(NOT FLATUSB_DESC_SRC)
message("flatUSB: No source of descriptors passed! Please either set FLATUSB_DESC_DIR to the directory containing the descriptor files OR pass descriptor files directly by defining FLATUSB_DESC_SRC and FLATUSB_DESC_HEADER!")
endif()
message("flatUSB classes selected: ${FLATUSB_CLASSES}") message("flatUSB classes selected: ${FLATUSB_CLASSES}")
set(FLATUSB_SRC set(FLATUSB_SRC
${FLATUSB_CLASSES_SRC} ${FLATUSB_CLASSES_SRC}
${FLATUSB_DESC_SRC}
desc/usb_desc.c
desc/usb_desc.h
usb.c usb.c
usb_callback_event.h usb_callback_event.h
usb_common_defs.h usb_common_defs.h
@ -45,6 +56,17 @@ set(FLATUSB_SRC
) )
add_library(${FLATUSB_TARGET} STATIC ${FLATUSB_SRC}) add_library(${FLATUSB_TARGET} STATIC ${FLATUSB_SRC})
target_include_directories(${FLATUSB_TARGET} PRIVATE ${FLATUSB_INCLUDES}) target_include_directories(${FLATUSB_TARGET} PRIVATE ${FLATUSB_INCLUDES} ${CMAKE_CURRENT_LIST_DIR})
target_compile_options(${FLATUSB_TARGET} PRIVATE ${FLATUSB_CPU_PARAMS}) target_compile_options(${FLATUSB_TARGET} PRIVATE ${FLATUSB_CPU_PARAMS})
target_compile_definitions(${FLATUSB_TARGET} PRIVATE ${FLATUSB_COMPILE_DEFS}) target_compile_definitions(${FLATUSB_TARGET} PRIVATE ${FLATUSB_COMPILE_DEFS})
target_compile_definitions(${FLATUSB_TARGET} PRIVATE FLATUSB_DESCRIPTOR_HEADER="${FLATUSB_DESC_HEADER}")
if (FLATUSB_DESC_JSON AND FLATUSB_DESC_DIR)
message("flatUSB: descriptor JSON passed: " ${FLATUSB_DESC_JSON})
message("flatUSB: also defining flatUSB-gen-desc target")
add_custom_target(
flatUSB-gen-desc
COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/desc-gen/main.py ${FLATUSB_DESC_JSON} ${FLATUSB_DESC_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
endif()

View File

@ -5,10 +5,12 @@
#include "../usb_device_types.h" #include "../usb_device_types.h"
#include "../usb.h" #include "../usb.h"
#include "flatUSB/usb_driver.h"
#include <blocking_io/blocking_fifo.h> #include <blocking_io/blocking_fifo.h>
#include <cmsis_gcc.h> #include <cmsis_gcc.h>
#include <string.h>
// state // state
static USB_CdcState cdcs = {0}; static USB_CdcState cdcs = {0};
@ -25,12 +27,15 @@ void usb_cdc_init(const USB_CdcAssignments *as) {
// clear the structure // clear the structure
memset(&cdcs, 0, sizeof(USB_CdcState)); memset(&cdcs, 0, sizeof(USB_CdcState));
// set Control Line State to something invalid
cdcs.control_line_state.D = USB_CDC_INVALID_CONTROL_LINE_STATE;
// fill-in default values // fill-in default values
USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding; // USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding;
lc->dwDTERate = USB_CDC_DEFAULT_BITRATE; // lc->dwDTERate = USB_CDC_DEFAULT_BITRATE;
lc->bCharFormat = USB_CDC_DEFAULT_CHAR_FORMAT; // lc->bCharFormat = USB_CDC_DEFAULT_CHAR_FORMAT;
lc->bParityType = USB_CDC_DEFAULT_PARITY_TYPE; // lc->bParityType = USB_CDC_DEFAULT_PARITY_TYPE;
lc->bDataBits = USB_CDC_DEFAULT_DATA_BITS; // lc->bDataBits = USB_CDC_DEFAULT_DATA_BITS;
// fill-in assigments // fill-in assigments
cdcs.ep_assignments = *as; cdcs.ep_assignments = *as;
@ -42,38 +47,65 @@ void usb_cdc_init(const USB_CdcAssignments *as) {
cdcs.interrupt_data = 0; cdcs.interrupt_data = 0;
cdcs.interrupt_pending = true; cdcs.interrupt_pending = true;
// from now on CDC is considered initialized // communication parameters have not been set
cdcs.initialized = true; cdcs.commInit = false;
// from now on CDC module is considered initialized
cdcs.moduleInit = true;
} }
// static uint8_t replyBuf[sizeof(USB_Cdc_LineCodingStruct)]; // static uint8_t replyBuf[sizeof(USB_Cdc_LineCodingStruct)];
static void usb_cdc_review_comm_init() {
// check if line coding was initialized
USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding;
bool lcOk = (lc->dwDTERate != 0) && (lc->bDataBits != 0);
// check if control line state was initialized
bool clsOk = cdcs.control_line_state.D != USB_CDC_INVALID_CONTROL_LINE_STATE;
// combine the above criteria
cdcs.commInit = lcOk && clsOk;
// wake up endpoint if initialized
if (cdcs.commInit) {
usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
}
}
int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) { int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
int ret = -1; int ret = -1;
switch (cbevt->type) { switch (cbevt->type) {
case USB_CBEVT_UNKNOWN_REQ: { case USB_CBEVT_UNKNOWN_REQ: {
// initialize reply
cbevt->reply_data = NULL;
cbevt->reply_size = 0;
cbevt->reply_valid = true;
switch (cbevt->setup_request->bRequest) { switch (cbevt->setup_request->bRequest) {
case USB_CDC_SET_LINE_CODING: // set line coding case USB_CDC_SET_LINE_CODING: // set line coding
memcpy(&cdcs.line_coding, cbevt->data, sizeof(USB_Cdc_LineCodingStruct)); memcpy(&cdcs.line_coding, cbevt->data, sizeof(USB_Cdc_LineCodingStruct));
usb_cdc_review_comm_init(); // review the communcation initialization state
// MSG("%u\n", cdcs.line_coding.dwDTERate); // MSG("%u\n", cdcs.line_coding.dwDTERate);
ret = 0; ret = 0;
break; break;
case USB_CDC_GET_LINE_CODING: // get line coding case USB_CDC_GET_LINE_CODING: // get line coding
cbevt->reply_data = (const uint8_t *)&cdcs.line_coding; // expert move: pass the pointer, no copying cbevt->reply_data = (const uint8_t *)&cdcs.line_coding; // expert move: pass the pointer, no copying
cbevt->reply_size = sizeof(USB_Cdc_LineCodingStruct); cbevt->reply_size = sizeof(USB_Cdc_LineCodingStruct);
cbevt->reply_valid = true; // the reply has been set to something valid
ret = 0; ret = 0;
break; break;
case USB_CDC_SEND_BREAK: // send break case USB_CDC_SEND_BREAK: // send break
// do nothing // do nothing
ret = 0; ret = 0;
break; break;
case USB_CDC_SET_CONTROL_LINE_STATE: // set control line state case USB_CDC_SET_CONTROL_LINE_STATE: // set control line state
memcpy(&cdcs.control_line_state, cbevt->data, sizeof(USB_Cdc_ControlLineStateStruct)); cdcs.control_line_state.D = cbevt->setup_request->wValue; // control line state is carried in wValue of the SETUP request
usb_cdc_review_comm_init(); // review the communcation initialization state
// MSG("%u\n", cdcs.control_line_state.D); // MSG("%u\n", cdcs.control_line_state.D);
ret = 0; ret = 0;
break; break;
default: default:
cbevt->reply_valid = false; // this event is not processed by or not related to the CDC ACM module
break; break;
} }
@ -110,10 +142,12 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
ret = 0; ret = 0;
// read from the fifo // read from the fifo
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE); if (cdcs.commInit) {
if (readSize > 0) { uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE);
uint32_t writeSize = usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer if (readSize > 0) {
bfifo_pop(&fifo, writeSize, 0); // pop with no blocking uint32_t writeSize = usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
bfifo_pop(&fifo, writeSize, 0); // pop with no blocking
}
} }
} }
} }
@ -130,7 +164,7 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
// } // }
void usb_cdc_write(const uint8_t *data, uint32_t size) { void usb_cdc_write(const uint8_t *data, uint32_t size) {
if (cdcs.initialized) { if (cdcs.moduleInit) {
bfifo_push_all(&fifo, data, size); bfifo_push_all(&fifo, data, size);
usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN); usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
} }

View File

@ -27,10 +27,10 @@ typedef enum {
// CDC line coding structure // CDC line coding structure
typedef struct { typedef struct {
uint32_t dwDTERate; // data terminal rate, bits per second uint32_t dwDTERate; // data terminal rate, bits per second
uint8_t bCharFormat; // character format uint8_t bCharFormat; // character format
uint8_t bParityType; // parity type uint8_t bParityType; // parity type
uint8_t bDataBits; // data bits uint8_t bDataBits; // data bits
} USB_Cdc_LineCodingStruct; } USB_Cdc_LineCodingStruct;
// CDC control line state struct // CDC control line state struct
@ -43,20 +43,23 @@ typedef struct {
// endpoint assignments // endpoint assignments
typedef struct { typedef struct {
uint8_t control_ep : 4; // control endpoint uint8_t control_ep : 4; // control endpoint
uint8_t data_ep : 4; // data endpoint uint8_t data_ep : 4; // data endpoint
} USB_CdcAssignments; } USB_CdcAssignments;
typedef struct { typedef struct {
USB_CdcAssignments ep_assignments; // endpoint assignments USB_CdcAssignments ep_assignments; // endpoint assignments
USB_Cdc_LineCodingStruct line_coding; // line coding USB_Cdc_LineCodingStruct line_coding; // line coding
USB_Cdc_ControlLineStateStruct control_line_state; // control line state USB_Cdc_ControlLineStateStruct control_line_state; // control line state
uint16_t interrupt_data; // data sent though the next transfer on the notification element uint16_t interrupt_data; // data sent though the next transfer on the notification element
bool interrupt_pending; // interrupt data is valid and should be send in the next cycle bool interrupt_pending; // interrupt data is valid and should be send in the next cycle
bool initialized; // CDC is initialized bool moduleInit; // CDC module is initialized
bool commInit; // communication is initialized
} USB_CdcState; } USB_CdcState;
// ---------------- // ----------------
#define USB_CDC_INVALID_CONTROL_LINE_STATE (0xFFFF)
#define USB_CDC_DEFAULT_BITRATE (115200) #define USB_CDC_DEFAULT_BITRATE (115200)
#define USB_CDC_DEFAULT_DATA_BITS (8) #define USB_CDC_DEFAULT_DATA_BITS (8)
#define USB_CDC_DEFAULT_PARITY_TYPE (0) #define USB_CDC_DEFAULT_PARITY_TYPE (0)
@ -68,8 +71,8 @@ typedef struct {
// ---------------- // ----------------
void usb_cdc_init(const USB_CdcAssignments * as); void usb_cdc_init(const USB_CdcAssignments *as);
int usb_cdc_process_and_return(USB_CallbackEvent * cbevt); int usb_cdc_process_and_return(USB_CallbackEvent *cbevt);
void usb_cdc_write(const uint8_t * data, uint32_t size); void usb_cdc_write(const uint8_t *data, uint32_t size);
#endif /* CORE_USB_CLASS_CDC */ #endif /* CORE_USB_CLASS_CDC */

View File

@ -1,4 +1,5 @@
import subprocess import subprocess
import datetime
import Descriptor import Descriptor
import Descriptor as desc import Descriptor as desc
@ -74,12 +75,16 @@ class ConfigGenerator:
# "serial_number" # "serial_number"
# ] # ]
#self.str_mgr.add_placeholders(string_fields) # self.str_mgr.add_placeholders(string_fields)
self.LANG_ID_US_EN = "0x0409" self.LANG_ID_US_EN = "0x0409"
self.max_config_str_desc_size = 0 # maximal size (wLength) of config descriptors self.max_config_str_desc_size = (
self.max_endpoint_index = 0 # maximum endpoint index used in at least one of the configurations 0 # maximal size (wLength) of config descriptors
)
self.max_endpoint_index = (
0 # maximum endpoint index used in at least one of the configurations
)
self.max_endpoint_count = 0 # maximum endpoint count across all configurations self.max_endpoint_count = 0 # maximum endpoint count across all configurations
# add macro to header file # add macro to header file
@ -94,23 +99,36 @@ class ConfigGenerator:
self.h += "\n" self.h += "\n"
# save generated config # save generated config
def save(self): def save(self, target_dir):
DECLARATIONS = "usb_desc.h" DECLARATIONS = "usb_desc.h"
DEFINITIONS = "usb_desc.c" DEFINITIONS = "usb_desc.c"
with open(DEFINITIONS, 'w') as f_c: DECLARATIONS_FULLPATH = target_dir + "/" + DECLARATIONS
f_c.write("#include \"" + DECLARATIONS + "\"\n\n") DEFINITIONS_FULLPATH = target_dir + "/" + DEFINITIONS
INFO_HEADER = "//------------\n// Descriptors generated by flatUSB Descriptor Generator by Epagris on " + (str)(datetime.date.today()) + ".\n//------------\n\n"
with open(DEFINITIONS_FULLPATH, "w") as f_c:
f_c.write(INFO_HEADER)
f_c.write('#include "' + DECLARATIONS + '"\n\n')
f_c.write(self.c) f_c.write(self.c)
include_guard_tag = "_" + DECLARATIONS.replace(".", "_").upper() include_guard_tag = "_" + DECLARATIONS.replace(".", "_").upper()
with open(DECLARATIONS, 'w') as f_h: with open(DECLARATIONS_FULLPATH, "w") as f_h:
f_h.writelines(("#ifndef " + include_guard_tag + "\n", "#define " + include_guard_tag + "\n\n", "#include \"../usb_device_types.h\"\n\n")) f_h.writelines(
(
INFO_HEADER,
"#ifndef " + include_guard_tag + "\n",
"#define " + include_guard_tag + "\n\n",
'#include "usb_descriptor_common.h"\n\n',
)
)
f_h.write(self.h) f_h.write(self.h)
f_h.writelines(("\n\n#endif // " + include_guard_tag)) f_h.writelines(("\n\n#endif // " + include_guard_tag))
subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DECLARATIONS]) subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DECLARATIONS_FULLPATH])
subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DEFINITIONS]) subprocess.run(["indent", "-linux", "-l120", "-i4", "-nut", DEFINITIONS_FULLPATH])
# generate Device descriptor # generate Device descriptor
def generate_device_descriptor(self): def generate_device_descriptor(self):
@ -152,35 +170,49 @@ class ConfigGenerator:
# generate interface descriptor # generate interface descriptor
intf_varname = "intf{:d}".format(intf["id"]) intf_varname = "intf{:d}".format(intf["id"])
ep_count = get_distinct_endpoint_count(intf["endpoints"]) ep_count = get_distinct_endpoint_count(intf["endpoints"])
intf_struct = desc.InterfaceDescriptor(intf_varname, intf) # endpoint count is unknown intf_struct = desc.InterfaceDescriptor(
intf_varname, intf
) # endpoint count is unknown
full_conf_struct.add_record(intf_struct) full_conf_struct.add_record(intf_struct)
# generate additional interface descriptors # generate additional interface descriptors
for addintf in intf["additional_interfaces"]: for addintf in intf["additional_interfaces"]:
type = addintf["type"] type = addintf["type"]
addintf_struct = desc.DescriptorFactory.generate(type, intf_varname + type, addintf, self.str_mgr) addintf_struct = desc.DescriptorFactory.generate(
type, intf_varname + type, addintf, self.str_mgr
)
full_conf_struct.add_record(addintf_struct) full_conf_struct.add_record(addintf_struct)
# generate typedef only, if not done before # generate typedef only, if not done before
if addintf_tdefs.count(type) == 0: if addintf_tdefs.count(type) == 0:
self.h += addintf_struct.print_typedef() # print typedef self.h += addintf_struct.print_typedef() # print typedef
addintf_tdefs.append(type) # add to already generated typedefs to avoid duplication addintf_tdefs.append(
type
) # add to already generated typedefs to avoid duplication
# generate endpoint descriptors # generate endpoint descriptors
self.generate_endpoint_descriptors(intf, full_conf_struct) # generate endpoints self.generate_endpoint_descriptors(
intf, full_conf_struct
) # generate endpoints
# generate configuration descriptors and subordinate descriptor # generate configuration descriptors and subordinate descriptor
def generate_configuration_descriptors(self): def generate_configuration_descriptors(self):
# array for referencing configuration descriptors # array for referencing configuration descriptors
conf_desc_array_struct = desc.Descriptor("confDescs", "USB_ConfigurationDesc *", []) conf_desc_array_struct = desc.Descriptor(
"confDescs", "USB_ConfigurationDesc *", []
)
conf_desc_array_struct.typedef = "ConfDescs" conf_desc_array_struct.typedef = "ConfDescs"
# generate full configurations # generate full configurations
index = 0 index = 0
for conf in self.config["configurations"]: for conf in self.config["configurations"]:
full_conf_typename = "struct _FullConfigurations{:d}".format(index) full_conf_typename = "struct _FullConfigurations{:d}".format(index)
full_conf_struct = Descriptor.Descriptor("fullConfDescs{:d}".format(index), full_conf_typename, []) full_conf_struct = Descriptor.Descriptor(
conf_struct = desc.ConfigurationDescriptor("config", conf, "sizeof({:s})".format(full_conf_typename)) # TODO: total length "fullConfDescs{:d}".format(index), full_conf_typename, []
)
conf_struct = desc.ConfigurationDescriptor(
"config", conf, "sizeof({:s})".format(full_conf_typename)
) # TODO: total length
full_conf_struct.add_record(conf_struct) full_conf_struct.add_record(conf_struct)
self.generate_interface_descriptors(conf, full_conf_struct) self.generate_interface_descriptors(conf, full_conf_struct)
@ -188,7 +220,12 @@ class ConfigGenerator:
self.h += full_conf_struct.gen_h(print_typedef=True) self.h += full_conf_struct.gen_h(print_typedef=True)
# add descriptor's pointer to the list # add descriptor's pointer to the list
str_desc_ptr = StructGenerator.DummyRecord(full_conf_struct.name, "USB_ConfigurationDesc *", "(USB_ConfigurationDesc *) &" + full_conf_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER) str_desc_ptr = StructGenerator.DummyRecord(
full_conf_struct.name,
"USB_ConfigurationDesc *",
"(USB_ConfigurationDesc *) &" + full_conf_struct.name,
StructGenerator.RecordFactory.PLAIN_PRINTER,
)
conf_desc_array_struct.add_record(str_desc_ptr) conf_desc_array_struct.add_record(str_desc_ptr)
self.h += self.DIVIDER self.h += self.DIVIDER
@ -212,7 +249,12 @@ class ConfigGenerator:
self.c += lang_id_struct.gen_c() self.c += lang_id_struct.gen_c()
self.h += lang_id_struct.gen_h(print_typedef=True) self.h += lang_id_struct.gen_h(print_typedef=True)
str_desc_ptr = StructGenerator.DummyRecord(lang_id_struct.name, "USB_StringDesc *", "(USB_StringDesc *) &" + lang_id_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER) str_desc_ptr = StructGenerator.DummyRecord(
lang_id_struct.name,
"USB_StringDesc *",
"(USB_StringDesc *) &" + lang_id_struct.name,
StructGenerator.RecordFactory.PLAIN_PRINTER,
)
str_desc_array_struct.add_record(str_desc_ptr) str_desc_array_struct.add_record(str_desc_ptr)
# generate individual string descriptors # generate individual string descriptors
@ -226,7 +268,12 @@ class ConfigGenerator:
self.h += str_struct.gen_h(print_typedef=True) self.h += str_struct.gen_h(print_typedef=True)
# add descriptor's pointer to the list # add descriptor's pointer to the list
str_desc_ptr = StructGenerator.DummyRecord(text_id, "USB_StringDesc *", "(USB_StringDesc *) &" + str_struct.name, StructGenerator.RecordFactory.PLAIN_PRINTER) str_desc_ptr = StructGenerator.DummyRecord(
text_id,
"USB_StringDesc *",
"(USB_StringDesc *) &" + str_struct.name,
StructGenerator.RecordFactory.PLAIN_PRINTER,
)
str_desc_array_struct.add_record(str_desc_ptr) str_desc_array_struct.add_record(str_desc_ptr)
self.h += self.DIVIDER self.h += self.DIVIDER
@ -237,10 +284,14 @@ class ConfigGenerator:
self.c += str_desc_array_struct.gen_c() self.c += str_desc_array_struct.gen_c()
def generate_macros(self): def generate_macros(self):
self.add_def_macro("USBF_NOF_CONFIGURATIONS", str(len(self.config["configurations"])), "Number of configurations") self.add_def_macro(
"USBF_NOF_CONFIGURATIONS",
str(len(self.config["configurations"])),
"Number of configurations",
)
self.h += self.DIVIDER self.h += self.DIVIDER
def generate(self): def generate(self, target_dir: str):
self.generate_macros() # generate macro definitions self.generate_macros() # generate macro definitions
self.generate_device_descriptor() # generate device descriptor self.generate_device_descriptor() # generate device descriptor
self.generate_device_qualifier_descriptor() # generate device qualifier descriptor self.generate_device_qualifier_descriptor() # generate device qualifier descriptor
@ -248,4 +299,4 @@ class ConfigGenerator:
self.generate_string_descriptors() # generate string descriptors (should be the last one, since additional interface descriptors may add new string descriptors) self.generate_string_descriptors() # generate string descriptors (should be the last one, since additional interface descriptors may add new string descriptors)
# save generated files # save generated files
self.save() self.save(target_dir)

View File

@ -8,8 +8,22 @@ from itertools import chain
from ConfigGenerator import ConfigGenerator from ConfigGenerator import ConfigGenerator
# print welcome message
print("----\nflatUSB descriptor generator by Epagris\n----\n")
# check number of parameters
if len(argv) < 3:
print("Insufficient parameters!\nCorrect usage: `main.py <input json> <target directory>`\nExiting.")
exit(0)
# fetch USB settings # fetch USB settings
usb_config_file_name = argv[1] usb_config_file_name = argv[1]
usb_target_dir = argv[2]
# print input and output parameters
print("Input JSON: ", usb_config_file_name)
print("Target directory: ", usb_target_dir)
#usb_config_file_name = "/home/epagris/VCSDEV/usbt1/stws/USB-T1/Modules/flatUSB/desc/usb_config_cdc.json" #usb_config_file_name = "/home/epagris/VCSDEV/usbt1/stws/USB-T1/Modules/flatUSB/desc/usb_config_cdc.json"
with open(usb_config_file_name, 'r') as usb_config_file: with open(usb_config_file_name, 'r') as usb_config_file:
usb_config_data = usb_config_file.read() usb_config_data = usb_config_file.read()
@ -26,7 +40,7 @@ if "misc" in usb_config:
# generate config # generate config
cfggen = ConfigGenerator(usb_config) cfggen = ConfigGenerator(usb_config)
cfggen.generate() cfggen.generate(usb_target_dir)
# devDesc = desc.DeviceDescriptor(usb_config) # devDesc = desc.DeviceDescriptor(usb_config)
# print(devDesc.print_assigment()) # print(devDesc.print_assigment())
@ -50,4 +64,7 @@ cfggen.generate()
# print(struct2.print_typedef("struct2")) # print(struct2.print_typedef("struct2"))
# #
# structrec = sg.StructRecord("object", "struct compound", [ struct1, struct2, *recs ]) # structrec = sg.StructRecord("object", "struct compound", [ struct1, struct2, *recs ])
# print(structrec.print_content()) # print(structrec.print_content())
# print complete message
print("Descriptor generation complete!")

View File

@ -1,149 +0,0 @@
#include "usb_desc.h"
const USB_DeviceDesc devDesc = { /* Device Descriptor */
0x12, //bLength
UD_Device, //bDescriptorType
0x200, //bcdUSB
0x2, //bDeviceClass
0x0, //bDeviceSubclass
0x0, //bDeviceProtocol
0x40, //bMaxPacketSize0
0x925, //idVendor
0x9050, //idProduct
0x100, //bcdDevice
0x1, //iManufacturer
0x2, //iProduct
0x3, //iSerialNumber
0x1, //bNumConfigurations
};
const USB_DeviceQualifierDesc devQualDesc = { /* Device Qualifier descriptor */
0x9, //bLength
UD_DeviceQualifier, //bDescriptorType
0x200, //bcdUSB
0x2, //bDeviceClass
0x0, //bDeviceSubclass
0x0, //bDeviceProtocol
0x40, //bMaxPacketSize
0x1, //bNumConfigurations
};
const FullConfigurations0 fullConfDescs0 = {
{ /* Configuration descriptor */
0x9, //bLength
UD_Configuration, //bDescriptorType
sizeof(struct _FullConfigurations0), //wTotalLength
0x2, //bNumInterfaces
0x1, //bConfigurationValue
0x0, //iConfiguration
USB_CONFIG_ATTR_USB1_1_FLAG, //bmAttributes
0x32, //bMaxPower
}, //config
{ /* Interface descriptor : 0 */
0x9, //bLength
UD_Interface, //bDescriptorType
0x0, //bInterfaceNumber
0x0, //bAlternateSetting
0x1, //bNumEndpoints
0x2, //bInterfaceClass
0x2, //bInterfaceSubclass
0x1, //bInterfaceProtocol
0x0, //iInterface
}, //intf0
{ /* Header Functional descriptor */
0x5, //bLength
0x24, //bDescriptorType
0x0, //bDescriptorSubType
0x110, //bcdCDC
}, //intf0hfd
{ /* Abstract Control Management Functional descriptor */
0x4, //bLength
0x24, //bDescriptorType
0x2, //bDescriptorSubType
0x2, //bmCapabilities
}, //intf0acmfd
{ /* Union Functional descriptor */
0x5, //bLength
0x24, //bDescriptorType
0x6, //bDescriptorSubType
0x0, //bMasterInterface
0x1, //bSlaveInterface0
}, //intf0ufd
{ /* Call Management Functional descriptor */
0x5, //bLength
0x24, //bDescriptorType
0x1, //bDescriptorSubType
0x0, //bmCapabilities
0x1, //dDataInterface
}, //intf0cmfd
{ /* Endpoint descriptor : 2 in */
0x7, //bLength
UD_Endpoint, //bDescriptorType
(USB_IN << 7) | (2), //bEndpointAddress
UT_Interrupt, //bmAttributes
0x40, //wMaxPacketSize
0x2, //bInterval
}, //ep2in
{ /* Interface descriptor : 1 */
0x9, //bLength
UD_Interface, //bDescriptorType
0x1, //bInterfaceNumber
0x0, //bAlternateSetting
0x2, //bNumEndpoints
0xa, //bInterfaceClass
0x0, //bInterfaceSubclass
0x0, //bInterfaceProtocol
0x0, //iInterface
}, //intf1
{ /* Endpoint descriptor : 1 in */
0x7, //bLength
UD_Endpoint, //bDescriptorType
(USB_IN << 7) | (1), //bEndpointAddress
UT_Bulk, //bmAttributes
0x40, //wMaxPacketSize
0x0, //bInterval
}, //ep1in
{ /* Endpoint descriptor : 1 out */
0x7, //bLength
UD_Endpoint, //bDescriptorType
(USB_OUT << 7) | (1), //bEndpointAddress
UT_Bulk, //bmAttributes
0x40, //wMaxPacketSize
0x0, //bInterval
}, //ep1out
};
const ConfDescs confDescs = {
(USB_ConfigurationDesc *) & fullConfDescs0, //fullConfDescs0
};
const USB_StrDesc_lang_id lang_id = { /* String descriptor */
0x4, //bLength
UD_String, //bDescriptorType
0x409, //bString
};
const USB_StrDesc_vendor_string vendor_string = { /* String descriptor */
0x10, //bLength
UD_String, //bDescriptorType
{'E', 'p', 'a', 'g', 'r', 'i', 's',}, //bString
};
const USB_StrDesc_product_string product_string = { /* String descriptor */
0x16, //bLength
UD_String, //bDescriptorType
{'T', 'e', 's', 't', 'd', 'e', 'v', 'i', 'c', 'e',}, //bString
};
const USB_StrDesc_serial_number serial_number = { /* String descriptor */
0xa, //bLength
UD_String, //bDescriptorType
{'1', '5', '5', '2',}, //bString
};
const StringDescs strDescs = {
(USB_StringDesc *) & lang_id, //lang_id
(USB_StringDesc *) & vendor_string, //vendor_string
(USB_StringDesc *) & product_string, //product_string
(USB_StringDesc *) & serial_number, //serial_number
};

View File

@ -1,91 +0,0 @@
#ifndef _USB_DESC_H
#define _USB_DESC_H
#include "../usb_device_types.h"
#define USBF_NOF_CONFIGURATIONS (1) // Number of configurations
// ---------------------------
extern const USB_DeviceDesc devDesc; /* Device Descriptor */
extern const USB_DeviceQualifierDesc devQualDesc; /* Device Qualifier descriptor */
typedef struct _USB_HeaderFunctionalDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint16_t bcdCDC;
} __attribute__((packed)) USB_HeaderFunctionalDescriptor;
typedef struct _USB_AbstractControlManagementFunctionalDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bmCapabilities;
} __attribute__((packed)) USB_AbstractControlManagementFunctionalDescriptor;
typedef struct _USB_UnionFunctionalDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bMasterInterface;
uint8_t bSlaveInterface0;
} __attribute__((packed)) USB_UnionFunctionalDescriptor;
typedef struct _USB_CallManagementFunctionalDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bmCapabilities;
uint8_t dDataInterface;
} __attribute__((packed)) USB_CallManagementFunctionalDescriptor;
typedef struct _FullConfigurations0 {
USB_ConfigurationDesc config; /* Configuration descriptor */
USB_InterfaceDesc intf0; /* Interface descriptor : 0 */
USB_HeaderFunctionalDescriptor intf0hfd; /* Header Functional descriptor */
USB_AbstractControlManagementFunctionalDescriptor intf0acmfd; /* Abstract Control Management Functional descriptor */
USB_UnionFunctionalDescriptor intf0ufd; /* Union Functional descriptor */
USB_CallManagementFunctionalDescriptor intf0cmfd; /* Call Management Functional descriptor */
USB_EndpointDesc ep2in; /* Endpoint descriptor : 2 in */
USB_InterfaceDesc intf1; /* Interface descriptor : 1 */
USB_EndpointDesc ep1in; /* Endpoint descriptor : 1 in */
USB_EndpointDesc ep1out; /* Endpoint descriptor : 1 out */
} __attribute__((packed)) FullConfigurations0;
extern const FullConfigurations0 fullConfDescs0;
// ---------------------------
typedef USB_ConfigurationDesc *ConfDescs[1];
extern const ConfDescs confDescs;
typedef struct _USB_StrDesc_lang_id {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString;
} __attribute__((packed)) USB_StrDesc_lang_id;
extern const USB_StrDesc_lang_id lang_id; /* String descriptor */
typedef struct _USB_StrDesc_vendor_string {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString[7];
} __attribute__((packed)) USB_StrDesc_vendor_string;
extern const USB_StrDesc_vendor_string vendor_string; /* String descriptor */
typedef struct _USB_StrDesc_product_string {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString[10];
} __attribute__((packed)) USB_StrDesc_product_string;
extern const USB_StrDesc_product_string product_string; /* String descriptor */
typedef struct _USB_StrDesc_serial_number {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString[4];
} __attribute__((packed)) USB_StrDesc_serial_number;
extern const USB_StrDesc_serial_number serial_number; /* String descriptor */
// ---------------------------
typedef USB_StringDesc *StringDescs[4];
extern const StringDescs strDescs;
#endif // _USB_DESC_H

View File

@ -1,28 +1,22 @@
#ifndef CORE_USB_USB_COMMON_DEFS #ifndef CORE_USB_USB_COMMON_DEFS
#define CORE_USB_USB_COMMON_DEFS #define CORE_USB_USB_COMMON_DEFS
#include <flatUSB_config.h>
// Select appropriate headers
#if defined(STM32H745xx) || defined(STM32H743xx) || defined(STM32H723xx) #if defined(STM32H745xx) || defined(STM32H743xx) || defined(STM32H723xx)
#include <stm32h7xx.h> #include <stm32h7xx.h>
#include <stm32h7xx_hal.h> #include <stm32h7xx_hal.h>
#if defined(STM32H745xx) || defined(STM32H743xx)
#define USBG (USB_OTG_FS)
#elif defined(STM32H723xx)
#define USBG (USB_OTG_HS)
#endif
#define USB_STM32H7 #define USB_STM32H7
// ------------
#elif defined(STM32F407xx) || defined(STM32F401xC) #elif defined(STM32F407xx) || defined(STM32F401xC)
#include <stm32f4xx.h> #include <stm32f4xx.h>
#include <stm32f4xx_hal.h> #include <stm32f4xx_hal.h>
#define USB_STM32F4 #define USB_STM32F4
#ifdef USB_HIGH_SPEED
#define USBG (USB_OTG_HS)
#else
#define USBG (USB_OTG_FS)
#endif
#endif #endif
#define USBD ((USB_OTG_DeviceTypeDef *) (((uint32_t)(USBG)) + ((uint32_t)(USB_OTG_DEVICE_BASE)))) #define USBD ((USB_OTG_DeviceTypeDef *) (((uint32_t)(USBG)) + ((uint32_t)(USB_OTG_DEVICE_BASE))))

134
driver/stm32/usb_drv.c Normal file
View File

@ -0,0 +1,134 @@
#include "usb_drv.h"
#include "flatUSB_config.h"
#include "stm32f4xx_hal.h"
#include "usb_common.h"
#include "usb_common_defs.h"
// ------------------------
#ifdef USB_HIGH_SPEED
__weak void usbdrv_ulpi_init() {
return;
}
#endif
// ------------------------
// initialize USB peripheral
void usbdrv_periph_init() {
USB_CLOCK_ENABLE();
// HAL_Delay(1000);
//__HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE();
//__HAL_RCC_USB_OTG_FS_FORCE_RESET();
//__HAL_RCC_USB_OTG_FS_RELEASE_RESET();
#if defined(USB_STM32H7)
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL); // select the internal FS PHY
WAIT_FOR_nBIT_DELAY(USBG->GRSTCTL, USB_OTG_GRSTCTL_AHBIDL, 1);
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset the USB core
HAL_Delay(1);
WAIT_FOR_BIT_DELAY(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST, 1);
#else
#if defined(USB_HIGH_SPEED)
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL); // select the external HS PHY
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_TSDPS);
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIFSLS);
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIEVBUSD);
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIEVBUSI);
// SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL);
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset USB core
HAL_Delay(1);
WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST);
usbdrv_ulpi_init(); // initialize PHY
#endif
#endif
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // power the internal transceiver peripheral
CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); // mask all interrupts for now
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP); // disable HNP and SRP
WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TRDT, TRDT_VALUE); // set TRDT according to the RM
// WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TOCAL, TOCAL_VALUE); // set TOCAL
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FHMOD); // clear Host mode forcing
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FDMOD); // force Device mode
HAL_Delay(25); // wait for Device mode forcing propagation
WAIT_FOR_BIT(USBG->GINTSTS, 0b1);
// SET_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS); // soft disconnect peripheral (should be upper, but since it's controlled by a Device register, cannot be set before switching to device mode)
#if defined(USB_STM32H7)
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBDEN); // turn off VBUSSENSE
SET_BIT(USBG->GOTGCTL, USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL); // force B-session
#elif defined(USB_STM32F4)
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_VBUSASEN);
#endif
// HAL_Delay(50); // it takes time to forcing Device mode takes effect
#ifdef USB_HIGH_SPEED
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED);
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_HIGH_SPEED_ULPI);
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED_ULPI);
#else
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED); // there's no other possible option
#endif
// allow specific interrupts
uint32_t intmask = /*USB_OTG_GINTMSK_WUIM | // Wake up */
USB_OTG_GINTMSK_OEPINT | // OUT EP events
USB_OTG_GINTMSK_IEPINT | // IN EP events
USB_OTG_GINTMSK_ENUMDNEM | // (Linespeed) Enumeration (negotiation) done
USB_OTG_GINTMSK_USBRST | // USB Reset
USB_OTG_GINTMSK_USBSUSPM | // USB Suspend
USB_OTG_GINTMSK_RXFLVLM; // RX FIFO level (signal if non-empty)
USBG->GINTMSK = intmask;
// set global NAK on all Endpoints
// usbdrv_set_global_NAK(USB_IN, true);
// usbdrv_set_global_NAK(USB_OUT, true);
// flush Tx and Rx FIFOs
usbdrv_flush_rx_fifo();
usbdrv_flush_tx_fifo(USB_FLUSH_TX_FIFO_ALL);
// make Tx FIFO empty interrupt fire when Tx FIFO is emtpy
// SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_TXFELVL);
// set masks for endpoint interrupts
SET_BIT(USBD->DIEPMSK, USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_ITTXFEMSK); // transfer complete, timeout and Tx FIFO empty while receiving IN for IN EPs
SET_BIT(USBD->DOEPMSK, USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_STUPM); // transfer complete and SETUP complete for OUT EPs
// mask all endpoint interrupts in both directions and also clear flags
USBD->DAINTMSK = 0;
USBD->DAINT = 0;
// enbale global interrupts
SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT);
}
// initialize USB subsystem
void usbdrv_init() {
HAL_NVIC_DisableIRQ(USB_IRQn);
//usbdrv_init_global_state();
usbdrv_gpio_init();
usbdrv_periph_init();
usbdrv_initial_ep0_setup();
usbdrv_power_and_connect(true);
HAL_NVIC_SetPriority(USB_IRQn, 8, 0);
HAL_NVIC_EnableIRQ(USB_IRQn);
}

35
driver/stm32/usb_drv.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef STM32_USB_DRV
#define STM32_USB_DRV
#include "usb_common_defs.h"
// Select IO crossbar advanced function
#if defined(USB_STM32H7)
#ifndef STM32H723xx
#define USB_GPIO_AF (GPIO_AF10_OTG2_FS)
#else
// #define USB_GPIO_AF (GPIO_AF10_OTG1_HS)
#endif
#elif defined(USB_STM32F4)
#ifdef USB_HIGH_SPEED
#define USB_GPIO_AF (GPIO_AF10_OTG_HS)
#else
#define USB_GPIO_AF (GPIO_AF10_OTG_FS)
#endif
#endif
// Set TOCAL and TRDT values (see Ref. Man.)
#if defined(USB_STM32H7) /*|| defined(USB_HIGH_SPEED)*/
#define TOCAL_VALUE (0x00)
#define TRDT_VALUE (0x05)
#elif defined(USB_STM32F4)
#if !defined(USB_HIGH_SPEED)
#define TOCAL_VALUE (0x07)
#define TRDT_VALUE (0x06)
#else
#define TOCAL_VALUE (0x07)
#define TRDT_VALUE (0x09)
#endif
#endif
#endif /* STM32_USB_DRV */

5
usb.c
View File

@ -3,11 +3,10 @@
#include <memory.h> #include <memory.h>
#include "usb_common.h" #include "usb_common.h"
#include "usb_core_types.h"
// #include "utils/gen_queue.h" // #include "utils/gen_queue.h"
#include "desc/usb_desc.h" #include FLATUSB_DESCRIPTOR_HEADER
#include "usb_driver.h" #include "usb_driver.h"
@ -44,7 +43,7 @@ static uint8_t tx_assembly_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // buffer for assem
// ---------------- // ----------------
__weak void usb_event_callback(USB_CallbackEvent *cbevt) { __attribute__((weak)) void usb_event_callback(USB_CallbackEvent *cbevt) {
return; return;
} }

View File

@ -2,7 +2,6 @@
#define CORE_USB_USB_COMMON #define CORE_USB_USB_COMMON
#include "usb_common_types.h" #include "usb_common_types.h"
#include "usb_common_defs.h"
#include "usb_device_types.h" #include "usb_device_types.h"
#define READ_FIELD(r,f) (((r) & (f##_Msk)) >> (f##_Pos)) #define READ_FIELD(r,f) (((r) & (f##_Msk)) >> (f##_Pos))

8
usb_descriptor_common.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef FLATUSB_USB_DESCRIPTOR_COMMON
#define FLATUSB_USB_DESCRIPTOR_COMMON
#include <stdint.h>
#include "usb_device_types.h"
#endif /* FLATUSB_USB_DESCRIPTOR_COMMON */

View File

@ -3,13 +3,12 @@
#include <memory.h> #include <memory.h>
#include "flatUSB/usb_common_defs.h" #include "usb_common_defs.h"
#include "stm32h743xx.h"
#include "usb_common.h" #include "usb_common.h"
#include <stm32h7xx_hal.h> #include "usb_device_types.h"
#include "desc/usb_desc.h" #include FLATUSB_DESCRIPTOR_HEADER
#include "embfmt/embformat.h" #include "embfmt/embformat.h"
#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__) #define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
@ -206,10 +205,6 @@ __weak void usbdrv_ulpi_init() {
// --------------- // ---------------
#define USB_LINESPEED_FULL_SPEED (0b11)
#define USB_LINESPEED_FULL_SPEED_ULPI (0b01)
#define USB_LINESPEED_HIGH_SPEED_ULPI (0b00)
// initialize USB peripheral // initialize USB peripheral
void usbdrv_periph_init() { void usbdrv_periph_init() {
#if defined(USB_STM32H7) #if defined(USB_STM32H7)
@ -234,7 +229,7 @@ void usbdrv_periph_init() {
#endif #endif
#endif #endif
//HAL_Delay(1000); // HAL_Delay(1000);
//__HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE(); //__HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE();
//__HAL_RCC_USB_OTG_FS_FORCE_RESET(); //__HAL_RCC_USB_OTG_FS_FORCE_RESET();