- 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:
parent
6edf06c2ca
commit
dcf2c2b808
@ -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()
|
||||||
|
54
class/cdc.c
54
class/cdc.c
@ -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,26 +47,51 @@ 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
|
||||||
@ -69,11 +99,13 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
|||||||
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,6 +142,7 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
// read from the fifo
|
// read from the fifo
|
||||||
|
if (cdcs.commInit) {
|
||||||
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE);
|
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE);
|
||||||
if (readSize > 0) {
|
if (readSize > 0) {
|
||||||
uint32_t writeSize = usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
|
uint32_t writeSize = usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
|
||||||
@ -117,6 +150,7 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,14 @@ typedef struct {
|
|||||||
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)
|
||||||
|
0
desc/.gitignore → desc-gen/.gitignore
vendored
0
desc/.gitignore → desc-gen/.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
import datetime
|
||||||
|
|
||||||
import Descriptor
|
import Descriptor
|
||||||
import Descriptor as desc
|
import Descriptor as desc
|
||||||
@ -78,8 +79,12 @@ class ConfigGenerator:
|
|||||||
|
|
||||||
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)
|
@ -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())
|
||||||
@ -51,3 +65,6 @@ cfggen.generate()
|
|||||||
#
|
#
|
||||||
# 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!")
|
149
desc/usb_desc.c
149
desc/usb_desc.c
@ -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
|
|
||||||
};
|
|
@ -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
|
|
@ -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
134
driver/stm32/usb_drv.c
Normal 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
35
driver/stm32/usb_drv.h
Normal 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
5
usb.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
8
usb_descriptor_common.h
Normal 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 */
|
11
usb_driver.c
11
usb_driver.c
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user