Merge branch 'master' of epagris.com:epagris/flatUSB

This commit is contained in:
Wiesner András 2024-10-06 23:38:39 +02:00
commit 32a964f13c
8 changed files with 212 additions and 35 deletions

View File

@ -132,6 +132,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.initialized) {
bfifo_push_all(&fifo, data, size); bfifo_push_all(&fifo, data, size);
usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
} }
} }

View File

@ -27,9 +27,10 @@ class USB_DescriptorSize(Enum):
# base class for descriptor generator # base class for descriptor generator
class Descriptor(StructGenerator.StructRecord): class Descriptor(StructGenerator.StructRecord):
QUALIFIERS = "const"
def __init__(self, name, ctype, content, comment=None): def __init__(self, name, ctype, content, comment=None):
super().__init__(name, ctype, content, comment) super().__init__(name, ctype, content, comment)
self.qualifiers = "const" self.qualifiers = Descriptor.QUALIFIERS
self.typedef = ctype[8:] self.typedef = ctype[8:]
self.attribute = "packed" self.attribute = "packed"

View File

@ -10,10 +10,21 @@ from ConfigGenerator import ConfigGenerator
# fetch USB settings # fetch USB settings
usb_config_file_name = argv[1] usb_config_file_name = argv[1]
#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()
usb_config = json.loads(usb_config_data) usb_config = json.loads(usb_config_data)
# process "misc"
if "misc" in usb_config:
misc = usb_config["misc"]
# mutable descriptors
if "mutable_descriptors" in misc:
if misc["mutable_descriptors"]:
desc.Descriptor.QUALIFIERS = ""
# generate config
cfggen = ConfigGenerator(usb_config) cfggen = ConfigGenerator(usb_config)
cfggen.generate() cfggen.generate()

19
usb.c
View File

@ -25,7 +25,14 @@
// --------------- // ---------------
static uint8_t tx_assembly_buf[USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS] DWORD_ALIGN; // buffer for assembling packets #ifndef USB_HIGH_SPEED
#define USB_RX_BUF_SIZE (USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS)
#else
#define USB_RX_BUF_SIZE (USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS)
#endif
static uint8_t tx_assembly_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // buffer for assembling packets
// --------------- // ---------------
@ -131,8 +138,13 @@ void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stag
SET_TRANSMISSION_POINTER(&devDesc); SET_TRANSMISSION_POINTER(&devDesc);
break; break;
case UD_Configuration: // CONFIGURATION DESCRIPTOR case UD_Configuration: // CONFIGURATION DESCRIPTOR
case UD_OtherSpeedConfiguration: // OTHER SPEED CONFIGURATION DESCRIPTOR
DETERMINE_TRANSFER_SIZE(confDescs[desc_index]->wTotalLength); DETERMINE_TRANSFER_SIZE(confDescs[desc_index]->wTotalLength);
SET_TRANSMISSION_POINTER(confDescs[desc_index]); SET_TRANSMISSION_POINTER(confDescs[desc_index]);
if (desc_type == UD_OtherSpeedConfiguration) { // change bDescriptorType to Other_Speed_Configuration
confDescs[desc_index]->bDescriptorType = UD_OtherSpeedConfiguration;
}
break; break;
case UD_String: // STRING DESCRIPTOR case UD_String: // STRING DESCRIPTOR
DETERMINE_TRANSFER_SIZE(strDescs[desc_index]->bLength); DETERMINE_TRANSFER_SIZE(strDescs[desc_index]->bLength);
@ -236,7 +248,12 @@ void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) {
} }
} }
void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir) {
usbdrv_enable_endpoint_interrupt(ep, dir, true);
}
uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size) { uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size) {
usbdrv_enable_endpoint_interrupt(ep, USB_IN, true);
return usbdrv_arm_IN_endpoint(ep, data, size); return usbdrv_arm_IN_endpoint(ep, data, size);
} }

5
usb.h
View File

@ -3,8 +3,9 @@
#include "usb_callback_event.h" #include "usb_callback_event.h"
void usbcore_init(); // initialize USB core void usbcore_init(); // initialize USB core
uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint, return with number of bytes actually written uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint, return with number of bytes actually written
uint32_t usbcore_schedule_reception(uint8_t ep, uint16_t size); // expect data coming from the endpoint uint32_t usbcore_schedule_reception(uint8_t ep, uint16_t size); // expect data coming from the endpoint
void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir); // wake up endpoint
#endif /* CORE_USB_USB */ #endif /* CORE_USB_USB */

View File

@ -18,10 +18,10 @@
#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))))
#define USBINEP ((USB_OTG_INEndpointTypeDef *) ((uint32_t)(USBG) + (uint32_t)(USB_OTG_IN_ENDPOINT_BASE))) #define USBINEP ((USB_OTG_INEndpointTypeDef *) (((uint32_t)(USBG)) + ((uint32_t)(USB_OTG_IN_ENDPOINT_BASE))))
#define USBOUTEP ((USB_OTG_OUTEndpointTypeDef *) ((uint32_t)(USBG) + (uint32_t)(USB_OTG_OUT_ENDPOINT_BASE))) #define USBOUTEP ((USB_OTG_OUTEndpointTypeDef *) (((uint32_t)(USBG)) + ((uint32_t)(USB_OTG_OUT_ENDPOINT_BASE))))
#define USBFIFO(ep) ((uint32_t *)((uint32_t)(USBG) + USB_OTG_FIFO_BASE + (USB_OTG_FIFO_SIZE) * (ep))) #define USBFIFO(ep) ((uint32_t *)(((uint32_t)(USBG)) + USB_OTG_FIFO_BASE + (USB_OTG_FIFO_SIZE) * (ep)))
#define USBPCGCCTL ((uint32_t *)((uint32_t)(USBG) + USB_OTG_PCGCCTL_BASE)) #define USBPCGCCTL ((uint32_t *)(((uint32_t)(USBG)) + USB_OTG_PCGCCTL_BASE))
#endif /* CORE_USB_USB_COMMON_DEFS */ #endif /* CORE_USB_USB_COMMON_DEFS */

View File

@ -8,6 +8,9 @@
#include "desc/usb_desc.h" #include "desc/usb_desc.h"
#include "embfmt/embformat.h"
#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
// --------------- // ---------------
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b))
@ -24,7 +27,13 @@
static USBDRV_GlobalState gs; // global USB state static USBDRV_GlobalState gs; // global USB state
static uint8_t rx_buf[USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS] DWORD_ALIGN; // receive buffer #ifndef USB_HIGH_SPEED
#define USB_RX_BUF_SIZE (USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS)
#else
#define USB_RX_BUF_SIZE (USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS)
#endif
static uint8_t rx_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // receive buffer
#define USB_EVENT_QUEUE_LENGTH (16) #define USB_EVENT_QUEUE_LENGTH (16)
@ -45,14 +54,22 @@ static const char *FIFO_STATUS_STR[6] = {
#if defined(USB_STM32H7) #if defined(USB_STM32H7)
#define USB_GPIO_AF (GPIO_AF10_OTG2_FS) #define USB_GPIO_AF (GPIO_AF10_OTG2_FS)
#elif defined(USB_STM32F4) #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) #define USB_GPIO_AF (GPIO_AF10_OTG_FS)
#endif #endif
#endif
// USB pin low level, early peripheral initialization // USB pin low level, early peripheral initialization
// PA12: D+, PA11: D- // PA12: D+, PA11: D-
void usbdrv_gpio_init() { void usbdrv_gpio_init() {
// turn GPIO-s into AF mode // turn GPIO-s into AF mode
__HAL_RCC_GPIOA_CLK_ENABLE(); // turn ON GPIOA clocks __HAL_RCC_GPIOA_CLK_ENABLE(); // turn ON GPIOA clocks
#ifdef USB_HIGH_SPEED
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
#endif
GPIO_InitTypeDef gpio_init; GPIO_InitTypeDef gpio_init;
gpio_init.Mode = GPIO_MODE_AF_PP; gpio_init.Mode = GPIO_MODE_AF_PP;
@ -60,6 +77,19 @@ void usbdrv_gpio_init() {
gpio_init.Pull = GPIO_NOPULL; gpio_init.Pull = GPIO_NOPULL;
gpio_init.Alternate = USB_GPIO_AF; gpio_init.Alternate = USB_GPIO_AF;
#ifdef USB_HIGH_SPEED
gpio_init.Pin = GPIO_PIN_3 | GPIO_PIN_5; // D0, CK
HAL_GPIO_Init(GPIOA, &gpio_init);
// D1, D2, D7, D3, D4, D5, D6
gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &gpio_init);
// STP, DIR, NXT
gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3;
HAL_GPIO_Init(GPIOC, &gpio_init);
#else
/* Pin initializations cannot be OR-ed together! */ /* Pin initializations cannot be OR-ed together! */
gpio_init.Pin = GPIO_PIN_11; gpio_init.Pin = GPIO_PIN_11;
@ -81,13 +111,20 @@ void usbdrv_gpio_init() {
// gpio_init.Alternate = 0; // gpio_init.Alternate = 0;
// HAL_GPIO_Init(GPIOA, &gpio_init); // USB VBUSSENSE // HAL_GPIO_Init(GPIOA, &gpio_init); // USB VBUSSENSE
#endif
} }
// --------------- // ---------------
#ifdef USB_HIGH_SPEED
#define USB_IRQn OTG_HS_IRQn
#else
#define USB_IRQn OTG_FS_IRQn
#endif
// initialize USB subsystem // initialize USB subsystem
void usbdrv_init() { void usbdrv_init() {
NVIC_DisableIRQ(OTG_FS_IRQn); HAL_NVIC_DisableIRQ(USB_IRQn);
usbdrv_init_global_state(); usbdrv_init_global_state();
usbdrv_gpio_init(); usbdrv_gpio_init();
@ -95,8 +132,8 @@ void usbdrv_init() {
usbdrv_initial_ep0_setup(); usbdrv_initial_ep0_setup();
usbdrv_power_and_connect(true); usbdrv_power_and_connect(true);
NVIC_SetPriority(OTG_FS_IRQn, 6); HAL_NVIC_SetPriority(USB_IRQn, 8, 0);
NVIC_EnableIRQ(OTG_FS_IRQn); HAL_NVIC_EnableIRQ(USB_IRQn);
} }
void usbdrv_reset() { void usbdrv_reset() {
@ -135,17 +172,30 @@ void usbdrv_init_global_state() {
// --------------- // ---------------
#if defined(USB_STM32H7) #ifdef USB_HIGH_SPEED
__weak void usbdrv_ulpi_init() {
return;
}
#endif
#if defined(USB_STM32H7) /*|| defined(USB_HIGH_SPEED)*/
#define TOCAL_VALUE (0x00) #define TOCAL_VALUE (0x00)
#define TRDT_VALUE (0x05) #define TRDT_VALUE (0x05)
#elif defined(USB_STM32F4) #elif defined(USB_STM32F4)
#if !defined(USB_HIGH_SPEED)
#define TOCAL_VALUE (0x07) #define TOCAL_VALUE (0x07)
#define TRDT_VALUE (0x06) #define TRDT_VALUE (0x06)
#else
#define TOCAL_VALUE (0x07)
#define TRDT_VALUE (0x09)
#endif
#endif #endif
// --------------- // ---------------
#define USB_LINESPEED_FULL_SPEED (0b11) #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() {
@ -154,9 +204,17 @@ void usbdrv_periph_init() {
WAIT_FOR_nBIT(PWR->CR3, PWR_CR3_USB33RDY); WAIT_FOR_nBIT(PWR->CR3, PWR_CR3_USB33RDY);
#endif #endif
__HAL_RCC_USB_OTG_FS_CLK_ENABLE(); // enable clock on USB peripheral #ifdef USB_STM32F4
HAL_Delay(1000); #ifdef USB_HIGH_SPEED
__HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable HS USB peripheral
__HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); // also enable ULPI module clock
#else
__HAL_RCC_USB_OTG_FS_CLK_ENABLE(); // enable FS USB peripheral
#endif
#endif
// 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();
@ -167,28 +225,60 @@ void usbdrv_periph_init() {
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset USB core SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset USB core
WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST);
#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
WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST);
usbdrv_ulpi_init(); // initialize PHY
#endif #endif
#endif
(uint32_t *)(((uint32_t)USBG) + 0x028), // DIEPTXF0
(uint32_t *)(((uint32_t)USBG) + 0x104), // DIEPTXF1
(uint32_t *)(((uint32_t)USBG) + 0x108), // DIEPTXF2
(uint32_t *)(((uint32_t)USBG) + 0x10C), // DIEPTXF3
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // power down the peripheral CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // power down the peripheral
CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); // mask all interrupts for now 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 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_TRDT, TRDT_VALUE); // set TRDT according to the RM
WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TOCAL, TOCAL_VALUE); // set TOCAL // WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TOCAL, TOCAL_VALUE); // set TOCAL
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FDMOD); // force Device mode 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) #if defined(USB_STM32H7)
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBDEN); // turn on VBUSSENSE CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBDEN); // turn on VBUSSENSE
SET_BIT(USBG->GOTGCTL, USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL); // force B-session SET_BIT(USBG->GOTGCTL, USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL); // force B-session
#elif defined(USB_STM32F4) #elif defined(USB_STM32F4)
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_VBUSASEN);
#endif #endif
// HAL_Delay(50); // it takes time to forcing Device mode takes effect // HAL_Delay(50); // it takes time to forcing Device mode takes effect
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) #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 WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED); // there's no other possible option
#endif
// allow specific interrupts // allow specific interrupts
uint32_t intmask = /*USB_OTG_GINTMSK_WUIM | // Wake up */ uint32_t intmask = /*USB_OTG_GINTMSK_WUIM | // Wake up */
@ -227,10 +317,14 @@ void usbdrv_periph_init() {
void usbdrv_power_and_connect(bool en) { void usbdrv_power_and_connect(bool en) {
if (en) { // ON if (en) { // ON
CLEAR_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS); CLEAR_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS);
#ifndef USB_HIGH_SPEED
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // actually, this is power UP SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // actually, this is power UP
} else { // OFF #endif
} else { // OFF
SET_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS); SET_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS);
#ifndef USB_HIGH_SPEED
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN);
#endif
} }
} }
@ -309,11 +403,18 @@ void usbdrv_fetch_endpoint_configuration(uint8_t config_index) {
#define USB_MIN_GROSS_TX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE) #define USB_MIN_GROSS_TX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE)
#if defined(USB_STM32F4) #if defined(USB_STM32F4)
#ifndef USB_HIGH_SPEED
#define USB_MIN_GROSS_RX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE + USB_RX_FIFO_SETUP_RESERVATION_DWORDS * 4) #define USB_MIN_GROSS_RX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE + USB_RX_FIFO_SETUP_RESERVATION_DWORDS * 4)
#else
#define USB_MIN_GROSS_RX_FIFO_SIZE (1024)
#endif
#elif defined(USB_STM32H7) #elif defined(USB_STM32H7)
#define USB_MIN_GROSS_RX_FIFO_SIZE (256) #define USB_MIN_GROSS_RX_FIFO_SIZE (256)
#endif #endif
#define USBDRV_ADDR_TABLE_STR_LEN (255)
static char usbdrv_addr_table[USBDRV_ADDR_TABLE_STR_LEN + 1];
// build FIFO (compute addresses) // build FIFO (compute addresses)
void usbdrv_build_fifo() { void usbdrv_build_fifo() {
// ---- OUT ---- // ---- OUT ----
@ -348,19 +449,28 @@ void usbdrv_build_fifo() {
next_fifo_addr += fifo_size; // advance next FIFO address next_fifo_addr += fifo_size; // advance next FIFO address
usbdrv_set_rx_fifo_size(fifo_size); // set Rx FIFO size in hardware usbdrv_set_rx_fifo_size(fifo_size); // set Rx FIFO size in hardware
uint32_t str_offset = SNPRINTF(usbdrv_addr_table, USBDRV_ADDR_TABLE_STR_LEN, "RX: 000-%03x (%u)\r\n", fifo_size - 1, fifo_size);
// ---- IN ---- // ---- IN ----
for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) { for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) {
USBDRV_EpConfig *cfg = &gs.ep_IN[i]; USBDRV_EpConfig *cfg = &gs.ep_IN[i];
if (cfg->is_configured) { if (cfg->is_configured) {
cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, 2 * cfg->max_packet_size)); // correct FIFO size if necessary cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, cfg->max_packet_size + 64)); // correct FIFO size if necessary
cfg->fifo_address = next_fifo_addr; // store FIFO address cfg->fifo_address = next_fifo_addr; // store FIFO address
cfg->zlp_next = false; cfg->zlp_next = false;
str_offset += SNPRINTF(usbdrv_addr_table + str_offset, USBDRV_ADDR_TABLE_STR_LEN - str_offset, "TX%u: %03x-%03x (%u)\r\n", i, next_fifo_addr, next_fifo_addr + cfg->fifo_size - 1, cfg->fifo_size);
// cfg->txp = false; // no transfer is in progress // cfg->txp = false; // no transfer is in progress
next_fifo_addr += cfg->fifo_size; // advance next address next_fifo_addr += cfg->fifo_size; // advance next address
} }
} }
} }
const char * usbdrv_get_fifo_addr_table() {
return usbdrv_addr_table;
}
// create an initial setup for EP0 in both directions // create an initial setup for EP0 in both directions
void usbdrv_initial_ep0_setup() { void usbdrv_initial_ep0_setup() {
// setup EP0 OUT and IN // setup EP0 OUT and IN
@ -389,6 +499,7 @@ static uint32_t *USB_pDIEPTXF[4] = {
(uint32_t *)(((uint32_t)USBG) + 0x104), // DIEPTXF1 (uint32_t *)(((uint32_t)USBG) + 0x104), // DIEPTXF1
(uint32_t *)(((uint32_t)USBG) + 0x108), // DIEPTXF2 (uint32_t *)(((uint32_t)USBG) + 0x108), // DIEPTXF2
(uint32_t *)(((uint32_t)USBG) + 0x10C), // DIEPTXF3 (uint32_t *)(((uint32_t)USBG) + 0x10C), // DIEPTXF3
// TODO: HS USB controller has more endpoints
}; };
// configure USB endpoint // configure USB endpoint
@ -433,12 +544,12 @@ void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *c
// program FIFO corresponding FIFO number // program FIFO corresponding FIFO number
WRITE_FIELD(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_TXFNUM, ep); WRITE_FIELD(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_TXFNUM, ep);
// store Tx FIFO size (both fields are WORD units, NOT bytes, this RM is missing this information!) // store Tx FIFO size (both fields are WORD units, NOT bytes, RM is missing this information!)
uint32_t tx_fifo_config = ((cfg->fifo_size >> 2) << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (cfg->fifo_address >> 2); // combine size in DWORDs and address uint32_t tx_fifo_config = ((cfg->fifo_size >> 2) << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (cfg->fifo_address >> 2); // combine size in DWORDs and address
*(USB_pDIEPTXF[ep]) = tx_fifo_config; // save *(USB_pDIEPTXF[ep]) = tx_fifo_config; // save
// enable interrupt // enable interrupt
SET_BIT(USBD->DAINTMSK, 1 << ep); // SET_BIT(USBD->DAINTMSK, 1 << ep);
// NAK processing // NAK processing
if (cfg->responding_NAK) { if (cfg->responding_NAK) {
@ -601,9 +712,12 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
// enable endpoint and cancel responding NAK // enable endpoint and cancel responding NAK
SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK); SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK);
// enable endpoint interrupts
SET_BIT(USBD->DAINTMSK, 1 << ep);
} }
// turn interrupt generation on only, if this is NOT the last FIFO write considering the current transfer // turn on interrupt generation only, if this is NOT the last FIFO write considering the current transfer
if (len > writeSize) { if (len > writeSize) {
USBD->DIEPEMPMSK |= ((uint32_t)(1 << ep)); USBD->DIEPEMPMSK |= ((uint32_t)(1 << ep));
} }
@ -611,6 +725,8 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
// disable ALL USB interrupts to prevent access to specific registers (see errata) // disable ALL USB interrupts to prevent access to specific registers (see errata)
CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT);
// WAIT_FOR_nBIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TXFE);
// https://github.com/iliasam/STM32F4_USB_MICROPHONE/blob/master/Libraries/STM32_USB_OTG_Driver/src/usb_dcd_int.c#L655 // https://github.com/iliasam/STM32F4_USB_MICROPHONE/blob/master/Libraries/STM32_USB_OTG_Driver/src/usb_dcd_int.c#L655
// https://github.com/iliasam/STM32F4_USB_MICROPHONE/blob/master/Libraries/STM32_USB_OTG_Driver/src/usb_core.c#L168 // https://github.com/iliasam/STM32F4_USB_MICROPHONE/blob/master/Libraries/STM32_USB_OTG_Driver/src/usb_core.c#L168
@ -667,6 +783,15 @@ void usbdrv_autoarm_OUT_endpoint(uint8_t ep) {
gs.ep_OUT[ep].autoarm = true; gs.ep_OUT[ep].autoarm = true;
} }
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en) {
uint32_t mask = 1 << (ep + ((dir == USB_OUT) ? USB_OTG_DAINTMSK_OEPM_Pos : 0));
if (en) {
SET_BIT(USBD->DAINTMSK, mask);
} else {
CLEAR_BIT(USBD->DAINTMSK, mask);
}
}
// ---------------- // ----------------
void usbdrv_set_address(uint8_t addr) { void usbdrv_set_address(uint8_t addr) {
@ -772,7 +897,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
// SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt // SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
} else { // not EP0 } else { // not EP0
if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) { // TODO maybe the if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) { // TODO: "maybe the"????
USBDRV_CallbackCompound cbcpd; USBDRV_CallbackCompound cbcpd;
cbcpd.ep = evt_data.rx.ep_num; cbcpd.ep = evt_data.rx.ep_num;
cbcpd.dir = USB_OUT; cbcpd.dir = USB_OUT;
@ -817,7 +942,8 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
for (uint8_t ep = 0; ep < USB_NUM_OF_ENDPOINTS; ep++) { for (uint8_t ep = 0; ep < USB_NUM_OF_ENDPOINTS; ep++) {
cbcpd.ep = ep; cbcpd.ep = ep;
if (gs.ep_IN[ep].is_configured) { // if the endpoint is running bool ep_on = USBD->DAINTMSK & (1 << ep); // decide if this endpoint is currently enable for transmission based on its endpoint mask
if (gs.ep_IN[ep].is_configured && ep_on) { // if the endpoint is running
if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done
SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC); SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC);
USBMSG("TO\n"); USBMSG("TO\n");
@ -845,14 +971,24 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
cbcpd.code = USB_CBC_IN_DONE; cbcpd.code = USB_CBC_IN_DONE;
usbcore_process_nonsetup_event(&cbcpd); usbcore_process_nonsetup_event(&cbcpd);
} }
} else if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt } else if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt
SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE); SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE);
// MSG("E %u\n", ep);
// USBMSG("IN FIFOEMPTY [%d]\n", ep); // USBMSG("IN FIFOEMPTY [%d]\n", ep);
// transfer finished // transfer finished
// gs.ep_IN[ep].txp = false; // gs.ep_IN[ep].txp = false;
// if (!gs.ep_IN[ep].) {
//}
// disable endpoint interrupt
usbdrv_enable_endpoint_interrupt(ep, USB_IN, false);
cbcpd.code = USB_CBC_IN_FIFOEMPTY; cbcpd.code = USB_CBC_IN_FIFOEMPTY;
usbcore_process_nonsetup_event(&cbcpd); usbcore_process_nonsetup_event(&cbcpd);
} }
@ -890,7 +1026,12 @@ bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir) {
#define PROCESS_EVENT(evt, data) usbdrv_process_event((evt), (data)) #define PROCESS_EVENT(evt, data) usbdrv_process_event((evt), (data))
#endif #endif
void OTG_FS_IRQHandler() { #ifdef USB_HIGH_SPEED
void OTG_HS_IRQHandler()
#else
void OTG_FS_IRQHandler()
#endif
{
uint32_t ints = USBG->GINTSTS; uint32_t ints = USBG->GINTSTS;

View File

@ -7,9 +7,13 @@
// #define USBDBGMSG // #define USBDBGMSG
#define USB_NUM_OF_ENDPOINTS (4) #define USB_NUM_OF_ENDPOINTS (4) // FIXME: this is module-dependend
// non isochronous transfers
#define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64) #define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64)
#define USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS (512)
// isochronous transfers
#define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023) #define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023)
#define USB_MIN_EP_FIFO_SIZE (64) #define USB_MIN_EP_FIFO_SIZE (64)
@ -135,6 +139,7 @@ void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConf
void usbdrv_clear_endpoint_config(); // clear endpoint config void usbdrv_clear_endpoint_config(); // clear endpoint config
void usbdrv_apply_endpoint_config(); // apply preloaded endpoint configuration void usbdrv_apply_endpoint_config(); // apply preloaded endpoint configuration
void usbdrv_build_fifo(); // build FIFO (compute addresses) void usbdrv_build_fifo(); // build FIFO (compute addresses)
const char *usbdrv_get_fifo_addr_table(); // get FIFO address table
void usbdrv_fetch_endpoint_configuration(uint8_t config_index); // fetch endpoint configuration from descriptor dump void usbdrv_fetch_endpoint_configuration(uint8_t config_index); // fetch endpoint configuration from descriptor dump
void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint
@ -151,10 +156,10 @@ void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data); // see what's on to
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO
#define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0) #define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0)
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint) uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint)
void usbdrv_autoarm_OUT_endpoint(uint8_t ep); // automatically re-arm OUT endpoint at the and of the current OUT transfer void usbdrv_autoarm_OUT_endpoint(uint8_t ep); // automatically re-arm OUT endpoint at the and of the current OUT transfer
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en); // enable/disable endpoint interrupt signaling
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag
void usbdrv_set_address(uint8_t addr); // set device address void usbdrv_set_address(uint8_t addr); // set device address