Merge branch 'master' of epagris.com:epagris/flatUSB
This commit is contained in:
commit
8ca9852915
@ -1,13 +1,31 @@
|
||||
target_sources(
|
||||
${CMAKE_PROJECT_NAME}
|
||||
PUBLIC
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
class/cdc.c
|
||||
class/cdc.h
|
||||
class/eem.c
|
||||
class/eem.h
|
||||
set(FLATUSB_TARGET flatUSB)
|
||||
|
||||
CMakeLists.txt
|
||||
if (FLATUSB_TARGET_TAG)
|
||||
set(FLATUSB_TARGET "${FLATUSB_TARGET}_${FLATUSB_TARGET_TAG}")
|
||||
message("Custom flatUSB target: ${FLATUSB_TARGET}")
|
||||
endif()
|
||||
|
||||
set(FLATUSB_CLASSES_SRC "")
|
||||
if ("CDC_ACM" IN_LIST FLATUSB_CLASSES)
|
||||
list(APPEND FLATUSB_CLASSES_SRC
|
||||
class/cdc.c
|
||||
class/cdc.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if ("CDC_EEM" IN_LIST FLATUSB_CLASSES)
|
||||
list(APPEND FLATUSB_CLASSES_SRC
|
||||
class/eem.c
|
||||
class/eem.h
|
||||
)
|
||||
endif()
|
||||
|
||||
message("flatUSB classes selected: ${FLATUSB_CLASSES}")
|
||||
|
||||
set(FLATUSB_SRC
|
||||
${FLATUSB_CLASSES_SRC}
|
||||
|
||||
desc/usb_desc.c
|
||||
desc/usb_desc.h
|
||||
@ -25,3 +43,8 @@ target_sources(
|
||||
# utils/gen_queue.c
|
||||
# utils/gen_queue.h
|
||||
)
|
||||
|
||||
add_library(${FLATUSB_TARGET} STATIC ${FLATUSB_SRC})
|
||||
target_include_directories(${FLATUSB_TARGET} PRIVATE ${FLATUSB_INCLUDES})
|
||||
target_compile_options(${FLATUSB_TARGET} PRIVATE ${FLATUSB_CPU_PARAMS})
|
||||
target_compile_definitions(${FLATUSB_TARGET} PRIVATE ${FLATUSB_COMPILE_DEFS})
|
||||
|
@ -1,10 +1,23 @@
|
||||
#ifndef CORE_USB_USB_COMMON_DEFS
|
||||
#define CORE_USB_USB_COMMON_DEFS
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
#if defined(STM32H745xx) || defined(STM32H743xx)
|
||||
#include <stm32h7xx.h>
|
||||
#include <stm32h7xx_hal.h>
|
||||
#define USB_STM32H7
|
||||
#elif defined(STM32F407xx) || defined(STM32F401xC)
|
||||
#include <stm32f4xx.h>
|
||||
#include <stm32f4xx_hal.h>
|
||||
#define USB_STM32F4
|
||||
|
||||
#ifdef USB_HIGH_SPEED
|
||||
#define USBG (USB_OTG_HS)
|
||||
#else
|
||||
#define USBG (USB_OTG_FS)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#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 USBOUTEP ((USB_OTG_OUTEndpointTypeDef *) ((uint32_t)(USBG) + (uint32_t)(USB_OTG_OUT_ENDPOINT_BASE)))
|
||||
|
108
usb_driver.c
108
usb_driver.c
@ -42,6 +42,12 @@ static const char *FIFO_STATUS_STR[6] = {
|
||||
|
||||
// ---------------
|
||||
|
||||
#if defined(USB_STM32H7)
|
||||
#define USB_GPIO_AF (GPIO_AF10_OTG2_FS)
|
||||
#elif defined(USB_STM32F4)
|
||||
#define USB_GPIO_AF (GPIO_AF10_OTG_FS)
|
||||
#endif
|
||||
|
||||
// USB pin low level, early peripheral initialization
|
||||
// PA12: D+, PA11: D-
|
||||
void usbdrv_gpio_init() {
|
||||
@ -50,18 +56,23 @@ void usbdrv_gpio_init() {
|
||||
|
||||
GPIO_InitTypeDef gpio_init;
|
||||
gpio_init.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_init.Pin = GPIO_PIN_12;
|
||||
gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
gpio_init.Pull = GPIO_NOPULL;
|
||||
gpio_init.Alternate = GPIO_AF10_OTG_FS;
|
||||
gpio_init.Alternate = USB_GPIO_AF;
|
||||
|
||||
/* Pin initializations cannot be OR-ed together! */
|
||||
|
||||
gpio_init.Pin = GPIO_PIN_11;
|
||||
HAL_GPIO_Init(GPIOA, &gpio_init); // USB D-
|
||||
|
||||
gpio_init.Pin = GPIO_PIN_12;
|
||||
HAL_GPIO_Init(GPIOA, &gpio_init); // USB D+
|
||||
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
|
||||
|
||||
gpio_init.Pin = GPIO_PIN_11;
|
||||
gpio_init.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOA, &gpio_init); // USB D-
|
||||
// gpio_init.Pin = GPIO_PIN_11;
|
||||
// gpio_init.Pull = GPIO_NOPULL;
|
||||
// HAL_GPIO_Init(GPIOA, &gpio_init); // USB D-
|
||||
|
||||
// gpio_init.Mode = GPIO_MODE_INPUT;
|
||||
// gpio_init.Pin = GPIO_PIN_9;
|
||||
@ -121,24 +132,55 @@ void usbdrv_init_global_state() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(USB_STM32H7)
|
||||
#define TOCAL_VALUE (0x00)
|
||||
#define TRDT_VALUE (0x05)
|
||||
#elif defined(USB_STM32F4)
|
||||
#define TOCAL_VALUE (0x07)
|
||||
#define TRDT_VALUE (0x06)
|
||||
#endif
|
||||
|
||||
// ---------------
|
||||
|
||||
#define USB_LINESPEED_FULL_SPEED (0b11)
|
||||
|
||||
// initialize USB peripheral
|
||||
void usbdrv_periph_init() {
|
||||
#if defined(USB_STM32H7)
|
||||
HAL_PWREx_EnableUSBVoltageDetector();
|
||||
WAIT_FOR_nBIT(PWR->CR3, PWR_CR3_USB33RDY);
|
||||
#endif
|
||||
|
||||
__HAL_RCC_USB_OTG_FS_CLK_ENABLE(); // enable clock on USB peripheral
|
||||
|
||||
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
|
||||
|
||||
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset USB core
|
||||
WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST);
|
||||
#endif
|
||||
|
||||
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->GUSBCFG, USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP); // disable HNP and SRP
|
||||
WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TRDT, 0x06); // set TRDT according to the RM
|
||||
WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TOCAL, 0x07); // set TOCAL
|
||||
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
|
||||
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FDMOD); // force Device mode
|
||||
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE
|
||||
|
||||
#if defined(USB_STM32H7)
|
||||
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
|
||||
#elif defined(USB_STM32F4)
|
||||
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE
|
||||
#endif
|
||||
|
||||
|
||||
// HAL_Delay(50); // it takes time to forcing Device mode takes effect
|
||||
|
||||
@ -262,18 +304,43 @@ void usbdrv_fetch_endpoint_configuration(uint8_t config_index) {
|
||||
#define USB_FIFO_MARGIN (8)
|
||||
#define USB_RX_FIFO_SETUP_RESERVATION_DWORDS (10)
|
||||
#define USB_MIN_GROSS_TX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE)
|
||||
|
||||
#if defined(USB_STM32F4)
|
||||
#define USB_MIN_GROSS_RX_FIFO_SIZE (2 * USB_MIN_EP_FIFO_SIZE + USB_RX_FIFO_SETUP_RESERVATION_DWORDS * 4)
|
||||
#elif defined(USB_STM32H7)
|
||||
#define USB_MIN_GROSS_RX_FIFO_SIZE (256)
|
||||
#endif
|
||||
|
||||
// build FIFO (compute addresses)
|
||||
void usbdrv_build_fifo() {
|
||||
// ---- OUT ----
|
||||
uint16_t fifo_size = USB_MIN_GROSS_RX_FIFO_SIZE; // at least this large
|
||||
uint16_t next_fifo_addr = 0x00; // Rx FIFO begins at address zero
|
||||
for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) { // look for greatest FIFO size
|
||||
if (gs.ep_OUT[i].is_configured) {
|
||||
fifo_size = CEIL4(MAX(fifo_size, gs.ep_OUT[i].max_packet_size)); // compare and replace if necessary
|
||||
uint16_t largest_packet_size = 0; // largest packet size
|
||||
uint16_t control_ep_count = 0; // number of control endpoints
|
||||
uint16_t out_ep_count = 0; // count of OUT pipes
|
||||
for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) { // gather config information
|
||||
// look for largest packet size
|
||||
if (gs.ep_OUT[i].is_configured) { // examine OUT EPs
|
||||
largest_packet_size = MAX(largest_packet_size, gs.ep_OUT[i].max_packet_size);
|
||||
out_ep_count++;
|
||||
}
|
||||
if (gs.ep_IN[i].is_configured) { // examine IN EPs
|
||||
largest_packet_size = MAX(largest_packet_size, gs.ep_IN[i].max_packet_size);
|
||||
}
|
||||
|
||||
// count control endpoints
|
||||
if (((gs.ep_OUT[i].is_configured) && (gs.ep_OUT[i].type == UT_Control)) ||
|
||||
((gs.ep_IN[i].is_configured) && (gs.ep_IN[i].type == UT_Control))) {
|
||||
control_ep_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// RX FIFO size calculation expression from the RM
|
||||
uint16_t fifo_size_dwords = (5 * control_ep_count + 8) + (CEILDIV4(largest_packet_size) + 1) + (2 * out_ep_count) + 1; // calculate RX FIFO size in DWORDS
|
||||
uint16_t fifo_size = fifo_size_dwords * 4; // calculate RX FIFO size in bytes
|
||||
fifo_size = CEIL4(MAX(fifo_size, USB_MIN_GROSS_RX_FIFO_SIZE)); // RX FIFO should be at least this large
|
||||
|
||||
// fifo_size *= 2; // TODO:
|
||||
gs.rx_fifo_size = fifo_size; // save Rx FIFO size for later
|
||||
next_fifo_addr += fifo_size; // advance next FIFO address
|
||||
usbdrv_set_rx_fifo_size(fifo_size); // set Rx FIFO size in hardware
|
||||
@ -315,10 +382,11 @@ void usbdrv_initial_ep0_setup() {
|
||||
|
||||
// addresses of specific DIEPTXF registers, addresses from the RM
|
||||
static uint32_t *USB_pDIEPTXF[4] = {
|
||||
(uint32_t *)(USB_OTG_FS_PERIPH_BASE + 0x028), // DIEPTXF0
|
||||
(uint32_t *)(USB_OTG_FS_PERIPH_BASE + 0x104), // DIEPTXF1
|
||||
(uint32_t *)(USB_OTG_FS_PERIPH_BASE + 0x108), // DIEPTXF2
|
||||
(uint32_t *)(USB_OTG_FS_PERIPH_BASE + 0x10C), // DIEPTXF3
|
||||
(uint32_t *)(USBG + 0x028), // DIEPTXF0
|
||||
(uint32_t *)(USBG + 0x104), // DIEPTXF1
|
||||
(uint32_t *)(USBG + 0x108), // DIEPTXF2
|
||||
(uint32_t *)(USBG + 0x10C), // DIEPTXF3
|
||||
// TODO: HS USB controller has more endpoints
|
||||
};
|
||||
|
||||
// configure USB endpoint
|
||||
@ -573,7 +641,7 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
|
||||
// arm OUT endpoint
|
||||
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size) {
|
||||
// arm endpoint only if it was not armed before
|
||||
// arm endpoint only if it was not armed before OR if it's the EP0 OUT which is always enabled, but responds NAK after a successful transfer
|
||||
if (READ_BIT(USBOUTEP[ep].DOEPCTL, USB_OTG_DOEPCTL_EPENA)) {
|
||||
return 0;
|
||||
}
|
||||
@ -582,7 +650,11 @@ uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size) {
|
||||
size = MIN(gs.ep_OUT[ep].max_packet_size, size);
|
||||
|
||||
// write registers
|
||||
USBOUTEP[ep].DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT | size; // program DIEPTSIZ with maximum (expected) transfer length and set PCKTCNT to make ready for reception
|
||||
uint32_t doeptsiz = USBOUTEP[ep].DOEPTSIZ;
|
||||
doeptsiz &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); // clear XFERSIZ bits
|
||||
doeptsiz |= USB_OTG_DOEPTSIZ_PKTCNT | size; // program DIEPTSIZ with maximum (expected) transfer length and set PCKTCNT to make ready for reception
|
||||
USBOUTEP[ep].DOEPTSIZ = doeptsiz; // write value to the actual register
|
||||
|
||||
SET_BIT(USBOUTEP[ep].DOEPCTL, USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK); // enable endpoint and clear NAK
|
||||
|
||||
// return with armed size
|
||||
|
Loading…
x
Reference in New Issue
Block a user