From fc10ff2f056684eb570b74f51e10bf21adbf5805 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 10 Sep 2019 14:10:33 -0400 Subject: [PATCH 01/94] Add pyboard (v1.1) BSP. cdc_msc_hid example tested. --- hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld | 189 +++++++++ hw/bsp/pyboardv11/board.mk | 50 +++ hw/bsp/pyboardv11/pyboardv11.c | 200 +++++++++ hw/bsp/pyboardv11/stm32f4xx_hal_conf.h | 489 +++++++++++++++++++++++ 4 files changed, 928 insertions(+) create mode 100644 hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld create mode 100644 hw/bsp/pyboardv11/board.mk create mode 100644 hw/bsp/pyboardv11/pyboardv11.c create mode 100644 hw/bsp/pyboardv11/stm32f4xx_hal_conf.h diff --git a/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld new file mode 100644 index 000000000..57ef61e26 --- /dev/null +++ b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld @@ -0,0 +1,189 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F405RGTx Device with +** 1024KByte FLASH, 128KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk new file mode 100644 index 000000000..9e328072b --- /dev/null +++ b/hw/bsp/pyboardv11/board.mk @@ -0,0 +1,50 @@ +CFLAGS += \ + -DHSE_VALUE=120000000 \ + -DSTM32F405xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F4 + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = synopsys + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = stm32f407vg +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c new file mode 100644 index 000000000..85c0eb58f --- /dev/null +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32f4xx.h" +#include "stm32f4xx_hal_conf.h" + +// Blue LED is chosen because the other LEDs are connected to ST-LINK lines. +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_4 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOB +#define BUTTON_PIN GPIO_PIN_3 +#define BUTTON_STATE_ACTIVE 1 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 168000000 + * HCLK(Hz) = 168000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 4 + * APB2 Prescaler = 2 + * HSE Frequency(Hz) = 12000000 + * PLL_M = 12 + * PLL_N = 336 + * PLL_P = 2 + * PLL_Q = 7 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + /* Enable Power Control clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 336; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+/D- + __HAL_RCC_GPIOB_CLK_ENABLE(); // button, LED + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOD_CLK_ENABLE(); + + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // Enable USB OTG clock + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + // USB Pin Init + // PA9- VUSB, PA10- ID, PA11- DM, PA12- DP + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure DM DP Pins */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* This for ID line debug */ + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h new file mode 100644 index 000000000..dbef20e0a --- /dev/null +++ b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2019 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)12000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* Copied over manually- STM32Cube didn't generate these for some reason. */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 986beda9ebc5f772a6c172ad8b2f3193506b4d23 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 11:22:44 +0700 Subject: [PATCH 02/94] adding stm32l4 support, board test run with stm32l476disco, usb doens't work yet --- hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld | 183 +++++++++ hw/bsp/stm32l476disco/board.mk | 53 +++ hw/bsp/stm32l476disco/stm32l476disco.c | 217 +++++++++++ hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h | 380 +++++++++++++++++++ hw/mcu/st/README.md | 52 --- src/portable/st/synopsys/dcd_synopsys.c | 30 +- src/tusb_option.h | 10 +- 7 files changed, 863 insertions(+), 62 deletions(-) create mode 100644 hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld create mode 100644 hw/bsp/stm32l476disco/board.mk create mode 100644 hw/bsp/stm32l476disco/stm32l476disco.c create mode 100644 hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h delete mode 100644 hw/mcu/st/README.md diff --git a/hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld b/hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld new file mode 100644 index 000000000..98f468ac0 --- /dev/null +++ b/hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld @@ -0,0 +1,183 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32L476VGTx Device with +** 1024KByte FLASH, 96KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20018000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x500; /* required amount of heap */ +_Min_Stack_Size = 0x1000; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(8); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(8); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(8); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(8); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(8); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(8); + } >FLASH + + .ARM.extab : + { + . = ALIGN(8); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(8); + } >FLASH + .ARM : { + . = ALIGN(8); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(8); + } >FLASH + + .preinit_array : + { + . = ALIGN(8); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(8); + } >FLASH + + .init_array : + { + . = ALIGN(8); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(8); + } >FLASH + .fini_array : + { + . = ALIGN(8); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(8); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(8); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(8); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32l476disco/board.mk new file mode 100644 index 000000000..c987fea64 --- /dev/null +++ b/hw/bsp/stm32l476disco/board.mk @@ -0,0 +1,53 @@ +CFLAGS += \ + -DHSE_VALUE=8000000 \ + -DSTM32L476xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32L4 + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L4xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L4xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/$(BOARD)/STM32L476VGTx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32l4xx.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l476xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = synopsys + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = stm32l476vg +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/stm32l476disco/stm32l476disco.c b/hw/bsp/stm32l476disco/stm32l476disco.c new file mode 100644 index 000000000..ab8f13226 --- /dev/null +++ b/hw/bsp/stm32l476disco/stm32l476disco.c @@ -0,0 +1,217 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32l4xx.h" +#include "stm32l4xx_hal_conf.h" + +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_2 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PIN_0 +#define BUTTON_STATE_ACTIVE 1 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * + * If define USB_USE_LSE_MSI_CLOCK enabled: + * System Clock source = PLL (MSI) + * SYSCLK(Hz) = 80000000 + * HCLK(Hz) = 80000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 1 + * APB2 Prescaler = 2 + * MSI Frequency(Hz) = 4800000 + * LSE Frequency(Hz) = 32768 + * PLL_M = 6 + * PLL_N = 40 + * PLL_P = 7 + * PLL_Q = 4 + * PLL_R = 4 + * Flash Latency(WS) = 4 + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + + /* Enable the LSE Oscilator */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Enable the CSS interrupt in case LSE signal is corrupted or not present */ + HAL_RCCEx_DisableLSECSS(); + + /* Enable MSI Oscillator and activate PLL with MSI as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + RCC_OscInitStruct.PLL.PLLM = 6; + RCC_OscInitStruct.PLL.PLLN = 40; + RCC_OscInitStruct.PLL.PLLP = 7; + RCC_OscInitStruct.PLL.PLLQ = 4; + RCC_OscInitStruct.PLL.PLLR = 4; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Enable MSI Auto-calibration through LSE */ + HAL_RCCEx_EnableMSIPLLMode(); + + /* Select MSI output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_MSI, RCC_MCODIV_1);//RCC_MCO1SOURCE_SYSCLK + + /* Enable Power Clock*/ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* Enable USB power on Pwrctrl CR2 register */ + HAL_PWREx_EnableVddUSB(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOB_CLK_ENABLE(); + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // USB + /* Configure DM DP Pins */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* This for ID line */ + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* Enable USB FS Clock */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h b/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h new file mode 100644 index 000000000..dce4008d0 --- /dev/null +++ b/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h @@ -0,0 +1,380 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32l4xx_hal_conf.h. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_CONF_H +#define __STM32L4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +/* #define HAL_COMP_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_FIREWALL_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +/* #define HAL_NAND_MODULE_ENABLED */ +#define HAL_NOR_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +//#define HAL_I2C_MODULE_ENABLED +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +//#define HAL_LCD_MODULE_ENABLED +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_OPAMP_MODULE_ENABLED */ +//#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +/* #define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RCC_MODULE_ENABLED +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +//#define HAL_SAI_MODULE_ENABLED +//#define HAL_SD_MODULE_ENABLED +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_SWPMI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_TSC_MODULE_ENABLED */ +//#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ + + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for SAI1 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) + #define EXTERNAL_SAI1_CLOCK_VALUE 48000U /*!< Value of the SAI1 External clock source in Hz*/ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +/** + * @brief External clock source for SAI2 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) + #define EXTERNAL_SAI2_CLOCK_VALUE 48000U /*!< Value of the SAI2 External clock source in Hz*/ +#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32l4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32l4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32l4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32l4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32l4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32l4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32l4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "Legacy/stm32l4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32l4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32l4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32l4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32l4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FIREWALL_MODULE_ENABLED + #include "stm32l4xx_hal_firewall.h" +#endif /* HAL_FIREWALL_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32l4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32l4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32l4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32l4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32l4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32l4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32l4xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32l4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32l4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32l4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32l4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32l4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32l4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32l4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32l4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32l4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32l4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SWPMI_MODULE_ENABLED + #include "stm32l4xx_hal_swpmi.h" +#endif /* HAL_SWPMI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32l4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32l4xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32l4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32l4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32l4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32l4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32l4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32l4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32l4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hw/mcu/st/README.md b/hw/mcu/st/README.md deleted file mode 100644 index c1313d8d7..000000000 --- a/hw/mcu/st/README.md +++ /dev/null @@ -1,52 +0,0 @@ -This README describes the layout of system files and headers for -microcontrollers supported by tinyusb from the vendor [ST](www.st.com). - -The CMSIS by ARM is an attempt to unify how system initialization and headers -for ARM microcontrollers are handled across vendors. A vendor is expected to -provide a number of files, including vendor-specific device headers, -vendor-specific system init code (in C), vendor-specific startup code (coded in -assembly _and_ meant to make writing C interrupt handlers easy), and ARM -architecture-specific headers. In practice, it's actually difficult to find all -these files in one place. - -* stm32cube generates a self-contained application. All the relevant headers, - system init, and startup code are under `Drivers/CMSIS`. The linker script is - stored at the root of your project, _along_ with a copy of the startup code. - Relative to `Drivers/CMSIS`: - * Device header files are stored under `Device/ST/$family/Include`. - * Arm-provided CMSIS headers are stored under `Include`. - * The portable C portion of the startup code, called `system_$family.c`, is - stored under `Device/ST/$family/Source/Templates`. This "system init" code - is required by CMSIS. - * The assembly portion of the startup code, called `startup_$device.c`, is - stored under `Device\ST\STM32F4xx\Source\Templates\gcc`. - -* Micropython maintains [a repo](https://github.com/micropython/stm32lib) - with _only_ the device header files. We use that - repo and provide the remaining files ourselves. - * Micropython keeps the linker script and assembly portion of the startup - code under the - [boards](https://github.com/micropython/micropython/tree/master/ports/stm32/boards) - directory in the stm32 port (but the code is board agnostic). - * Micropython also embeds its own - [copy](https://github.com/micropython/micropython/tree/master/lib/cmsis/inc) - of CMSIS headers for all ARM targets into the repo. - * Micropython indeed _does_ use their own custom C startup code (CMSIS system - init) for - [stm32](https://github.com/micropython/micropython/blob/master/ports/stm32/system_stm32.c) - targets. It is - [missing](https://github.com/micropython/micropython/commit/fdbc22e4d27b9d1c686647c9c67a32206f7bc83a) - the `SystemCoreClockUpdate` function. - -* TinyUSB uses Micropython's [stm32lib](stm32lib) as a submodule to provide - device headers. The remaining system files can be found in the following - directories: - * C system init code is in the [system-init](system-init) directory. - * Assembly startup code is in the [startup](startup) directory. Each family - gets its own subdirectory under startup (e.g. [stm32f4](startup/stm32f4)). - * ARM-provided headers are stored in the [cmsis](cmsis) directory. - * The linker script for the STM32F4-DISCOVERY board demo is supplied as - part of TinyUSB's - [Board Support Packages](../../bsp/stm32f407disco/STM32F407VGTx_FLASH.ld). - The above files were extracted from a dummy stm32cube project in February - 2019. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 71c691223..b0e7e04bd 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -27,10 +27,20 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7) +#define STM32L4_SYNOPSYS ( \ + defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) \ +) + +#if TUSB_OPT_DEVICE_ENABLED && \ + ( CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && STM32L4_SYNOPSYS) \ + ) // TODO Support OTG_HS // EP_MAX : Max number of bi-directional endpoints including EP0 @@ -52,6 +62,10 @@ #include "stm32f7xx.h" #define EP_MAX 6 #define EP_FIFO_SIZE 1280 +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" + #define EP_MAX 6 + #define EP_FIFO_SIZE 1280 #else #error "Unsupported MCUs" #endif @@ -61,10 +75,10 @@ /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ -#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE) -#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE) -#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE) -#define FIFO_BASE(_x) (volatile uint32_t *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE) +#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE) +#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE) +#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE) +#define FIFO_BASE(_x) ((volatile uint32_t *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; static uint8_t _setup_offs; // We store up to 3 setup packets. diff --git a/src/tusb_option.h b/src/tusb_option.h index eccb4245c..9aacb558f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -35,6 +35,8 @@ /** \defgroup group_mcu Supported MCU * \ref CFG_TUSB_MCU must be defined to one of these * @{ */ + +// LPC #define OPT_MCU_LPC11UXX 1 ///< NXP LPC11Uxx #define OPT_MCU_LPC13XX 3 ///< NXP LPC13xx #define OPT_MCU_LPC175X_6X 4 ///< NXP LPC175x, LPC176x @@ -46,12 +48,14 @@ #define OPT_MCU_LPC54XXX 10 ///< NXP LPC54xxx #define OPT_MCU_LPC55XX 11 ///< NXP LPC55xx +// NRF #define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series +// SAM #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 #define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 -// ST Synopsis OTG devices +// STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 #define OPT_MCU_STM32F1 301 ///< ST STM32F1 #define OPT_MCU_STM32F2 302 ///< ST STM32F2 @@ -59,7 +63,9 @@ #define OPT_MCU_STM32F4 304 ///< ST STM32F4 #define OPT_MCU_STM32F7 305 ///< ST STM32F7 #define OPT_MCU_STM32H7 306 ///< ST STM32H7 - +#define OPT_MCU_STM32L0 307 ///< ST STM32L0 +#define OPT_MCU_STM32L1 308 ///< ST STM32L1 +#define OPT_MCU_STM32L4 309 ///< ST STM32L4 /** @} */ From c3598f030158cf32f571a3c11b833a3a910d63c8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 13:03:11 +0700 Subject: [PATCH 03/94] fix #139, correct usbd request intepreting, Non-STD request to Interface must be forward to class driver --- src/device/usbd.c | 57 ++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index a6eda79de..53f0226bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -439,33 +439,44 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); - switch ( p_request->bRequest ) + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { - case TUSB_REQ_GET_INTERFACE: + switch ( p_request->bRequest ) { - // TODO not support alternate interface yet - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); + case TUSB_REQ_GET_INTERFACE: + { + // TODO not support alternate interface yet + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + } + break; + + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const alternate = (uint8_t) p_request->wValue; + + // TODO not support alternate interface yet + TU_ASSERT(alternate == 0); + tud_control_status(rhport, p_request); + } + break; + + default: + // forward to class driver: "STD request to Interface" + // GET HID REPORT DESCRIPTOR falls into this case + usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); + + // stall control endpoint if driver return false + TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + break; } - break; + }else + { + // forward to class driver: "non-STD request to Interface" + usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - case TUSB_REQ_SET_INTERFACE: - { - uint8_t alternate = (uint8_t) p_request->wValue; - - // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); - - tud_control_status(rhport, p_request); - } - break; - - default: - // forward to class driver - // stall control endpoint if driver return false - usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); - break; + // stall control endpoint if driver return false + TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); } } break; From 064adebbd0c6e35e6a18d5dda3deba232db2690d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 14:03:59 +0700 Subject: [PATCH 04/94] fix #152, potential memory issue --- src/device/usbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 53f0226bc..184702f1a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -435,8 +435,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_RCPT_INTERFACE: { uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const drvid = _usbd_dev.itf2drv[itf]; + TU_VERIFY(itf < TU_ARRAY_SZIE(_usbd_dev.itf2drv)); + uint8_t const drvid = _usbd_dev.itf2drv[itf]; TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) From a75d77417aa51a60a8f91f971fbbc01fdfeeefd7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:42:58 +0700 Subject: [PATCH 05/94] Update boards.md --- docs/boards.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index 96650b20b..de6328aa2 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -48,8 +48,8 @@ This code base already had supported for a handful of following boards - [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) - [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) - [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [Nucleo STM32F767zi](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [Nucleo H743zi](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From de386751b5a0e2823624c41a56b87d866314b838 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:43:46 +0700 Subject: [PATCH 06/94] Update boards.md --- docs/boards.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index de6328aa2..30b0eb958 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -41,15 +41,15 @@ This code base already had supported for a handful of following boards ### ST STM32 -- [STM32F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) -- [STM32F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) -- [STM32F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) -- [STM32F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) -- [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) -- [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) -- [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) +- [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) +- [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) +- [STM32 F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) +- [STM32 F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) +- [STM32 F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) +- [STM32 F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) +- [STM32 F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From ac8c343fef785c9aa19ba628f746e72774b9e8c8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 22:16:24 +0700 Subject: [PATCH 07/94] fix #154 forward all endpoint recipeint request to class driver fix typo remove magic number 0xff of driver id --- src/common/tusb_common.h | 2 +- src/device/usbd.c | 117 +++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 43 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 4f0105d13..57c6e2fcf 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ // Macros Helper //--------------------------------------------------------------------+ -#define TU_ARRAY_SZIE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define TU_MIN(_x, _y) ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( (_x) > (_y) ) ? (_x) : (_y) ) diff --git a/src/device/usbd.c b/src/device/usbd.c index 184702f1a..c92884334 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -61,6 +61,9 @@ typedef struct { static usbd_device_t _usbd_dev = { 0 }; +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xff }; + //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ @@ -144,7 +147,7 @@ static usbd_class_driver_t const usbd_class_drivers[] = #endif }; -enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SZIE(usbd_class_drivers) }; +enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) }; //--------------------------------------------------------------------+ // DCD Event @@ -213,8 +216,8 @@ static void usbd_reset(uint8_t rhport) { tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping + memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping usbd_control_reset(rhport); @@ -287,19 +290,19 @@ void tud_task (void) { // Invoke the class callback associated with the endpoint address uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); - _usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[dir], epnum); + _usbd_dev.ep_busy_map[ep_dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[ep_dir], epnum); - if ( 0 == tu_edpt_number(ep_addr) ) + if ( 0 == epnum ) { // control transfer DATA stage callback usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } else { - uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; + uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir]; TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); @@ -435,7 +438,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_RCPT_INTERFACE: { uint8_t const itf = tu_u16_low(p_request->wIndex); - TU_VERIFY(itf < TU_ARRAY_SZIE(_usbd_dev.itf2drv)); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); uint8_t const drvid = _usbd_dev.itf2drv[itf]; TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); @@ -465,18 +468,16 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const default: // forward to class driver: "STD request to Interface" // GET HID REPORT DESCRIPTOR falls into this case - usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - // stall control endpoint if driver return false + usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); break; } }else { // forward to class driver: "non-STD request to Interface" - usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - // stall control endpoint if driver return false + usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); } } @@ -484,37 +485,69 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const //------------- Endpoint Request -------------// case TUSB_REQ_RCPT_ENDPOINT: - // Non standard request is not supported - TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ); + { + uint8_t const ep_addr = tu_u16_low(p_request->wIndex); + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); - switch ( p_request->bRequest ) + TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); + + uint8_t const drv_id = _usbd_dev.ep2drv[ep_num][ep_dir]; + TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); + + // Some classes such as TMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request + // We will forward all request targeted endpoint to its class driver + // - For non-standard request: driver can ACK or Stall the request by return true/false + // - For standard request: usbd decide the ACK stage regardless of driver return value + bool ret; + + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { - case TUSB_REQ_GET_STATUS: - { - uint16_t status = usbd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; - tud_control_xfer(rhport, p_request, &status, 2); - } - break; - - case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); - } - tud_control_status(rhport, p_request); - break; - - case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); - } - tud_control_status(rhport, p_request); - break; - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; + // complete callback is also capable of stalling/acking the request + usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete); } + + // Invoke class driver first + ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + + // Then handle if it is standard request + if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + { + // force return true for standard request + ret = true; + + switch ( p_request->bRequest ) + { + case TUSB_REQ_GET_STATUS: + { + uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; + tud_control_xfer(rhport, p_request, &status, 2); + } + break; + + case TUSB_REQ_CLEAR_FEATURE: + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) + { + usbd_edpt_clear_stall(rhport, ep_addr); + } + tud_control_status(rhport, p_request); + break; + + case TUSB_REQ_SET_FEATURE: + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) + { + usbd_edpt_stall(rhport, ep_addr); + } + tud_control_status(rhport, p_request); + break; + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + return ret; + } break; // Unknown recipient @@ -560,7 +593,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); // Interface number must not be used already TODO alternate interface - TU_ASSERT( 0xff == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; uint16_t itf_len=0; From bb7f581b6d046c1c358fab70f3640d0312527804 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 20:28:26 -0400 Subject: [PATCH 08/94] TI compiler quirks, and le byte swapping functions. --- src/common/tusb_compiler.h | 85 +++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 09768ef88..ca294c20f 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -53,6 +53,9 @@ // for declaration of reserved field, make use of _TU_COUNTER_ #define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) +#define TU_LITTLE_ENDIAN (0x12u) +#define TU_BIG_ENDIAN (0x21u) + //--------------------------------------------------------------------+ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ @@ -67,20 +70,80 @@ // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define tu_htonl(u32) __builtin_bswap32(u32) - #define tu_ntohl(u32) __builtin_bswap32(u32) - - #define tu_htons(u16) __builtin_bswap16(u16) - #define tu_ntohs(u16) __builtin_bswap16(u16) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN #else - #define tu_htonl(u32) (u32) - #define tu_ntohl(u32) (u32) - - #define tu_htons(u16) (u16) - #define tu_ntohs(u16) (u16) + #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } + + #define TU_BSWAP16 + +#elif defined(__TI_COMPILER_VERSION__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_PREPACKED + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) + #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } #else - #error "Compiler attribute porting are required" + #error "Compiler attribute porting is required" +#endif + +#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) + #define tu_htonl(u32) tu_bswap32(u32) + #define tu_ntohl(u32) tu_bswap32(u32) + + #define tu_htons(u16) tu_bswap16(u16) + #define tu_ntohs(u16) tu_bswap16(u16) + + #define tu_htole16(x) (x) + #define tu_le16toh(x) (x) + + #define tu_htole32(x) (x) + #define tu_le32toh(x) (x) + +#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) + #define tu_htonl(u32) (x) + #define tu_ntohl(u32) (x) + + #define tu_htons(u16) (x) + #define tu_ntohs(u16) (x) + + #define tu_htole16(x) tu_bswap16(u32) + #define tu_le16toh(x) tu_bswap16(u32) + + #define tu_htole32(x) tu_bswap32(u32) + #define tu_le32toh(x) tu_bswap32(u32) + +#else + #error Byte order is undefined #endif #endif /* _TUSB_COMPILER_H_ */ From c831311a12a42d27690c830cc9cefd4d4e6efe2d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:37:47 -0400 Subject: [PATCH 09/94] Off-by-one error in Synopsys assertions. (and move some braces to their own lines. --- src/portable/st/synopsys/dcd_synopsys.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b0e7e04bd..2daa16a26 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -268,21 +268,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - // Unsupported endpoint numbers/size. - if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > EP_MAX)) { - return false; - } - + + TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; - if(dir == TUSB_DIR_OUT) { + if(dir == TUSB_DIR_OUT) + { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | \ desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos | \ desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos; dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); - } else { + } + else + { // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // From 4ea212a432c32dedfefa79d995d2190462a27a5f Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:52:43 -0400 Subject: [PATCH 10/94] This demonstrates that I don't pre-build things before committing them... oops. --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2daa16a26..f15b92edc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -269,7 +269,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); From d7137e36ca3681958603f610a16b68434baad474 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 14 Sep 2019 04:31:43 -0400 Subject: [PATCH 11/94] pyboardv11: Fix typo in HSE_VALUE define so that SysTick runs at correct frequency. --- hw/bsp/pyboardv11/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 9e328072b..2ba1d3900 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -1,5 +1,5 @@ CFLAGS += \ - -DHSE_VALUE=120000000 \ + -DHSE_VALUE=12000000 \ -DSTM32F405xx \ -mthumb \ -mabi=aapcs \ From 21ba37aec64aa8e436062aaa43be898ece993907 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 09:02:21 -0400 Subject: [PATCH 12/94] Interpretation of assert vs verify. --- src/common/tusb_verify.h | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 2727ce043..fae0c88ae 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -36,10 +36,34 @@ * as C++ for the sake of code simplicity. Beware of a headache macro * manipulation that you are told to stay away. * - * e.g * - * - TU_VERIFY( cond ) will return false if cond is false - * - TU_VERIFY( cond, err) will return err instead if cond is false + * This contains macros for both VERIFY and ASSERT: + * + * VERIFY: Used when there is an error condition which is not the + * fault of the MCU. For example, bounds checking on data + * sent to the micro over USB should use this function. + * Another example is checking for buffer overflows, where + * returning from the active function causes a NAK. + * + * ASSERT: Used for error conditions that are caused by MCU firmware + * bugs. This is used to discover bugs in the code more + * quickly. One example would be adding assertions in library + * function calls to confirm a function's (untainted) + * parameters are valid. + * + * + * The difference in behaviour is that ASSERT triggers a breakpoint while + * verify does not. + * + * #define TU_VERIFY(cond) if(cond) return false; + * #define TU_VERIFY(cond,ret) if(cond) return ret; + * + * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} + * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} + * + * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} + * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} + * *------------------------------------------------------------------*/ #ifdef __cplusplus From 1cae96951f59e7549ff1a2d5643cda66784c22a1 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 12:13:11 -0400 Subject: [PATCH 13/94] Add usbtmc class driver. --- examples/device/usbtmc/Makefile | 12 + examples/device/usbtmc/src/main.c | 113 +++++ examples/device/usbtmc/src/tusb_config.h | 66 +++ examples/device/usbtmc/src/usb_descriptors.c | 254 +++++++++++ examples/device/usbtmc/src/usbtmc_app.c | 133 ++++++ examples/rules.mk | 1 + src/class/usbtmc/usbtmc.h | 267 ++++++++++++ src/class/usbtmc/usbtmc_device.c | 420 +++++++++++++++++++ src/class/usbtmc/usbtmc_device.h | 130 ++++++ src/device/usbd.c | 16 + src/tusb.h | 4 + src/tusb_option.h | 4 + 12 files changed, 1420 insertions(+) create mode 100644 examples/device/usbtmc/Makefile create mode 100644 examples/device/usbtmc/src/main.c create mode 100644 examples/device/usbtmc/src/tusb_config.h create mode 100644 examples/device/usbtmc/src/usb_descriptors.c create mode 100644 examples/device/usbtmc/src/usbtmc_app.c create mode 100644 src/class/usbtmc/usbtmc.h create mode 100644 src/class/usbtmc/usbtmc_device.c create mode 100644 src/class/usbtmc/usbtmc_device.h diff --git a/examples/device/usbtmc/Makefile b/examples/device/usbtmc/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/usbtmc/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c new file mode 100644 index 000000000..0293261ad --- /dev/null +++ b/examples/device/usbtmc/src/main.c @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h new file mode 100644 index 000000000..022dc7691 --- /dev/null +++ b/examples/device/usbtmc/src/tusb_config.h @@ -0,0 +1,66 @@ +/* + * tusb_config.h + * + * Created on: Sep 5, 2019 + * Author: nconrad + */ + +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUD_ENDOINT0_SIZE 64 + +//------------- CLASS -------------// + +#define CFG_TUD_USBTMC 1 +#define CFG_TUD_USBTMC_ENABLE_INT_EP +//#define USBTMC_CFG_ENABLE_488 0 + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c new file mode 100644 index 000000000..296636359 --- /dev/null +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -0,0 +1,254 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" +#include "class/usbtmc/usbtmc.h" +#include "class/usbtmc/usbtmc_device.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + #if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + #else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + #endif + + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// HID Report Descriptor +//--------------------------------------------------------------------+ +#if CFG_TUD_HID + +uint8_t const desc_hid_report[] = +{ + TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), + TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) +}; + +// Invoked when received GET HID REPORT DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_hid_descriptor_report_cb(void) +{ + return desc_hid_report; +} + +#endif + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +#if defined(CFG_TUD_USBTMC) + +# define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ + USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 7u, USBTMC_PROTOCOL_USB488), \ + USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) + +#if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) + +# define USBTMC_DESC(_itfnum) \ + USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ + USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 64, /* bInterval = */16u ) +# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) + +#else + +# define USBTMC_DESC(_itfnum) \ + USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u) +# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN) + +#endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */ + +#else +# define USBTMC_DESC_LEN (0) +#endif /* CFG_TUD_USBTMC */ + +enum +{ +#if CFG_TUD_CDC + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, +#endif + +#if CFG_TUD_MSC + ITF_NUM_MSC, +#endif + +#if CFG_TUD_HID + ITF_NUM_HID, +#endif +#if CFG_TUD_USBTMC + ITF_NUM_USBTMC, +#endif + ITF_NUM_TOTAL +}; + + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + \ + CFG_TUD_HID*TUD_HID_DESC_LEN + (CFG_TUD_USBTMC)*USBTMC_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force + // endpoint number for MSC to 5 + #define EPNUM_MSC 0x05 +#else + #define EPNUM_MSC 0x03 +#endif + + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), +#endif + +#if CFG_TUD_USBTMC + USBTMC_DESC(ITF_NUM_USBTMC), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), +#endif + +#if CFG_TUD_HID + // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10) +#endif +}; + + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "TinyUSB CDC", // 4: CDC Interface + "TinyUSB MSC", // 5: MSC Interface + "TinyUSB HID", // 6: HID + "TinyUSB USBTMC", // 7: USBTMC +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index) +{ + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) { + chr_count = 31; + } + + for(uint8_t i=0; i +#include "class/usbtmc/usbtmc_device.h" + +#if (USBTMC_CFG_ENABLE_488) +usbtmc_response_capabilities_488_t const +#else +usbtmc_response_capabilities_t const +#endif +usbtmcd_app_capabilities = +{ + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .bcdUSBTMC = USBTMC_VERSION, + .bmIntfcCapabilities = + { + .listenOnly = 0, + .talkOnly = 0, + .supportsIndicatorPulse = 0 + }, + .bmDevCapabilities = { + .canEndBulkInOnTermChar = 0 + }, + +#if (USBTMC_CFG_ENABLE_488) + .bcdUSB488 = USBTMC_488_VERSION, + .bmIntfcCapabilities488 = + { + .supportsTrigger = 0, + .supportsREN_GTL_LLO = 0, + .is488_2 = 1 + }, + .bmDevCapabilities488 = + { + .SCPI = 1, + .SR1 = 0, + .RL1 = 0, + .DT1 =0, + } +#endif +}; + +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static uint8_t status; +static bool queryReceived = false; + + +bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader) +{ + (void)msgHeader; + return true; +} + + +bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete) +{ + (void)transfer_complete; + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { + queryReceived = true; + } + return true; +} + +bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) +{ + (void)rhport; + return true; +} + +static uint8_t noQueryMsg[] = "ERR: No query"; +bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +{ + usbtmc_msg_dev_dep_msg_in_header_t hdr = { + .header = + { + .MsgID = request->header.MsgID, + .bTag = request->header.bTag, + .bTagInverse = request->header.bTagInverse + }, + .TransferSize = sizeof(idn)-1, + .bmTransferAttributes = + { + .EOM = 1, + .UsingTermChar = 0 + } + }; + if(queryReceived) + { + usbtmcd_transmit_dev_msg_data(rhport, &hdr, idn); + } + else + { + hdr.TransferSize = sizeof(noQueryMsg)-1; + usbtmcd_transmit_dev_msg_data(rhport, &hdr, noQueryMsg); + } + queryReceived = false; + return true; +} + +// Return status byte, but put the transfer result status code in the rspResult argument. +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +{ + (void)rhport; + *rspResult = USBTMC_STATUS_SUCCESS; + // Increment status so that we see different results on each read... + status++; + + return status; +} + diff --git a/examples/rules.mk b/examples/rules.mk index 478a5907a..c3daf9dac 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -15,6 +15,7 @@ SRC_C += \ src/class/cdc/cdc_device.c \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ + src/class/usbtmc/usbtmc_device.c \ src/class/vendor/vendor_device.c \ src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h new file mode 100644 index 000000000..846c0e38d --- /dev/null +++ b/src/class/usbtmc/usbtmc.h @@ -0,0 +1,267 @@ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBTMC_H__ +#define _TUSB_USBTMC_H__ + +#include "common/tusb_common.h" + + +/* Implements USBTMC Revision 1.0, April 14, 2003 + + String descriptors must have a "LANGID=0x409"/US English string. + Characters must be 0x20 (' ') to 0x7E ('~') ASCII, + But MUST not contain: "/:?\* + Also must not have leading or trailing space (' ') + Device descriptor must state USB version 0x0200 or greater + + If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. +*/ + +#define USBTMC_VERSION 0x0100 +#define USBTMC_488_VERSION 0x0100 + +typedef enum { + USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, + USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, + USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, + USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, + USBTMC_MSGID_USB488_TRIGGER = 128u, +} usbtmc_msgid_enum; + +/// \brief Message header (For BULK OUT and BULK IN); 4 bytes +typedef struct TU_ATTR_PACKED +{ + uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) + uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 + uint8_t bTagInverse ; ///< Complement of the tag + uint8_t _reserved ; ///< Must be 0x00 +} usbtmc_msg_header_t; + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint8_t data[8]; +} usbtmc_msg_generic_t; + +/* Uses on the bulk-out endpoint: */ +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct { + uint8_t EOM : 1 ; ///< EOM set on last byte + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_request_dev_dep_out; + +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct { + uint8_t : 0; + uint8_t TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar + } bmTransferAttributes; + uint8_t TermChar; + uint8_t _reserved[2]; +} usbtmc_msg_request_dev_dep_in; + +/* Bulk-in headers */ + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint32_t TransferSize; + struct { + uint8_t EOM: 1; ///< Last byte of transfer is the end of the message + uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_dev_dep_msg_in_header_t; + + +/* Unsupported vendor things.... Are these ever used?*/ + +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_out; + + +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_in; + +// Control request type should use tusb_control_request_t + +/* +typedef struct TU_ATTR_PACKED { + struct { + uint8_t Recipient : 5 ; ///< EOM set on last byte + uint8_t Type : 2 ; ///< EOM set on last byte + uint8_t DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN + } bmRequestType; + uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum + uint16_t wValue ; + uint16_t wIndex ; + uint16_t wLength ; // Number of bytes in data stage +} usbtmc_class_specific_control_req; + +*/ +// bulk-in protocol errors +enum { + USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, + USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, + USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, + USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, + USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, +}; +// bult-in halt errors +enum { + USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a + /// Bulk-IN transfer is in progress +}; + +typedef enum { + USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, + USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, + USBTMC_bREQUEST_INITIATE_CLEAR = 5u, + USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, + USBTMC_bREQUEST_GET_CAPABILITIES = 7u, + + USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional +} usmtmc_request_type_enum; + +typedef enum { + USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, + USBTMC488_bREQUEST_REN_CONTROL = 160u, + USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, + USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, +} usbtmc_request_type_488_enum; + +typedef enum { + USBTMC_STATUS_SUCCESS = 0x01, + USBTMC_STATUS_PENDING = 0x02, + USBTMC_STATUS_FAILED = 0x80, + USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, + USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, + USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83 +} usbtmc_status_enum; + +/************************************************************ + * Control Responses + */ + +typedef struct TU_ATTR_PACKED { + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct { + uint8_t listenOnly :1; + uint8_t talkOnly :1; + uint8_t supportsIndicatorPulse :1; + } bmIntfcCapabilities; + struct { + uint8_t canEndBulkInOnTermChar :1; + } bmDevCapabilities; + uint8_t _reserved2[6]; + uint8_t _reserved3[12]; +} usbtmc_response_capabilities_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct + { + uint8_t listenOnly :1; + uint8_t talkOnly :1; + uint8_t supportsIndicatorPulse :1; + } bmIntfcCapabilities; + + struct + { + uint8_t canEndBulkInOnTermChar :1; + } bmDevCapabilities; + + uint8_t _reserved2[6]; + uint16_t bcdUSB488; + + struct + { + uint8_t is488_2 :1; + uint8_t supportsREN_GTL_LLO :1; + uint8_t supportsTrigger :1; + } bmIntfcCapabilities488; + + struct + { + uint8_t SCPI :1; + uint8_t SR1 :1; + uint8_t RL1 :1; + uint8_t DT1 :1; + } bmDevCapabilities488; + uint8_t _reserved3[8]; +} usbtmc_response_capabilities_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; + uint8_t statusByte; +} usbtmc_read_stb_rsp_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); + +typedef struct TU_ATTR_PACKET +{ + union { + struct { + uint8_t bTag : 7; + uint8_t one : 1; + } bNotify1Struct; + uint8_t bNotify1; + }; + uint8_t StatusByte; +} usbtmc_read_stb_interrupt_488_t; +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); + +#endif + diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c new file mode 100644 index 000000000..4bb21f354 --- /dev/null +++ b/src/class/usbtmc/usbtmc_device.c @@ -0,0 +1,420 @@ +/* + * usbtmc.c + * + * Created on: Sep 9, 2019 + * Author: nconrad + */ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +// We don't do any cross-task anything here (everything is in tud or interrupt context). +// You must ensure thread safety in your own app. + + +//Limitations (not planned to be implemented): +// "vendor-specific" commands are not handled + +// TODO: +// USBTMC 3.2.2 error conditions not strictly followed +// No local lock-out, REN, or GTL. +// Cannot issue clear. +// No "capabilities" supported +// Interrupt-IN endpoint +// 488 MsgID=Trigger +// Clear message available status byte at the correct time? (488 4.3.1.3) +// Split transfers +// No CLEAR_FEATURE/HALT (yet) + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) + +#include "usbtmc.h" +#include "usbtmc_device.h" +#include "device/dcd.h" +#include "device/usbd.h" + +// FIXME: I shouldn't need to include _pvt headers. +#include "device/usbd_pvt.h" + +typedef enum +{ + STATE_IDLE, + STATE_RCV, + STATE_TX_REQUESTED, + STATE_TX_INITIATED +} usbtmcd_state_enum; + +typedef struct +{ + usbtmcd_state_enum state; + uint8_t itf_id; + uint8_t ep_bulk_in; + uint8_t ep_bulk_out; + uint8_t ep_int_in; + uint8_t ep_bulk_in_buf[64]; + uint8_t ep_bulk_out_buf[64]; + uint8_t lastTag; + + uint32_t transfer_size_remaining; + uint8_t const * devInBuffer; +} usbtmc_interface_state_t; + +static usbtmc_interface_state_t usbtmc_state = +{ + .state = STATE_IDLE, + .itf_id = 0xFF, + .ep_bulk_in = 0, + .ep_bulk_out = 0, + .ep_int_in = 0 +}; + +// We want everything to fit nicely in a single packet, so lets require EP size >32 +// I'm not sure if this is really necessary, though. +TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); + +// called from app +// We keep a reference to the buffer, so it MUST not change until the app is +// notified that the transfer is complete. +// length of data is specified in the hdr. +bool usbtmcd_transmit_dev_msg_data( + uint8_t rhport, + usbtmc_msg_dev_dep_msg_in_header_t const * hdr, + const void *data) +{ + TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); + TU_ASSERT(hdr->TransferSize > 0u); + + // Copy in the header + memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); + uint packetLen = sizeof(*hdr); + // Single-packet transfer + if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) + { + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); + packetLen = (uint16_t)(packetLen+ hdr->TransferSize); + // Pad up to multiple of 4 bytes + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0; + packetLen++; + } + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + } + else + { + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, USBTMCD_MAX_PACKET_SIZE - packetLen); + usbtmc_state.transfer_size_remaining = hdr->TransferSize - (USBTMCD_MAX_PACKET_SIZE - packetLen); + usbtmc_state.devInBuffer += (USBTMCD_MAX_PACKET_SIZE - packetLen); + packetLen = USBTMCD_MAX_PACKET_SIZE; + } + usbtmc_state.state = STATE_TX_INITIATED; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + return true; +} + +void usbtmcd_init(void) +{ + +} + +bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + (void)rhport; + uint8_t const * p_desc; + uint8_t found_endpoints = 0; + + // Perhaps there are other application specific class drivers, so don't assert here. + if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) + return false; + if( itf_desc->bInterfaceSubClass != USBTMC_APP_SUBCLASS) + return false; + + // Only 2 or 3 endpoints are allowed for USBTMC. + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); + + // Interface + (*p_length) = 0u; + p_desc = (uint8_t const *) itf_desc; + + usbtmc_state.itf_id = itf_desc->bInterfaceNumber; + + while (found_endpoints < itf_desc->bNumEndpoints) + { + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; + switch(ep_desc->bmAttributes.xfer) { + case TUSB_XFER_BULK: + if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) + { + usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; + } else { + usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; + } + + break; + case TUSB_XFER_INTERRUPT: + TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); + TU_ASSERT(usbtmc_state.ep_int_in == 0); + usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; + break; + default: + TU_ASSERT(false); + } + TU_VERIFY( dcd_edpt_open(rhport, ep_desc)); + found_endpoints++; + } + (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); + p_desc = tu_desc_next(p_desc); + } + + // bulk endpoints are required, but interrupt IN is optional + TU_ASSERT(usbtmc_state.ep_bulk_in != 0); + TU_ASSERT(usbtmc_state.ep_bulk_out != 0); + if (itf_desc->bNumEndpoints == 2) { + TU_ASSERT(usbtmc_state.ep_int_in == 0); + } + else if (itf_desc->bNumEndpoints == 2) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0); + } + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + + return true; +} +void usbtmcd_reset(uint8_t rhport) +{ + // FIXME: Do endpoints need to be closed here? + (void)rhport; +} +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len) +{ + (void)rhport; + bool shortPacket = (len < USBTMCD_MAX_PACKET_SIZE); + if(usbtmc_state.state == STATE_IDLE) + { + // must be a header, should have been confirmed before calling here. + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkOut_start(msg)); + len -= sizeof(*msg); + data = (uint8_t*)data + sizeof(*msg); + } + // Packet is to be considered complete when we get enough data or at a short packet. + bool atEnd = false; + if(len >= usbtmc_state.transfer_size_remaining || shortPacket) + atEnd = true; + if(len > usbtmc_state.transfer_size_remaining) + len = usbtmc_state.transfer_size_remaining; + usbtmcd_app_msg_data(data, len, atEnd); + if(atEnd) + usbtmc_state.state = STATE_IDLE; + else + usbtmc_state.state = STATE_RCV; + return true; +} +static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) +{ + TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); + usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + usbtmc_state.state = STATE_TX_REQUESTED; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); + return true; +} + +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + TU_VERIFY(result == XFER_RESULT_SUCCESS); + if(ep_addr == usbtmc_state.ep_bulk_out) + { + switch(usbtmc_state.state) + { + case STATE_IDLE: + TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); + usbtmc_msg_generic_t *msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); + uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); + TU_VERIFY(msg->header.bTag == invInvTag); + TU_VERIFY(msg->header.bTag != 0x00); + usbtmc_state.lastTag = msg->header.bTag; + + switch(msg->header.MsgID) { + case USBTMC_MSGID_DEV_DEP_MSG_OUT: + TU_VERIFY(handle_devMsgOut(rhport, msg, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + break; + case USBTMC_MSGID_DEV_DEP_MSG_IN: + TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); + break; + case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: + case USBTMC_MSGID_VENDOR_SPECIFIC_IN: + case USBTMC_MSGID_USB488_TRIGGER: + default: + TU_VERIFY(false); + } + return true; + + case STATE_RCV: + TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + return true; + break; + + default: + TU_VERIFY(false); + } + } + else if(ep_addr == usbtmc_state.ep_bulk_in) + { + TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); + if(usbtmc_state.transfer_size_remaining == 0) + { + usbtmc_state.state = STATE_IDLE; + TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + } + else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) + { + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, USBTMCD_MAX_PACKET_SIZE); + usbtmc_state.devInBuffer += USBTMCD_MAX_PACKET_SIZE; + usbtmc_state.transfer_size_remaining -= USBTMCD_MAX_PACKET_SIZE; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,USBTMCD_MAX_PACKET_SIZE)); + } + else // short packet + { + uint packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0; + packetLen++; + } + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + } + return true; + } + else if (ep_addr == usbtmc_state.ep_int_in) { + // Good? + return true; + } + return false; +} + +bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { + +#if (USBTMC_CFG_ENABLE_488) + ushort bTag; +#endif + // We only handle class requests. + if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) + return false; + + switch(request->bRequest) + { + // USBTMC required requests + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + case USBTMC_bREQUEST_INITIATE_CLEAR: + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: + TU_VERIFY(false); + break; + + case USBTMC_bREQUEST_GET_CAPABILITIES: + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY(request->wValue == 0x0000); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + return true; + // USBTMC Optional Requests + case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + TU_VERIFY(false); + return false; + +#if (USBTMC_CFG_ENABLE_488) + // USB488 required requests + case USBTMC488_bREQUEST_READ_STATUS_BYTE: + + bTag = request->wValue & 0x7F; + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero + TU_VERIFY(bTag >= 0x02 && bTag <= 127); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == 0x0003); + usbtmc_read_stb_rsp_488_t rsp; + rsp.bTag = (uint8_t)bTag; + if(usbtmc_state.ep_int_in != 0) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp.statusByte = 0x00; // Use interrupt endpoint, instead. + + usbtmc_read_stb_interrupt_488_t intMsg = + { + .bNotify1 = (uint8_t)(0x80 | bTag), + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + }; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + + } + else + { + rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + return true; + + // USB488 optional requests + case USBTMC488_bREQUEST_REN_CONTROL: + case USBTMC488_bREQUEST_GO_TO_LOCAL: + case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + TU_VERIFY(false); + return false; +#endif + + default: + TU_VERIFY(false); + } + TU_VERIFY(false); +} + +bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void)rhport; + //------------- Class Specific Request -------------// + TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + return true; +} + +#endif /* CFG_TUD_TSMC */ diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h new file mode 100644 index 000000000..c03ca9461 --- /dev/null +++ b/src/class/usbtmc/usbtmc_device.h @@ -0,0 +1,130 @@ +/* + * usbtmc_device.h + * + * Created on: Sep 10, 2019 + * Author: nconrad + */ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ +#define CLASS_USBTMC_USBTMC_DEVICE_H_ + +#include "usbtmc.h" + +// Enable 488 mode by default +#if !defined(USBTMC_CFG_ENABLE_488) +#define USBTMC_CFG_ENABLE_488 (1) +#endif + +// USB spec says that full-speed must be 8,16,32, or 64. +// However, this driver implementation requires it to be >=32 +#define USBTMCD_MAX_PACKET_SIZE (64u) + +/*********************************************** + * Functions to be implemeted by the class implementation + */ + +#if (USBTMC_CFG_ENABLE_488) +extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; +#else +extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; +#endif + +bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader); + +// transfer_complete does not imply that a message is complete. +bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete); + +bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); + +bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); + +#if (USBTMC_CFG_ENABLE_488) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); + +//TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); +#endif + +/******************************************* + * Called from app + * + * We keep a reference to the buffer, so it MUST not change until the app is + * notified that the transfer is complete. + ******************************************/ + +bool usbtmcd_transmit_dev_msg_data( + uint8_t rhport, + usbtmc_msg_dev_dep_msg_in_header_t const * hdr, + const void *data); + + +/* "callbacks" from USB device core */ + +bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +void usbtmcd_reset(uint8_t rhport); +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init(void); + +/************************************************************ + * USBTMC Descriptor Templates + *************************************************************/ + +#define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC +#define USBTMC_APP_SUBCLASS 0x03 + +#define USBTMC_PROTOCOL_STD 0x00 +#define USBTMC_PROTOCOL_USB488 0x01 + +// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, +// bulk-in endpoint ID +#define USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ +/* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, USBTMC_APP_CLASS, USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + +#define USBTMC_IF_DESCRIPTOR_LEN 9u + +// bulk-out Size must be a multiple of 4 bytes +#define USBTMC_BULK_DESCRIPTORS(_epout, _epin) \ +/* Endpoint Out */ \ +7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u, \ +/* Endpoint In */ \ +7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u + +#define USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) + +/* optional interrupt endpoint */ \ +// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? +#define USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ +7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + +#define USBTMC_INT_DESCRIPTOR_LEN (7u) + + +#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index c92884334..572708f7d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -145,6 +145,22 @@ static usbd_class_driver_t const usbd_class_drivers[] = .sof = NULL }, #endif + + #if CFG_TUD_USBTMC + // Presently USBTMC is the only defined class with the APP_SPECIFIC class code. + // We maybe need to add subclass codes here, or a callback to ask if a driver can + // handle a particular interface. + { + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .init = usbtmcd_init, + .reset = usbtmcd_reset, + .open = usbtmcd_open, + .control_request = usbtmcd_control_request, + .control_complete = usbtmcd_control_complete, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) }; diff --git a/src/tusb.h b/src/tusb.h index fe8673726..1a6ff0b10 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -83,6 +83,10 @@ #if CFG_TUD_VENDOR #include "class/vendor/vendor_device.h" #endif + + #if CFG_TUD_USBTMC + #include "class/usbtmc/usbtmc_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9aacb558f..76ea59758 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -181,6 +181,10 @@ #define CFG_TUD_VENDOR 0 #endif +#ifndef CFG_TUD_USBTMC + #define CFG_TUD_USBTMC 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS From e74c6b0874a54b86fee61692484e0407d6a97508 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 15:38:11 -0400 Subject: [PATCH 14/94] Combined status response enum (std with 488), support trigger. --- src/class/usbtmc/usbtmc.h | 6 +-- src/class/usbtmc/usbtmc_device.c | 63 ++++++++++++++++++++++---------- src/class/usbtmc/usbtmc_device.h | 8 ++-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 846c0e38d..ecc16a315 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -160,14 +160,14 @@ typedef enum { USBTMC_bREQUEST_GET_CAPABILITIES = 7u, USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional -} usmtmc_request_type_enum; -typedef enum { + /****** USBTMC 488 *************/ USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, USBTMC488_bREQUEST_REN_CONTROL = 160u, USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, -} usbtmc_request_type_488_enum; + +} usmtmc_request_type_enum; typedef enum { USBTMC_STATUS_SUCCESS = 0x01, diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 4bb21f354..25f943598 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -97,6 +97,10 @@ static usbtmc_interface_state_t usbtmc_state = // I'm not sure if this is really necessary, though. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. @@ -140,7 +144,10 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { - +#if USBTMC_CFG_ENABLE_488 + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(usbtmcd_app_msg_trigger != NULL,); +#endif } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -213,32 +220,39 @@ void usbtmcd_reset(uint8_t rhport) // FIXME: Do endpoints need to be closed here? (void)rhport; } -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len) + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - bool shortPacket = (len < USBTMCD_MAX_PACKET_SIZE); - if(usbtmc_state.state == STATE_IDLE) - { - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(usbtmcd_app_msgBulkOut_start(msg)); - len -= sizeof(*msg); - data = (uint8_t*)data + sizeof(*msg); - } + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + // must be a header, should have been confirmed before calling here. + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkOut_start(rhport,msg)); + + TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + return true; +} + +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) +{ + (void)rhport; + bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); + // Packet is to be considered complete when we get enough data or at a short packet. bool atEnd = false; if(len >= usbtmc_state.transfer_size_remaining || shortPacket) atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - usbtmcd_app_msg_data(data, len, atEnd); + usbtmcd_app_msg_data(rhport,data, len, atEnd); if(atEnd) usbtmc_state.state = STATE_IDLE; else usbtmc_state.state = STATE_RCV; return true; } + static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); @@ -267,25 +281,34 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: - TU_VERIFY(handle_devMsgOut(rhport, msg, xferred_bytes)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); break; + case USBTMC_MSGID_DEV_DEP_MSG_IN: TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; + +#ifdef USBTMC_CFG_ENABLE_488 + case USBTMC_MSGID_USB488_TRIGGER: + // Spec says we halt the EP if we didn't declare we support it. + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); + + break; +#endif case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - case USBTMC_MSGID_USB488_TRIGGER: default: TU_VERIFY(false); + return false; } return true; case STATE_RCV: - TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; - break; default: TU_VERIFY(false); @@ -298,7 +321,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint { usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); } else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index c03ca9461..1246d11d1 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -55,18 +55,18 @@ extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; #endif -bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader); +bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete); +bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); - +uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult); +TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From acd8fa76505f036858e2d33ebbc58cc7f15e3a8b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 16:56:53 -0400 Subject: [PATCH 15/94] (and update the example to match) --- examples/device/usbtmc/src/usbtmc_app.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 515c2a486..4ec6ad90c 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -49,7 +49,7 @@ usbtmcd_app_capabilities = .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { - .supportsTrigger = 0, + .supportsTrigger = 1, .supportsREN_GTL_LLO = 0, .is488_2 = 1 }, @@ -68,15 +68,21 @@ static uint8_t status; static bool queryReceived = false; -bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader) +bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { + (void)rhport; (void)msgHeader; return true; } +bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { + (void)rhport; + (void)msg; + return true; +} - -bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete) +bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) { + (void)rhport; (void)transfer_complete; if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryReceived = true; @@ -121,7 +127,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) { (void)rhport; *rspResult = USBTMC_STATUS_SUCCESS; From 6e00886ffbbc552cf91be73d57fe8ad0a4842d0b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 17:15:34 -0400 Subject: [PATCH 16/94] Handle USBTMC TermChar. --- src/class/usbtmc/usbtmc_device.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 25f943598..909f8251f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -61,6 +61,9 @@ // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" +static uint8_t termChar; +static uint8_t termCharRequested = false; + typedef enum { STATE_IDLE, @@ -113,6 +116,13 @@ bool usbtmcd_transmit_dev_msg_data( TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); TU_ASSERT(hdr->TransferSize > 0u); + if(hdr->bmTransferAttributes.UsingTermChar) + { + TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(termCharRequested); + TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); + } + // Copy in the header memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); uint packetLen = sizeof(*hdr); @@ -260,6 +270,12 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(usbtmc_state.state == STATE_IDLE); usbtmc_state.state = STATE_TX_REQUESTED; usbtmc_state.transfer_size_remaining = msg->TransferSize; + + termCharRequested = msg->bmTransferAttributes.TermCharEnabled; + termChar = msg->TermChar; + if(termCharRequested) + TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); return true; } @@ -310,6 +326,8 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; + case STATE_TX_REQUESTED: + case STATE_TX_INITIATED: default: TU_VERIFY(false); } From 64bfec79b2d1d75b5c06be2dc2fff83ee385a720 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 18:07:12 -0400 Subject: [PATCH 17/94] Change requset type parameter back to uint8_t (fix type cast), support USB indicator pulse --- examples/device/usbtmc/src/main.c | 47 ++++++++++++++++++++----- examples/device/usbtmc/src/main.h | 5 +++ examples/device/usbtmc/src/usbtmc_app.c | 13 ++++--- src/class/usbtmc/usbtmc_device.c | 21 ++++++----- src/class/usbtmc/usbtmc_device.h | 4 ++- 5 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 examples/device/usbtmc/src/main.h diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 0293261ad..8bc2a8398 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -36,12 +36,12 @@ /* Blink pattern * - 250 ms : device not mounted - * - 1000 ms : device mounted + * - 0 ms : device mounted * - 2500 ms : device is suspended */ enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, + BLINK_MOUNTED = 0, BLINK_SUSPENDED = 2500, }; @@ -97,17 +97,46 @@ void tud_resume_cb(void) } //--------------------------------------------------------------------+ -// BLINKING TASK +// BLINKING TASK + Indicator pulse //--------------------------------------------------------------------+ + + +volatile uint8_t doPulse = false; +// called from USB context +void led_indicator_pulse(void) { + doPulse = true; +} + void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; + if(blink_interval_ms == BLINK_MOUNTED) // Mounted + { + if(doPulse) + { + led_state = true; + board_led_write(true); + start_ms = board_millis(); + doPulse = false; + } + else if (led_state == true) + { + if ( board_millis() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. + { + return; // not enough time + } + led_state = false; + board_led_write(false); + } + } + else + { + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/examples/device/usbtmc/src/main.h b/examples/device/usbtmc/src/main.h new file mode 100644 index 000000000..673247ec7 --- /dev/null +++ b/examples/device/usbtmc/src/main.h @@ -0,0 +1,5 @@ +#ifndef MAIN_H +#define MAIN_H +void led_indicator_pulse(void); + +#endif diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 4ec6ad90c..6b72bb360 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,6 +25,7 @@ #include #include "class/usbtmc/usbtmc_device.h" +#include "main.h" #if (USBTMC_CFG_ENABLE_488) usbtmc_response_capabilities_488_t const @@ -39,7 +40,7 @@ usbtmcd_app_capabilities = { .listenOnly = 0, .talkOnly = 0, - .supportsIndicatorPulse = 0 + .supportsIndicatorPulse = 1 }, .bmDevCapabilities = { .canEndBulkInOnTermChar = 0 @@ -63,7 +64,7 @@ usbtmcd_app_capabilities = #endif }; -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; static uint8_t status; static bool queryReceived = false; @@ -96,7 +97,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) return true; } -static uint8_t noQueryMsg[] = "ERR: No query"; +static uint8_t noQueryMsg[] = "ERR: No query\n"; bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { usbtmc_msg_dev_dep_msg_in_header_t hdr = { @@ -127,7 +128,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) { (void)rhport; *rspResult = USBTMC_STATUS_SUCCESS; @@ -137,3 +138,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) return status; } +bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg) +{ + led_indicator_pulse(); +} diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 909f8251f..7bc768a58 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -39,17 +39,18 @@ //Limitations (not planned to be implemented): // "vendor-specific" commands are not handled +// Dealing with "termchar" must be handled by the application layer, +// though additional error checking is does in this module. // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. -// Cannot issue clear. -// No "capabilities" supported -// Interrupt-IN endpoint -// 488 MsgID=Trigger +// Cannot handle clear. +// Not all "capabilities" supported // Clear message available status byte at the correct time? (488 4.3.1.3) // Split transfers -// No CLEAR_FEATURE/HALT (yet) +// No CLEAR_FEATURE/HALT no EP (yet) +// No aborting transfers. #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) @@ -156,8 +157,11 @@ void usbtmcd_init(void) { #if USBTMC_CFG_ENABLE_488 if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(usbtmcd_app_msg_trigger != NULL,); + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); #endif + if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); + } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -400,8 +404,9 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ return true; // USBTMC Optional Requests case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - TU_VERIFY(false); - return false; + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request)); + return true; #if (USBTMC_CFG_ENABLE_488) // USB488 required requests diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 1246d11d1..09cda7c67 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,8 +64,10 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg); + #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult); +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From e53e9bd4f0749e53740c9c33e740998ac202dd8a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 21:24:52 -0400 Subject: [PATCH 18/94] Simulate query delay; getting to a point where implementing clear/aborts makes sense. Probably adding too many concurance issues; need to figure out semaphores. --- examples/device/usbtmc/src/main.c | 3 +- examples/device/usbtmc/src/usb_descriptors.c | 6 +- examples/device/usbtmc/src/usbtmc_app.c | 91 ++++++++++++++------ examples/device/usbtmc/src/usbtmc_app.h | 7 ++ src/class/usbtmc/usbtmc_device.c | 20 ++++- src/class/usbtmc/usbtmc_device.h | 5 +- 6 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 examples/device/usbtmc/src/usbtmc_app.h diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 8bc2a8398..1fce48f45 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "tusb.h" - +#include "usbtmc_app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -60,6 +60,7 @@ int main(void) { tud_task(); // tinyusb device task led_blinking_task(); + usbtmc_app_task_iter(); } return 0; diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 296636359..9567bcab5 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -110,10 +110,10 @@ uint8_t const * tud_hid_descriptor_report_cb(void) USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) - +// Interrupt endpoint should be 2 bytes on a FS USB link # define USBTMC_DESC(_itfnum) \ USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 64, /* bInterval = */16u ) + USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) # define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) #else @@ -248,7 +248,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) } // first byte is length (including header), second byte is string type - _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2); + _desc_str[0] = (((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u); return _desc_str; } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 6b72bb360..af97939b9 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,6 +25,7 @@ #include #include "class/usbtmc/usbtmc_device.h" +#include "bsp/board.h" #include "main.h" #if (USBTMC_CFG_ENABLE_488) @@ -65,9 +66,21 @@ usbtmcd_app_capabilities = }; static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; -static uint8_t status; -static bool queryReceived = false; +static volatile uint8_t status; +// 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? +// (to simulate delay) +static volatile uint16_t queryState = 0; +static volatile uint32_t queryDelayStart; +static volatile uint32_t bulkInStarted; + +static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { + .bmTransferAttributes = + { + .EOM = 1, + .UsingTermChar = 0 + } +}; bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { @@ -86,7 +99,7 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; (void)transfer_complete; if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { - queryReceived = true; + queryState = 1; } return true; } @@ -98,47 +111,73 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) } static uint8_t noQueryMsg[] = "ERR: No query\n"; + bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { - usbtmc_msg_dev_dep_msg_in_header_t hdr = { - .header = - { - .MsgID = request->header.MsgID, - .bTag = request->header.bTag, - .bTagInverse = request->header.bTagInverse - }, - .TransferSize = sizeof(idn)-1, - .bmTransferAttributes = - { - .EOM = 1, - .UsingTermChar = 0 - } - }; - if(queryReceived) + rspMsg.header.MsgID = request->header.MsgID, + rspMsg.header.bTag = request->header.bTag, + rspMsg.header.bTagInverse = request->header.bTagInverse; + if(queryState != 0) { - usbtmcd_transmit_dev_msg_data(rhport, &hdr, idn); + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; } else { - hdr.TransferSize = sizeof(noQueryMsg)-1; - usbtmcd_transmit_dev_msg_data(rhport, &hdr, noQueryMsg); + rspMsg.TransferSize = sizeof(noQueryMsg)-1; + usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, noQueryMsg); } - queryReceived = false; + // Always return true indicating not to stall the EP. return true; } +void usbtmc_app_task_iter(void) { + uint8_t const rhport = 0; + + switch(queryState) { + case 1: + queryDelayStart = board_millis(); + queryState = 2; + break; + case 2: + if( (board_millis() - queryDelayStart) > 1000u) { + queryDelayStart = board_millis(); + queryState=3; + status |= 0x10u; // MAV + } + break; + case 3: + if( (board_millis() - queryDelayStart) > 1000u) { + queryState = 4; + } + break; + case 4: // time to transmit; + if(bulkInStarted) { + queryState = 0; + bulkInStarted = 0; + rspMsg.TransferSize = sizeof(idn)-1; + usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); + status &= ~(0x10u); // MAV + } + break; + } +} + // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; - *rspResult = USBTMC_STATUS_SUCCESS; + *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... - status++; return status; } -bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg) +bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { + (void)rhport; + (void)msg; led_indicator_pulse(); + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; } diff --git a/examples/device/usbtmc/src/usbtmc_app.h b/examples/device/usbtmc/src/usbtmc_app.h new file mode 100644 index 000000000..4de30c2ba --- /dev/null +++ b/examples/device/usbtmc/src/usbtmc_app.h @@ -0,0 +1,7 @@ + +#ifndef USBTMC_APP_H +#define USBTMC_APP_H + +void usbtmc_app_task_iter(void); + +#endif diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 7bc768a58..db0c95a32 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -379,9 +379,11 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) ushort bTag; #endif - // We only handle class requests. + // We only handle class requests, IN direction. if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) + { return false; + } switch(request->bRequest) { @@ -390,27 +392,38 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(false); + break; + case USBTMC_bREQUEST_INITIATE_CLEAR: case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); break; case USBTMC_bREQUEST_GET_CAPABILITIES: - TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wValue == 0x0000); TU_VERIFY(request->wIndex == usbtmc_state.itf_id); TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); return true; // USBTMC Optional Requests + case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request)); + uint8_t tmcResult; + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcResult)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcResult, sizeof(tmcResult))); + return true; #if (USBTMC_CFG_ENABLE_488) // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface bTag = request->wValue & 0x7F; TU_VERIFY(request->bmRequestType == 0xA1); @@ -444,6 +457,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_REN_CONTROL: case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; #endif diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 09cda7c67..84640b136 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,10 +64,11 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); -TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg); +// Indicator pulse should be 0.5 to 1.0 seconds long +TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From 9593463367cca64acc7732013efdc634e84c2a81 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 15:20:01 -0400 Subject: [PATCH 19/94] Massive copy&paste typo of mine in the 32-bit byte swapping function.... --- src/common/tusb_compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index ca294c20f..df0326afd 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -80,7 +80,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } @@ -108,7 +108,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } From ae873a709e21738fecba561e7d57a402f8bf3f2c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 23:33:36 -0400 Subject: [PATCH 20/94] Wrote TX instead of RX. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 96579c75b..6e46afdbb 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -595,7 +595,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { *PCD_EP_TX_ADDRESS_PTR(USB, epnum) = ep_buf_ptr; - PCD_SET_EP_RX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); + PCD_SET_EP_TX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); PCD_CLEAR_TX_DTOG(USB, epnum); PCD_SET_EP_TX_STATUS(USB,epnum,USB_EP_TX_NAK); } From 18303e742ee3c7897e28ce9960069e362dae38d2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 23:37:57 -0400 Subject: [PATCH 21/94] Covert macros to inline functions. --- .gitignore | 4 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 141 ++++---- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 314 ++++++++++++------ 3 files changed, 292 insertions(+), 167 deletions(-) diff --git a/.gitignore b/.gitignore index 9864ea6be..772f5d8ee 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ latex test_old/ tests_obsolete/ _build +# coverity intermediate files +cov-int +# cppcheck build directories +*-build-dir diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 6e46afdbb..452c9a92e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -147,7 +147,7 @@ * Checks, structs, defines, function definitions, etc. */ -TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT,"Only 8 endpoints supported on the hardware"); +TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT, "Only 8 endpoints supported on the hardware"); TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LENGTH), "BTABLE does not fit in PMA RAM"); @@ -166,8 +166,17 @@ typedef struct uint16_t queued_len; } xfer_ctl_t; -static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; -#define XFER_CTL_BASE(_epnum, _dir) &xfer_status[_epnum][_dir] +static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; + +static xfer_ctl_t* xfer_ctl_ptr(unsigned int epnum, unsigned int dir) +{ +#ifndef NDEBUG + TU_ASSERT(epnum < MAX_EP_COUNT); + TU_ASSERT(dir < 2u); +#endif + + return &xfer_status[epnum][dir]; +} static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; @@ -224,7 +233,7 @@ void dcd_init (uint8_t rhport) for(uint32_t i=0; iDADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. - PCD_SET_EP_RX_STATUS(USB, 0, USB_EP_RX_VALID); // And start accepting SETUP on EP0 + pcd_set_ep_rx_status(USB, 0, USB_EP_RX_VALID); // And start accepting SETUP on EP0 } // FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed. @@ -370,9 +379,9 @@ static uint16_t dcd_ep_ctr_handler(void) { /* DIR = 0 => IN int */ /* DIR = 0 implies that (EP_CTR_TX = 1) always */ - PCD_CLEAR_TX_EP_CTR(USB, 0); + pcd_clear_tx_ep_ctr(USB, 0); - xfer_ctl_t * xfer = XFER_CTL_BASE(EPindex,TUSB_DIR_IN); + xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN); if((xfer->total_len == xfer->queued_len)) { @@ -386,7 +395,7 @@ static uint16_t dcd_ep_ctr_handler(void) } if(xfer->total_len == 0) // Probably a status message? { - PCD_CLEAR_RX_DTOG(USB,EPindex); + pcd_clear_rx_dtog(USB,EPindex); } } else @@ -399,10 +408,10 @@ static uint16_t dcd_ep_ctr_handler(void) /* DIR = 1 & CTR_RX => SETUP or OUT int */ /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ - xfer_ctl_t *xfer = XFER_CTL_BASE(EPindex,TUSB_DIR_OUT); + xfer_ctl_t *xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT); //ep = &hpcd->OUT_ep[0]; - wEPVal = PCD_GET_ENDPOINT(USB, EPindex); + wEPVal = pcd_get_endpoint(USB, EPindex); if ((wEPVal & USB_EP_SETUP) != 0U) // SETUP { @@ -410,38 +419,38 @@ static uint16_t dcd_ep_ctr_handler(void) // user memory, to allow for the 32-bit access that memcpy performs. uint8_t userMemBuf[8]; /* Get SETUP Packet*/ - count = PCD_GET_EP_RX_CNT(USB, EPindex); + count = pcd_get_ep_rx_cnt(USB, EPindex); //TU_ASSERT_ERR(count == 8); - dcd_read_packet_memory(userMemBuf, *PCD_EP_RX_ADDRESS_PTR(USB,EPindex), 8); + dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); /* SETUP bit kept frozen while CTR_RX = 1*/ dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); - PCD_CLEAR_RX_EP_CTR(USB, EPindex); + pcd_clear_rx_ep_ctr(USB, EPindex); } else if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT { - PCD_CLEAR_RX_EP_CTR(USB, EPindex); + pcd_clear_rx_ep_ctr(USB, EPindex); /* Get Control Data OUT Packet */ - count = PCD_GET_EP_RX_CNT(USB,EPindex); + count = pcd_get_ep_rx_cnt(USB,EPindex); if (count != 0U) { - dcd_read_packet_memory(xfer->buffer, *PCD_EP_RX_ADDRESS_PTR(USB,EPindex), count); + dcd_read_packet_memory(xfer->buffer, *pcd_ep_rx_address_ptr(USB,EPindex), count); xfer->queued_len = (uint16_t)(xfer->queued_len + count); } /* Process Control Data OUT status Packet*/ if(EPindex == 0u && xfer->total_len == 0u) { - PCD_CLEAR_EP_KIND(USB,0); // Good, so allow non-zero length packets now. + pcd_clear_ep_kind(USB,0); // Good, so allow non-zero length packets now. } dcd_event_xfer_complete(0, EPindex, xfer->total_len, XFER_RESULT_SUCCESS, true); - PCD_SET_EP_RX_CNT(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); + pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); if(EPindex == 0u && xfer->total_len == 0u) { - PCD_SET_EP_RX_STATUS(USB, EPindex, USB_EP_RX_VALID);// Await next SETUP + pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);// Await next SETUP } } @@ -452,21 +461,21 @@ static uint16_t dcd_ep_ctr_handler(void) { /* process related endpoint register */ - wEPVal = PCD_GET_ENDPOINT(USB, EPindex); + wEPVal = pcd_get_endpoint(USB, EPindex); if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT { /* clear int flag */ - PCD_CLEAR_RX_EP_CTR(USB, EPindex); + pcd_clear_rx_ep_ctr(USB, EPindex); - xfer_ctl_t * xfer = XFER_CTL_BASE(EPindex,TUSB_DIR_OUT); + xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT); //ep = &hpcd->OUT_ep[EPindex]; - count = PCD_GET_EP_RX_CNT(USB, EPindex); + count = pcd_get_ep_rx_cnt(USB, EPindex); if (count != 0U) { dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), - *PCD_EP_RX_ADDRESS_PTR(USB,EPindex), count); + *pcd_ep_rx_address_ptr(USB,EPindex), count); } /*multi-packet on the NON control OUT endpoint */ @@ -483,12 +492,12 @@ static uint16_t dcd_ep_ctr_handler(void) { uint16_t remaining = (uint16_t)(xfer->total_len - xfer->queued_len); if(remaining >=64) { - PCD_SET_EP_RX_CNT(USB, EPindex,64); + pcd_set_ep_rx_cnt(USB, EPindex,64); } else { - PCD_SET_EP_RX_CNT(USB, EPindex,remaining); + pcd_set_ep_rx_cnt(USB, EPindex,remaining); } - PCD_SET_EP_RX_STATUS(USB, EPindex, USB_EP_RX_VALID); + pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); } } /* if((wEPVal & EP_CTR_RX) */ @@ -496,9 +505,9 @@ static uint16_t dcd_ep_ctr_handler(void) if ((wEPVal & USB_EP_CTR_TX) != 0U) // IN { /* clear int flag */ - PCD_CLEAR_TX_EP_CTR(USB, EPindex); + pcd_clear_tx_ep_ctr(USB, EPindex); - xfer_ctl_t * xfer = XFER_CTL_BASE(EPindex,TUSB_DIR_IN); + xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN); if (xfer->queued_len != xfer->total_len) // data remaining in transfer? { @@ -578,33 +587,43 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc // Set type switch(p_endpoint_desc->bmAttributes.xfer) { case TUSB_XFER_CONTROL: - PCD_SET_EPTYPE(USB, epnum, USB_EP_CONTROL); break; - case TUSB_XFER_ISOCHRONOUS: - PCD_SET_EPTYPE(USB, epnum, USB_EP_ISOCHRONOUS); break; + pcd_set_eptype(USB, epnum, USB_EP_CONTROL); + break; +#if (0) + case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported + pcd_set_eptype(USB, epnum, USB_EP_ISOCHRONOUS); break; + break; +#endif + case TUSB_XFER_BULK: - PCD_SET_EPTYPE(USB, epnum, USB_EP_BULK); break; + pcd_set_eptype(USB, epnum, USB_EP_BULK); + break; + case TUSB_XFER_INTERRUPT: - PCD_SET_EPTYPE(USB, epnum, USB_EP_INTERRUPT); break; + pcd_set_eptype(USB, epnum, USB_EP_INTERRUPT); + break; + default: TU_ASSERT(false); + return false; } - PCD_SET_EP_ADDRESS(USB, epnum, epnum); - PCD_CLEAR_EP_KIND(USB,0); // Be normal, for now, instead of only accepting zero-byte packets + pcd_set_ep_address(USB, epnum, epnum); + pcd_clear_ep_kind(USB,0); // Be normal, for now, instead of only accepting zero-byte packets if(dir == TUSB_DIR_IN) { - *PCD_EP_TX_ADDRESS_PTR(USB, epnum) = ep_buf_ptr; - PCD_SET_EP_TX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); - PCD_CLEAR_TX_DTOG(USB, epnum); - PCD_SET_EP_TX_STATUS(USB,epnum,USB_EP_TX_NAK); + *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; + pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); + pcd_clear_tx_dtog(USB, epnum); + pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK); } else { - *PCD_EP_RX_ADDRESS_PTR(USB, epnum) = ep_buf_ptr; - PCD_SET_EP_RX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); - PCD_CLEAR_RX_DTOG(USB, epnum); - PCD_SET_EP_RX_STATUS(USB, epnum, USB_EP_RX_NAK); + *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; + pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); + pcd_clear_rx_dtog(USB, epnum); + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); } ep_buf_ptr = (uint16_t)(ep_buf_ptr + p_endpoint_desc->wMaxPacketSize.size); // increment buffer pointer @@ -622,11 +641,11 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) { len = 64u; } - dcd_write_packet_memory(*PCD_EP_TX_ADDRESS_PTR(USB,ep_ix), &(xfer->buffer[xfer->queued_len]), len); + dcd_write_packet_memory(*pcd_ep_tx_address_ptr(USB,ep_ix), &(xfer->buffer[xfer->queued_len]), len); xfer->queued_len = (uint16_t)(xfer->queued_len + len); - PCD_SET_EP_TX_CNT(USB,ep_ix,len); - PCD_SET_EP_TX_STATUS(USB, ep_ix, USB_EP_TX_VALID); + pcd_set_ep_tx_cnt(USB,ep_ix,len); + pcd_set_ep_tx_status(USB, ep_ix, USB_EP_TX_VALID); } bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) @@ -636,7 +655,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum,dir); + xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = buffer; xfer->total_len = total_bytes; @@ -649,15 +668,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if (epnum == 0 && buffer == NULL) { xfer->buffer = (uint8_t*)_setup_packet; - PCD_SET_EP_KIND(USB,0); // Expect a zero-byte INPUT + pcd_set_ep_kind(USB,0); // Expect a zero-byte INPUT } if(total_bytes > 64) { - PCD_SET_EP_RX_CNT(USB,epnum,64); + pcd_set_ep_rx_cnt(USB,epnum,64); } else { - PCD_SET_EP_RX_CNT(USB,epnum,total_bytes); + pcd_set_ep_rx_cnt(USB,epnum,total_bytes); } - PCD_SET_EP_RX_STATUS(USB, epnum, USB_EP_RX_VALID); + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID); } else // IN { @@ -671,14 +690,14 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) (void)rhport; if (ep_addr == 0) { // CTRL EP0 (OUT for setup) - PCD_SET_EP_TX_STATUS(USB,ep_addr, USB_EP_TX_STALL); + pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_STALL); } if (ep_addr & 0x80) { // IN ep_addr &= 0x7F; - PCD_SET_EP_TX_STATUS(USB,ep_addr, USB_EP_TX_STALL); + pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_STALL); } else { // OUT - PCD_SET_EP_RX_STATUS(USB,ep_addr, USB_EP_RX_STALL); + pcd_set_ep_rx_status(USB,ep_addr, USB_EP_RX_STALL); } } @@ -687,24 +706,24 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) (void)rhport; if (ep_addr == 0) { - PCD_SET_EP_TX_STATUS(USB,ep_addr, USB_EP_TX_NAK); + pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_NAK); } if (ep_addr & 0x80) { // IN ep_addr &= 0x7F; - PCD_SET_EP_TX_STATUS(USB,ep_addr, USB_EP_TX_NAK); + pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_NAK); /* Reset to DATA0 if clearing stall condition. */ - PCD_CLEAR_TX_DTOG(USB,ep_addr); + pcd_clear_tx_dtog(USB,ep_addr); } else { // OUT /* Reset to DATA0 if clearing stall condition. */ - PCD_CLEAR_RX_DTOG(USB,ep_addr); + pcd_clear_rx_dtog(USB,ep_addr); - PCD_SET_EP_RX_STATUS(USB,ep_addr, USB_EP_RX_VALID); + pcd_set_ep_rx_status(USB,ep_addr, USB_EP_RX_VALID); } } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index 586d94abf..2b9de4440 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -83,9 +83,9 @@ // For purposes of accessing the packet #if ((PMA_LENGTH) == 512u) -# define PMA_STRIDE (2u) +const size_t PMA_STRIDE = 2u; #elif ((PMA_LENGTH) == 1024u) -# define PMA_STRIDE (1u) +const size_t PMA_STRIDE = 1u; #endif // And for type-safety create a new macro for the volatile address of PMAADDR @@ -93,32 +93,75 @@ // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; -/* SetENDPOINT */ -#define PCD_SET_ENDPOINT(USBx, bEpNum,wRegValue) (*((__IO uint16_t *)(((uint32_t)(&(USBx)->EP0R + (bEpNum) * 2U))))= (uint16_t)(wRegValue)) -/* GetENDPOINT */ -#define PCD_GET_ENDPOINT(USBx, bEpNum) (*((__IO uint16_t *)(((uint32_t)(&(USBx)->EP0R + (bEpNum) * 2U))))) -#define PCD_SET_EPTYPE(USBx, bEpNum,wType) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ - (((((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & ((uint32_t)(USB_EP_T_MASK))) | ((uint32_t)(wType))) | USB_EP_CTR_RX | USB_EP_CTR_TX))) -#define PCD_GET_EPTYPE(USBx, bEpNum) (((uint16_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EP_T_FIELD) +// prototypes +static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum); +static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum); +static inline void pcd_set_endpoint(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wRegValue); + +/* SetENDPOINT */ +static inline void pcd_set_endpoint(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wRegValue) +{ + __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpNum*2u); + *reg = (uint16_t)wRegValue; +} + +/* GetENDPOINT */ +static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, unsigned int bEpNum) { + __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpNum*2u); + return *reg; +} + +static inline void pcd_set_eptype(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wType) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= (uint32_t)USB_EP_T_MASK; + regVal |= wType; + regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high + pcd_set_endpoint(USBx, bEpNum, regVal); +} + +static inline unsigned int pcd_get_eptype(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EP_T_FIELD; + return regVal; +} /** * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. * @param USBx USB peripheral instance register address. * @param bEpNum Endpoint Number. * @retval None */ -#define PCD_CLEAR_RX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ - PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0x7FFFU & USB_EPREG_MASK)) -#define PCD_CLEAR_TX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ - PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0xFF7FU & USB_EPREG_MASK)) +static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= 0x7FFFu & USB_EPREG_MASK; + pcd_set_endpoint(USBx, bEpNum, regVal); +} +static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= regVal & 0xFF7FU & USB_EPREG_MASK; + pcd_set_endpoint(USBx, bEpNum,regVal); +} /** * @brief gets counter of the tx buffer. * @param USBx USB peripheral instance register address. * @param bEpNum Endpoint Number. * @retval Counter value */ -#define PCD_GET_EP_TX_CNT(USBx, bEpNum)((uint16_t)(*PCD_EP_TX_CNT_PTR((USBx), (bEpNum))) & 0x3ffU) -#define PCD_GET_EP_RX_CNT(USBx, bEpNum)((uint16_t)(*PCD_EP_RX_CNT_PTR((USBx), (bEpNum))) & 0x3ffU) +static inline unsigned int pcd_get_ep_tx_cnt(USB_TypeDef * USBx, unsigned int bEpNum) +{ + __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpNum); + return *regPtr & 0x3ffU; +} + +static inline unsigned int pcd_get_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bEpNum) +{ + __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpNum); + return *regPtr & 0x3ffU; +} /** * @brief Sets counter of rx buffer with no. of blocks. @@ -127,38 +170,30 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param wNBlocks no. of Blocks. * @retval None */ -#define PCD_CALC_BLK32(dwReg,wCount,wNBlocks) {\ - (wNBlocks) = (uint32_t)((wCount) >> 5U);\ - if(((wCount) & 0x1fU) == 0U)\ - { \ - (wNBlocks)--;\ - } \ - *pdwReg = (uint16_t)((uint16_t)((wNBlocks) << 10U) | (uint16_t)0x8000U); \ - }/* PCD_CALC_BLK32 */ - - -#define PCD_CALC_BLK2(dwReg,wCount,wNBlocks) {\ - (wNBlocks) = (uint32_t)((wCount) >> 1U); \ - if(((wCount) & 0x1U) != 0U)\ - { \ - (wNBlocks)++;\ - } \ - *pdwReg = (uint16_t)((wNBlocks) << 10U);\ - }/* PCD_CALC_BLK2 */ - - -#define PCD_SET_EP_CNT_RX_REG(dwReg,wCount) {\ - uint32_t wNBlocks;\ - if((wCount) > 62U) \ - { \ - PCD_CALC_BLK32((dwReg),(wCount),wNBlocks) \ - } \ - else \ - { \ - PCD_CALC_BLK2((dwReg),(wCount),wNBlocks) \ - } \ - }/* PCD_SET_EP_CNT_RX_REG */ +static inline void pcd_set_ep_cnt_rx_reg(__O uint16_t * pdwReg, size_t wCount) { + unsigned int wNBlocks; + if(wCount > 62u) + { + wNBlocks = wCount >> 5u; + if((wCount & 0x1fU) == 0u) + { + wNBlocks--; + } + wNBlocks = wNBlocks << 10u; + wNBlocks |= 0x8000u; // Mark block size as 32byte + *pdwReg = (uint16_t)wNBlocks; + } + else + { + wNBlocks = wCount >> 1u; + if((wCount & 0x1U) != 0u) + { + wNBlocks++; + } + *pdwReg = (uint16_t)((wNBlocks) << 10u); + } +} /** @@ -168,23 +203,52 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param bAddr Address. * @retval None */ -#define PCD_SET_EP_ADDRESS(USBx, bEpNum,bAddr) PCD_SET_ENDPOINT((USBx), (bEpNum),\ - USB_EP_CTR_RX|USB_EP_CTR_TX|(((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPREG_MASK) | (bAddr)) +static inline void pcd_set_ep_address(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int bAddr) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPREG_MASK; + regVal |= bAddr; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpNum,regVal); +} -#define PCD_BTABLE_WORD_PTR(USBx,x) (&(pma[PMA_STRIDE*((((USBx)->BTABLE)>>1) + x)])) +static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) +{ + size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; + total_word_offset *= PMA_STRIDE; + return &(pma[total_word_offset]); +} // Pointers to the PMA table entries (using the ARM address space) -#define PCD_EP_TX_ADDRESS_PTR(USBx, bEpNum) (PCD_BTABLE_WORD_PTR(USBx,(bEpNum)*4u + 0u)) -#define PCD_EP_TX_CNT_PTR(USBx, bEpNum) (PCD_BTABLE_WORD_PTR(USBx,(bEpNum)*4u + 1u)) +static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 0u); +} +static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 1u); +} -#define PCD_EP_RX_ADDRESS_PTR(USBx, bEpNum) (PCD_BTABLE_WORD_PTR(USBx,(bEpNum)*4u + 2u)) -#define PCD_EP_RX_CNT_PTR(USBx, bEpNum) (PCD_BTABLE_WORD_PTR(USBx,(bEpNum)*4u + 3u)) +static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 2u); +} -#define PCD_SET_EP_TX_CNT(USBx, bEpNum,wCount) (*PCD_EP_TX_CNT_PTR((USBx), (bEpNum)) = (wCount)) -#define PCD_SET_EP_RX_CNT(USBx, bEpNum,wCount) do {\ - __IO uint16_t *pdwReg =PCD_EP_RX_CNT_PTR((USBx),(bEpNum)); \ - PCD_SET_EP_CNT_RX_REG((pdwReg), (wCount))\ - } while(0) +static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +{ + return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 3u); +} + +static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wCount) +{ + *pcd_ep_tx_cnt_ptr(USBx, bEpNum) = (uint16_t)wCount; +} + +static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wCount) +{ + __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpNum)); + pcd_set_ep_cnt_rx_reg(pdwReg, wCount); +} /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). @@ -193,21 +257,24 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param wState new state * @retval None */ -#define PCD_SET_EP_TX_STATUS(USBx, bEpNum, wState) { register uint16_t _wRegVal;\ - \ - _wRegVal = (uint32_t) (((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPTX_DTOGMASK);\ - /* toggle first bit ? */ \ - if((USB_EPTX_DTOG1 & (wState))!= 0U)\ - { \ - _wRegVal ^=(uint16_t) USB_EPTX_DTOG1; \ - } \ - /* toggle second bit ? */ \ - if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U) \ - { \ - _wRegVal ^=(uint16_t) USB_EPTX_DTOG2; \ - } \ - PCD_SET_ENDPOINT((USBx), (bEpNum), (((uint32_t)(_wRegVal)) | USB_EP_CTR_RX|USB_EP_CTR_TX));\ - } /* PCD_SET_EP_TX_STATUS */ +static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wState) +{ + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPTX_DTOGMASK; + + /* toggle first bit ? */ + if((USB_EPTX_DTOG1 & (wState))!= 0U) + { + regVal ^= USB_EPTX_DTOG1; + } + /* toggle second bit ? */ + if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U) + { + regVal ^= USB_EPTX_DTOG2; + } + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} /* pcd_set_ep_tx_status */ /** * @brief sets the status for rx transfer (bits STAT_TX[1:0]) @@ -216,22 +283,25 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param wState new state * @retval None */ -#define PCD_SET_EP_RX_STATUS(USBx, bEpNum,wState) {\ - register uint16_t _wRegVal; \ - \ - _wRegVal = (uint32_t) (((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPRX_DTOGMASK);\ - /* toggle first bit ? */ \ - if((USB_EPRX_DTOG1 & (wState))!= 0U) \ - { \ - _wRegVal ^= (uint16_t) USB_EPRX_DTOG1; \ - } \ - /* toggle second bit ? */ \ - if((USB_EPRX_DTOG2 & ((uint32_t)(wState)))!= 0U) \ - { \ - _wRegVal ^= (uint16_t) USB_EPRX_DTOG2; \ - } \ - PCD_SET_ENDPOINT((USBx), (bEpNum), (((uint32_t)(_wRegVal)) | USB_EP_CTR_RX|USB_EP_CTR_TX)); \ - } /* PCD_SET_EP_RX_STATUS */ + +static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wState) +{ + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPRX_DTOGMASK; + + /* toggle first bit ? */ + if((USB_EPRX_DTOG1 & wState)!= 0U) + { + regVal ^= USB_EPRX_DTOG1; + } + /* toggle second bit ? */ + if((USB_EPRX_DTOG2 & wState)!= 0U) + { + regVal ^= USB_EPRX_DTOG2; + } + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} /* pcd_set_ep_rx_status */ /** * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. @@ -239,10 +309,21 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param bEpNum Endpoint Number. * @retval None */ -#define PCD_RX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ - USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX | (((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPREG_MASK))) -#define PCD_TX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ - USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX | (((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPREG_MASK))) +static inline void pcd_rx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} + +static inline void pcd_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} /** * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. @@ -250,14 +331,24 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param bEpNum Endpoint Number. * @retval None */ -#define PCD_CLEAR_RX_DTOG(USBx, bEpNum) if((((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EP_DTOG_RX) != 0)\ - { \ - PCD_RX_DTOG((USBx),(bEpNum));\ - } -#define PCD_CLEAR_TX_DTOG(USBx, bEpNum) if((((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EP_DTOG_TX) != 0)\ - {\ - PCD_TX_DTOG((USBx),(bEpNum));\ - } + +static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + if((regVal & USB_EP_DTOG_RX) != 0) + { + pcd_rx_dtog(USBx,bEpNum); + } +} + +static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + if((regVal & USB_EP_DTOG_TX) != 0) + { + pcd_tx_dtog(USBx,bEpNum); + } +} /** * @brief set & clear EP_KIND bit. @@ -265,11 +356,22 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; * @param bEpNum Endpoint Number. * @retval None */ -#define PCD_SET_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ - (USB_EP_CTR_RX|USB_EP_CTR_TX|((((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) | USB_EP_KIND) & USB_EPREG_MASK)))) -#define PCD_CLEAR_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ - (USB_EP_CTR_RX|USB_EP_CTR_TX|((((uint32_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)))) & USB_EPKIND_MASK))))) +static inline void pcd_set_ep_kind(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal |= USB_EP_KIND; + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} +static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, unsigned int bEpNum) +{ + unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + regVal &= USB_EPKIND_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpNum, regVal); +} // This checks if the device has "LPM" #if defined(USB_ISTR_L1REQ) @@ -282,6 +384,6 @@ static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) // Number of endpoints in hardware -#define STFSDEV_EP_COUNT (8) +#define STFSDEV_EP_COUNT (8u) #endif /* PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ */ From 05c13342a3e176f36532b1d2a9e39fa8318a8094 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 23:51:42 -0400 Subject: [PATCH 22/94] Implement EP with size <64. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 452c9a92e..cafdd578e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -154,16 +154,13 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LEN TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); -// Max size of a USB FS packet is 64... -#define MAX_PACKET_SIZE 64 - - // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { uint8_t * buffer; uint16_t total_len; uint16_t queued_len; + uint16_t max_packet_size; } xfer_ctl_t; static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; @@ -357,7 +354,7 @@ static void dcd_handle_bus_reset(void) // FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed. static uint16_t dcd_ep_ctr_handler(void) { - uint16_t count=0U; + unsigned int count=0U; uint8_t EPindex; __IO uint16_t wIstr; __IO uint16_t wEPVal = 0U; @@ -390,7 +387,7 @@ static uint16_t dcd_ep_ctr_handler(void) { // Delayed setting of the DADDR after the 0-len DATA packet acking the request is sent. reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); - USB->DADDR |= (uint16_t)newDADDR; // leave the enable bit set + USB->DADDR = (uint16_t)(USB->DADDR | newDADDR); // leave the enable bit set newDADDR = 0; } if(xfer->total_len == 0) // Probably a status message? @@ -481,7 +478,7 @@ static uint16_t dcd_ep_ctr_handler(void) /*multi-packet on the NON control OUT endpoint */ xfer->queued_len = (uint16_t)(xfer->queued_len + count); - if ((count < 64) || (xfer->queued_len == xfer->total_len)) + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { /* RX COMPLETE */ dcd_event_xfer_complete(0, EPindex, xfer->queued_len, XFER_RESULT_SUCCESS, true); @@ -490,9 +487,9 @@ static uint16_t dcd_ep_ctr_handler(void) } else { - uint16_t remaining = (uint16_t)(xfer->total_len - xfer->queued_len); - if(remaining >=64) { - pcd_set_ep_rx_cnt(USB, EPindex,64); + uint32_t remaining = (uint32_t)xfer->total_len - (uint32_t)xfer->queued_len; + if(remaining >= xfer->max_packet_size) { + pcd_set_ep_rx_cnt(USB, EPindex,xfer->max_packet_size); } else { pcd_set_ep_rx_cnt(USB, EPindex,remaining); } @@ -575,14 +572,33 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc (void)rhport; uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - + const uint16_t epMaxPktSize = p_endpoint_desc->wMaxPacketSize.size; // Isochronous not supported (yet), and some other driver assumptions. +#ifndef NDEBUG TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - TU_ASSERT(p_endpoint_desc->wMaxPacketSize.size <= MAX_PACKET_SIZE); TU_ASSERT(epnum < MAX_EP_COUNT); - TU_ASSERT((p_endpoint_desc->wMaxPacketSize.size %2) == 0); - // __IO uint16_t * const epreg = &(EPREG(epnum)); + switch(p_endpoint_desc->bmAttributes.xfer) { + case TUSB_XFER_CONTROL: + // USB 2.0 spec on FS packets, 5.5.3 (control) + TU_ASSERT((epMaxPktSize == 8) ||(epMaxPktSize == 16) || (epMaxPktSize == 32) || (epMaxPktSize == 64)); + break; + case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported + TU_ASSERT(epMaxPktSize <= 1023); + break; + case TUSB_XFER_BULK: + // USB 2.0 spec on FS packets, 5.8.3 (bulk) + TU_ASSERT((epMaxPktSize == 8) ||(epMaxPktSize == 16) ||(epMaxPktSize == 32) ||(epMaxPktSize == 64)); + break; + case TUSB_XFER_INTERRUPT: + // USB 2.0 spec on FS packets, 5.5.3 (interrupt); interestingly 0 is allowed. + TU_ASSERT(epMaxPktSize <= 64); + break; + default: + TU_ASSERT(false); + return false; + } +#endif // Set type switch(p_endpoint_desc->bmAttributes.xfer) { @@ -626,6 +642,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); } + xfer_ctl_ptr(epnum, dir)->max_packet_size = epMaxPktSize; ep_buf_ptr = (uint16_t)(ep_buf_ptr + p_endpoint_desc->wMaxPacketSize.size); // increment buffer pointer return true; @@ -637,11 +654,12 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if(len > 64u) // max packet size for FS transfer + if(len > xfer->max_packet_size) // max packet size for FS transfer { - len = 64u; + len = xfer->max_packet_size; } - dcd_write_packet_memory(*pcd_ep_tx_address_ptr(USB,ep_ix), &(xfer->buffer[xfer->queued_len]), len); + uint16_t oldAddr = *pcd_ep_tx_address_ptr(USB,ep_ix); + dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); xfer->queued_len = (uint16_t)(xfer->queued_len + len); pcd_set_ep_tx_cnt(USB,ep_ix,len); @@ -670,9 +688,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->buffer = (uint8_t*)_setup_packet; pcd_set_ep_kind(USB,0); // Expect a zero-byte INPUT } - if(total_bytes > 64) + if(total_bytes > xfer->max_packet_size) { - pcd_set_ep_rx_cnt(USB,epnum,64); + pcd_set_ep_rx_cnt(USB,epnum,xfer->max_packet_size); } else { pcd_set_ep_rx_cnt(USB,epnum,total_bytes); } @@ -740,16 +758,17 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) */ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) { - uint32_t n = ((uint32_t)((uint32_t)wNBytes + 1U)) >> 1U; + uint32_t n = ((uint32_t)wNBytes + 1U) >> 1U; uint32_t i; uint16_t temp1, temp2; const uint8_t * srcVal; -#ifdef DEBUG +#ifndef NDEBUG # if (DCD_STM32_BTABLE_BASE > 0u) TU_ASSERT(dst >= DCD_STM32_BTABLE_BASE); # endif - TU_ASSERT(((dst%2) == 0) && (dst + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); + TU_ASSERT((dst%2) == 0); + TU_ASSERT((dst + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); #endif // The GCC optimizer will combine access to 32-bit sizes if we let it. Force @@ -786,11 +805,12 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN __IO const uint16_t *pdwVal; uint32_t temp; -#ifdef DEBUG +#ifndef NDEBUG # if (DCD_STM32_BTABLE_BASE > 0u) TU_ASSERT(src >= DCD_STM32_BTABLE_BASE); # endif - TU_ASSERT(((src%2) == 0) && (src + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); + TU_ASSERT((src%2) == 0); + TU_ASSERT((src + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); #endif From 9c5ae0369b2113ca3c7c8ac1240315ac1e7f1190 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 11:13:17 +0700 Subject: [PATCH 23/94] follow up to suggestion to pr 155 --- src/common/tusb_types.h | 3 ++- src/device/usbd.c | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a50e89934..ad42baad7 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -125,7 +125,8 @@ typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, - TUSB_REQ_TYPE_VENDOR + TUSB_REQ_TYPE_VENDOR, + TUSB_REQ_TYPE_INVALID } tusb_request_type_t; typedef enum diff --git a/src/device/usbd.c b/src/device/usbd.c index c92884334..0366d1ece 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -62,7 +62,7 @@ typedef struct { static usbd_device_t _usbd_dev = { 0 }; // Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xff }; +enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver @@ -349,6 +349,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { @@ -470,7 +472,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // GET HID REPORT DESCRIPTOR falls into this case // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); break; } }else @@ -478,7 +481,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // forward to class driver: "non-STD request to Interface" // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); } } break; @@ -499,7 +503,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // We will forward all request targeted endpoint to its class driver // - For non-standard request: driver can ACK or Stall the request by return true/false // - For standard request: usbd decide the ACK stage regardless of driver return value - bool ret; + bool ret = false; if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { @@ -507,8 +511,11 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete); } - // Invoke class driver first - ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + // Invoke class driver first if available + if ( usbd_class_drivers[drv_id].control_request ) + { + ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + } // Then handle if it is standard request if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) From a37d2d64beaea07d17b24d8b61bfa09b89ee5bba Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 13:32:47 +0700 Subject: [PATCH 24/94] fix #143 --- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 2b49f52e9..d5f90d2a7 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -293,7 +293,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) break; case TUSB_XFER_ISOCHRONOUS: - TU_ASSERT((epnum % 3) == 3 && (epnum != 15)); + TU_ASSERT((epnum % 3) == 0 && (epnum != 0) && (epnum != 15)); break; default: From 6b9783ceadf36d6507a624b8413adf9686d6e541 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 09:20:15 -0400 Subject: [PATCH 25/94] s/unsigned int/uint32_t/ --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 +- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 76 +++++++++---------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cafdd578e..d3cbef43c 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -165,7 +165,7 @@ typedef struct static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; -static xfer_ctl_t* xfer_ctl_ptr(unsigned int epnum, unsigned int dir) +static xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) { #ifndef NDEBUG TU_ASSERT(epnum < MAX_EP_COUNT); @@ -354,7 +354,7 @@ static void dcd_handle_bus_reset(void) // FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed. static uint16_t dcd_ep_ctr_handler(void) { - unsigned int count=0U; + uint32_t count=0U; uint8_t EPindex; __IO uint16_t wIstr; __IO uint16_t wEPVal = 0U; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index 2b9de4440..e205979fc 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -94,36 +94,36 @@ const size_t PMA_STRIDE = 1u; static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; // prototypes -static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum); -static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum); -static inline void pcd_set_endpoint(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wRegValue); +static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpNum); +static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpNum); +static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wRegValue); /* SetENDPOINT */ -static inline void pcd_set_endpoint(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wRegValue) +static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wRegValue) { __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpNum*2u); *reg = (uint16_t)wRegValue; } /* GetENDPOINT */ -static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, unsigned int bEpNum) { +static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpNum) { __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpNum*2u); return *reg; } -static inline void pcd_set_eptype(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wType) +static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wType) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= (uint32_t)USB_EP_T_MASK; regVal |= wType; regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high pcd_set_endpoint(USBx, bEpNum, regVal); } -static inline unsigned int pcd_get_eptype(USB_TypeDef * USBx, unsigned int bEpNum) +static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EP_T_FIELD; return regVal; } @@ -133,15 +133,15 @@ static inline unsigned int pcd_get_eptype(USB_TypeDef * USBx, unsigned int bEpNu * @param bEpNum Endpoint Number. * @retval None */ -static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= 0x7FFFu & USB_EPREG_MASK; pcd_set_endpoint(USBx, bEpNum, regVal); } -static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= regVal & 0xFF7FU & USB_EPREG_MASK; pcd_set_endpoint(USBx, bEpNum,regVal); } @@ -151,13 +151,13 @@ static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, unsigned int bEpNum) * @param bEpNum Endpoint Number. * @retval Counter value */ -static inline unsigned int pcd_get_ep_tx_cnt(USB_TypeDef * USBx, unsigned int bEpNum) +static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpNum) { __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpNum); return *regPtr & 0x3ffU; } -static inline unsigned int pcd_get_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bEpNum) +static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpNum) { __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpNum); return *regPtr & 0x3ffU; @@ -172,7 +172,7 @@ static inline unsigned int pcd_get_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bE */ static inline void pcd_set_ep_cnt_rx_reg(__O uint16_t * pdwReg, size_t wCount) { - unsigned int wNBlocks; + uint32_t wNBlocks; if(wCount > 62u) { wNBlocks = wCount >> 5u; @@ -203,9 +203,9 @@ static inline void pcd_set_ep_cnt_rx_reg(__O uint16_t * pdwReg, size_t wCount) * @param bAddr Address. * @retval None */ -static inline void pcd_set_ep_address(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int bAddr) +static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t bAddr) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPREG_MASK; regVal |= bAddr; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; @@ -220,31 +220,31 @@ static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) } // Pointers to the PMA table entries (using the ARM address space) -static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpNum) { return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 0u); } -static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpNum) { return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 1u); } -static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpNum) { return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 2u); } -static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, unsigned int bEpNum) +static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpNum) { return pcd_btable_word_ptr(USBx,(bEpNum)*4u + 3u); } -static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wCount) +static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wCount) { *pcd_ep_tx_cnt_ptr(USBx, bEpNum) = (uint16_t)wCount; } -static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wCount) +static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wCount) { __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpNum)); pcd_set_ep_cnt_rx_reg(pdwReg, wCount); @@ -257,7 +257,7 @@ static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, unsigned int bEpNum, u * @param wState new state * @retval None */ -static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wState) +static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPTX_DTOGMASK; @@ -284,7 +284,7 @@ static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, unsigned int bEpNum * @retval None */ -static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, unsigned int bEpNum, unsigned int wState) +static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpNum, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPRX_DTOGMASK; @@ -309,17 +309,17 @@ static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, unsigned int bEpNum * @param bEpNum Endpoint Number. * @retval None */ -static inline void pcd_rx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; pcd_set_endpoint(USBx, bEpNum, regVal); } -static inline void pcd_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; pcd_set_endpoint(USBx, bEpNum, regVal); @@ -332,18 +332,18 @@ static inline void pcd_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) * @retval None */ -static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); if((regVal & USB_EP_DTOG_RX) != 0) { pcd_rx_dtog(USBx,bEpNum); } } -static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); if((regVal & USB_EP_DTOG_TX) != 0) { pcd_tx_dtog(USBx,bEpNum); @@ -357,17 +357,17 @@ static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, unsigned int bEpNum) * @retval None */ -static inline void pcd_set_ep_kind(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal |= USB_EP_KIND; regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpNum, regVal); } -static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, unsigned int bEpNum) +static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpNum) { - unsigned int regVal = pcd_get_endpoint(USBx, bEpNum); + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); regVal &= USB_EPKIND_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpNum, regVal); From dfe92542e63af0032c5f9b0fcd14a5f5971f78fe Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 11:27:05 -0400 Subject: [PATCH 26/94] Change inline functions to macros, and make all parameter names uniform. --- src/common/tusb_compiler.h | 58 +++++++++++++++----------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index df0326afd..58732b871 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -75,17 +75,8 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } - - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } - - #define TU_BSWAP16 +#define TU_BSWAP16(u16) (__builtin_bswap16(u16)) +#define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__TI_COMPILER_VERSION__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -103,44 +94,41 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } + #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) + #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } #else #error "Compiler attribute porting is required" #endif #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) - #define tu_htonl(u32) tu_bswap32(u32) - #define tu_ntohl(u32) tu_bswap32(u32) - #define tu_htons(u16) tu_bswap16(u16) - #define tu_ntohs(u16) tu_bswap16(u16) + #define tu_htons(u16) (TU_BSWAP16(u16)) + #define tu_ntohs(u16) (TU_BSWAP16(u16)) - #define tu_htole16(x) (x) - #define tu_le16toh(x) (x) + #define tu_htonl(u32) (TU_BSWAP32(u32)) + #define tu_ntohl(u32) (TU_BSWAP32(u32)) - #define tu_htole32(x) (x) - #define tu_le32toh(x) (x) + #define tu_htole16(u16) (u16) + #define tu_le16toh(u16) (u16) + + #define tu_htole32(u32) (u32) + #define tu_le32toh(u32) (u32) #elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) - #define tu_htonl(u32) (x) - #define tu_ntohl(u32) (x) - #define tu_htons(u16) (x) - #define tu_ntohs(u16) (x) + #define tu_htons(u16) (u16) + #define tu_ntohs(u16) (u16) - #define tu_htole16(x) tu_bswap16(u32) - #define tu_le16toh(x) tu_bswap16(u32) + #define tu_htonl(u32) (u32) + #define tu_ntohl(u32) (u32) - #define tu_htole32(x) tu_bswap32(u32) - #define tu_le32toh(x) tu_bswap32(u32) + + #define tu_htole16(u16) (tu_bswap16(u16)) + #define tu_le16toh(u16) (tu_bswap16(u16)) + + #define tu_htole32(u32) (tu_bswap32(u32)) + #define tu_le32toh(u32) (tu_bswap32(u32)) #else #error Byte order is undefined From 13f7121285946eb32965f1bffac7a8ccb656ecad Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 23:42:56 +0700 Subject: [PATCH 27/94] add pyboard v1.1 link to bsp --- docs/boards.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/boards.md b/docs/boards.md index 30b0eb958..5e33c3ee3 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -41,6 +41,7 @@ This code base already had supported for a handful of following boards ### ST STM32 +- [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1) - [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) - [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) - [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) From d341337c6a80622c22fc002b35a65b40bdf15b4b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 20:25:50 -0400 Subject: [PATCH 28/94] Implement remote wakeup + perhaps better sleep? --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index d3cbef43c..0559a4087 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -308,6 +308,17 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; + uint32_t start; + + USB->CNTR |= (uint16_t)USB_CNTR_RESUME; + /* Wait 1 to 15 ms */ + /* Busy loop is bad, but the osal_task_delay() isn't implemented for the "none" OSAL */ + start = board_millis(); + while ((board_millis() - start) < 2) + { + ; + } + USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); } // I'm getting a weird warning about missing braces here that I don't @@ -538,10 +549,10 @@ static void dcd_fs_irqHandler(void) { } if (int_status & USB_ISTR_WKUP) { - reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); reg16_clear_bits(&USB->ISTR, USB_ISTR_WKUP); + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } if (int_status & USB_ISTR_SUSP) @@ -552,6 +563,7 @@ static void dcd_fs_irqHandler(void) { /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ reg16_clear_bits(&USB->ISTR, USB_ISTR_SUSP); + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } if(int_status & USB_ISTR_SOF) { From a33a8547936ccea0cfcbba8823c44cae8a887269 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 20:56:57 -0400 Subject: [PATCH 29/94] Include board header file... :X --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0559a4087..00a016e3b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -121,6 +121,7 @@ #undef USE_HAL_DRIVER #include "device/dcd.h" +#include "bsp/board.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" From 89ffe78f84fe9771f23b51e60e539cec236a1704 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 22:56:17 -0400 Subject: [PATCH 30/94] ST FSDEV: No need to always reset the interrupt priority, also add some synchronization primitives after disabling interrupts. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 00a016e3b..e2df2abe4 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -258,12 +258,8 @@ void dcd_int_enable (uint8_t rhport) { (void)rhport; #if defined(STM32F0) - NVIC_SetPriority(USB_IRQn, 0); NVIC_EnableIRQ(USB_IRQn); #elif defined(STM32F3) - NVIC_SetPriority(USB_HP_CAN_TX_IRQn, 0); - NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 0); - NVIC_SetPriority(USBWakeUp_IRQn, 0); NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); @@ -283,6 +279,10 @@ void dcd_int_disable(uint8_t rhport) #else #error Unknown arch in USB driver #endif + // I'm not convinced that memory synchronization is completely necessary, but + // it isn't a bad idea. + __DSB(); + __ISB(); } // Receive Set Address request, mcu port must also include status IN response From 915f52730d4bd91642bfcf74a8ebfb18536517e9 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 11:28:29 -0400 Subject: [PATCH 31/94] Implement HID desc request. --- src/class/hid/hid_device.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 572f2cad2..2d579f475 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -202,7 +202,29 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque uint8_t const desc_index = tu_u16_low (p_request->wValue); (void) desc_index; - if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) + if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) + { + // FIXME: Should check which is the active configuration, but no callback in usbd currently exists to do that + tusb_desc_configuration_t const* desc_cfg = + (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(0); + uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; + + while( p_desc < desc_end ) + { + tusb_hid_descriptor_hid_t *p_desc_hid =(tusb_hid_descriptor_hid_t*)p_desc; + if(p_desc_hid->bDescriptorType == HID_DESC_TYPE_HID) { + tud_control_xfer(rhport, p_request, (void*) p_desc_hid, p_desc_hid->bLength); + break; + } + p_desc += p_desc_hid->bLength; // next desc + } + if(p_desc >= desc_end) + { + return false; + } + } + else if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { uint8_t const * desc_report = tud_hid_descriptor_report_cb(); tud_control_xfer(rhport, p_request, (void*) desc_report, p_hid->reprot_desc_len); From c755aee7d0c1e2486055e02ac353878d8da3ba59 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 22:55:42 -0400 Subject: [PATCH 32/94] Clear --- examples/device/usbtmc/src/usbtmc_app.c | 44 +++++--- src/class/usbtmc/usbtmc.h | 94 +++++++++++------ src/class/usbtmc/usbtmc_device.c | 135 +++++++++++++++--------- src/class/usbtmc/usbtmc_device.h | 4 + 4 files changed, 182 insertions(+), 95 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index af97939b9..a41d911d2 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -97,7 +97,9 @@ bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) { (void)rhport; - (void)transfer_complete; + + // If transfer isn't finished, we just ignore it (for now) + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; } @@ -107,26 +109,24 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; + + status &= (uint8_t)~(0x10u); // clear MAV + return true; } -static uint8_t noQueryMsg[] = "ERR: No query\n"; - bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; - if(queryState != 0) - { - TU_ASSERT(bulkInStarted == 0); - bulkInStarted = 1; - } - else - { - rspMsg.TransferSize = sizeof(noQueryMsg)-1; - usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, noQueryMsg); - } + + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; + + // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message + // that expects a response, the device must NAK the request + // Always return true indicating not to stall the EP. return true; } @@ -157,12 +157,28 @@ void usbtmc_app_task_iter(void) { bulkInStarted = 0; rspMsg.TransferSize = sizeof(idn)-1; usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); - status &= ~(0x10u); // MAV + // MAV is cleared in the transfer complete callback. } break; + default: + TU_ASSERT(false,); + return; } } +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; +} + +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { + (void)rhport; + rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp->bmClear.BulkInFifoBytes = 0u; + return true; +} + // Return status byte, but put the transfer result status code in the rspResult argument. uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index ecc16a315..d24a72cb6 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -73,53 +73,67 @@ typedef struct TU_ATTR_PACKED typedef struct TU_ATTR_PACKED { usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first - struct { - uint8_t EOM : 1 ; ///< EOM set on last byte + struct TU_ATTR_PACKED + { + unsigned int EOM : 1 ; ///< EOM set on last byte } bmTransferAttributes; uint8_t _reserved[3]; } usbtmc_msg_request_dev_dep_out; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); + // Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first - struct { - uint8_t : 0; - uint8_t TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar + struct TU_ATTR_PACKED + { + unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar } bmTransferAttributes; uint8_t TermChar; uint8_t _reserved[2]; } usbtmc_msg_request_dev_dep_in; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); + /* Bulk-in headers */ typedef struct TU_ATTR_PACKED { usbtmc_msg_header_t header; uint32_t TransferSize; - struct { + struct TU_ATTR_PACKED + { uint8_t EOM: 1; ///< Last byte of transfer is the end of the message uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar } bmTransferAttributes; uint8_t _reserved[3]; } usbtmc_msg_dev_dep_msg_in_header_t; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); /* Unsupported vendor things.... Are these ever used?*/ -typedef struct TU_ATTR_PACKED { +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first uint8_t _reserved[4]; } usbtmc_msg_request_vendor_specific_out; -typedef struct TU_ATTR_PACKED { +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first uint8_t _reserved[4]; } usbtmc_msg_request_vendor_specific_in; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); + // Control request type should use tusb_control_request_t /* @@ -187,13 +201,15 @@ typedef struct TU_ATTR_PACKED { uint8_t _reserved; uint16_t bcdUSBTMC; ///< USBTMC_VERSION - struct { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; + struct TU_ATTR_PACKED + { + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; } bmIntfcCapabilities; - struct { - uint8_t canEndBulkInOnTermChar :1; + struct TU_ATTR_PACKED + { + unsigned int canEndBulkInOnTermChar :1; } bmDevCapabilities; uint8_t _reserved2[6]; uint8_t _reserved3[12]; @@ -201,40 +217,51 @@ typedef struct TU_ATTR_PACKED { TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes :1; + } bmClear; +} usbtmc_get_clear_status_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum uint8_t _reserved; uint16_t bcdUSBTMC; ///< USBTMC_VERSION - struct + struct TU_ATTR_PACKED { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; } bmIntfcCapabilities; - struct + struct TU_ATTR_PACKED { - uint8_t canEndBulkInOnTermChar :1; + unsigned int canEndBulkInOnTermChar :1; } bmDevCapabilities; uint8_t _reserved2[6]; uint16_t bcdUSB488; - struct + struct TU_ATTR_PACKED { - uint8_t is488_2 :1; - uint8_t supportsREN_GTL_LLO :1; - uint8_t supportsTrigger :1; + unsigned int is488_2 :1; + unsigned int supportsREN_GTL_LLO :1; + unsigned int supportsTrigger :1; } bmIntfcCapabilities488; - struct + struct TU_ATTR_PACKED { - uint8_t SCPI :1; - uint8_t SR1 :1; - uint8_t RL1 :1; - uint8_t DT1 :1; + unsigned int SCPI :1; + unsigned int SR1 :1; + unsigned int RL1 :1; + unsigned int DT1 :1; } bmDevCapabilities488; uint8_t _reserved3[8]; } usbtmc_response_capabilities_488_t; @@ -253,14 +280,15 @@ TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length") typedef struct TU_ATTR_PACKET { union { - struct { - uint8_t bTag : 7; - uint8_t one : 1; + struct TU_ATTR_PACKED { + unsigned int bTag : 7; + unsigned int one : 1; } bNotify1Struct; uint8_t bNotify1; }; uint8_t StatusByte; } usbtmc_read_stb_interrupt_488_t; + TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); #endif diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index db0c95a32..7264125bb 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -170,6 +170,9 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 uint8_t const * p_desc; uint8_t found_endpoints = 0; + + usbtmcd_reset(rhport); + // Perhaps there are other application specific class drivers, so don't assert here. if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) return false; @@ -232,6 +235,12 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 void usbtmcd_reset(uint8_t rhport) { // FIXME: Do endpoints need to be closed here? + usbtmc_state.state = STATE_IDLE; + usbtmc_state.itf_id = 0xFF; + usbtmc_state.ep_bulk_in = 0; + usbtmc_state.ep_bulk_out = 0; + usbtmc_state.ep_int_in = 0; + (void)rhport; } @@ -376,15 +385,19 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { + uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (USBTMC_CFG_ENABLE_488) ushort bTag; #endif // We only handle class requests, IN direction. + // (for now) if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) { return false; } + // Verification that we own the interface is unneeded since it's been routed to us specifically. + switch(request->bRequest) { // USBTMC required requests @@ -392,74 +405,100 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(false); - break; + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } case USBTMC_bREQUEST_INITIATE_CLEAR: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the + // control endpoint response shown in Table 31, and clear all input buffers and output buffers. + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + return true; + } + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - break; + { + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); + TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + return true; + } case USBTMC_bREQUEST_GET_CAPABILITIES: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wValue == 0x0000); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); - return true; + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + return true; + } // USBTMC Optional Requests case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - uint8_t tmcResult; - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcResult)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcResult, sizeof(tmcResult))); - - return true; - + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); + return true; + } #if (USBTMC_CFG_ENABLE_488) + // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - usbtmc_read_stb_rsp_488_t rsp; - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. + usbtmc_read_stb_rsp_488_t rsp; + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - usbtmc_read_stb_interrupt_488_t intMsg = + bTag = request->wValue & 0x7F; + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero + TU_VERIFY(bTag >= 0x02 && bTag <= 127); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == 0x0003); + rsp.bTag = (uint8_t)bTag; + if(usbtmc_state.ep_int_in != 0) { - .bNotify1 = (uint8_t)(0x80 | bTag), - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) - }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp.statusByte = 0x00; // Use interrupt endpoint, instead. - } - else - { - rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; + usbtmc_read_stb_interrupt_488_t intMsg = + { + .bNotify1 = (uint8_t)(0x80 | bTag), + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + }; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + } + else + { + rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + return true; + } // USB488 optional requests case USBTMC488_bREQUEST_REN_CONTROL: case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - return false; + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(false); + return false; + } #endif default: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 84640b136..702f595e6 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,6 +64,10 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); + +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); + // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); From e234998c6c8eeedd3ae2e28a3015afd6e910952d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 14:57:02 -0400 Subject: [PATCH 33/94] More proper handling of clear. --- examples/device/usbtmc/src/usbtmc_app.c | 23 +++++++++- src/class/usbtmc/usbtmc.h | 8 ++-- src/class/usbtmc/usbtmc_device.c | 58 ++++++++++++++++++------- src/class/usbtmc/usbtmc_device.h | 10 ++--- 4 files changed, 71 insertions(+), 28 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index a41d911d2..7328b6598 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -117,6 +117,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { + (void)rhport; rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; @@ -135,6 +136,8 @@ void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; switch(queryState) { + case 0: + break; case 1: queryDelayStart = board_millis(); queryState = 2; @@ -166,18 +169,34 @@ void usbtmc_app_task_iter(void) { } } -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) { +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) +{ (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; + queryState = 0; + bulkInStarted = false; + status = 0; return true; } -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +{ (void)rhport; + queryState = 0; + bulkInStarted = false; + status = 0; rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; rsp->bmClear.BulkInFifoBytes = 0u; return true; } +void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) +{ + (void)rhport; +} +void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) +{ + (void)rhport; +} // Return status byte, but put the transfer result status code in the rspResult argument. uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index d24a72cb6..2e4999c2d 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -279,13 +279,11 @@ TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length") typedef struct TU_ATTR_PACKET { - union { - struct TU_ATTR_PACKED { + struct TU_ATTR_PACKED + { unsigned int bTag : 7; unsigned int one : 1; - } bNotify1Struct; - uint8_t bNotify1; - }; + } bNotify1; uint8_t StatusByte; } usbtmc_read_stb_interrupt_488_t; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 7264125bb..cf8a5069a 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -115,18 +115,19 @@ bool usbtmcd_transmit_dev_msg_data( const void *data) { TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); +#ifndef NDEBUG TU_ASSERT(hdr->TransferSize > 0u); - if(hdr->bmTransferAttributes.UsingTermChar) { TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); } +#endif // Copy in the header memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); - uint packetLen = sizeof(*hdr); + size_t packetLen = sizeof(*hdr); // Single-packet transfer if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) { @@ -155,13 +156,14 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { -#if USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); +#ifndef NDEBUG +# if USBTMC_CFG_ENABLE_488 + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); +# endif + if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); #endif - if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); - } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -204,8 +206,10 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 break; case TUSB_XFER_INTERRUPT: +#ifndef NDEBUG TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); TU_ASSERT(usbtmc_state.ep_int_in == 0); +#endif usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; break; default: @@ -219,6 +223,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 } // bulk endpoints are required, but interrupt IN is optional +#ifndef NDEBUG TU_ASSERT(usbtmc_state.ep_bulk_in != 0); TU_ASSERT(usbtmc_state.ep_bulk_out != 0); if (itf_desc->bNumEndpoints == 2) { @@ -228,6 +233,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 { TU_ASSERT(usbtmc_state.ep_int_in != 0); } +#endif TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; @@ -363,7 +369,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint } else // short packet { - uint packetLen = usbtmc_state.transfer_size_remaining; + size_t packetLen = usbtmc_state.transfer_size_remaining; memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); while((packetLen % 4) != 0) { @@ -387,8 +393,25 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (USBTMC_CFG_ENABLE_488) - ushort bTag; + uint8_t bTag; #endif + + if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && + (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && + (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && + (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) + { + if((request->wIndex) == usbtmc_state.ep_bulk_out) + { + usmtmcd_app_bulkOut_clearFeature(rhport); + } + else if ((request->wIndex) == usbtmc_state.ep_bulk_in) + { + usmtmcd_app_bulkIn_clearFeature(rhport); + } + return false; // We want USBD core to handle sending the status response, and clear the stall condition + } + // We only handle class requests, IN direction. // (for now) if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) @@ -409,7 +432,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == 1u); tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); return true; } @@ -421,7 +444,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -432,7 +455,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } @@ -477,11 +500,13 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_read_stb_interrupt_488_t intMsg = { - .bNotify1 = (uint8_t)(0x80 | bTag), - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + .bNotify1 = { + .one = 1, + .bTag = bTag & 0x7Fu, + }, + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); - } else { @@ -503,6 +528,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ default: TU_VERIFY(false); + return false; } TU_VERIFY(false); } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 702f595e6..35d4da438 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -56,13 +56,13 @@ extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; #endif bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); - // transfer_complete does not imply that a message is complete. bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); - bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); @@ -104,10 +104,10 @@ void usbtmcd_init(void); *************************************************************/ #define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC -#define USBTMC_APP_SUBCLASS 0x03 +#define USBTMC_APP_SUBCLASS 0x03u -#define USBTMC_PROTOCOL_STD 0x00 -#define USBTMC_PROTOCOL_USB488 0x01 +#define USBTMC_PROTOCOL_STD 0x00u +#define USBTMC_PROTOCOL_USB488 0x01u // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID From 45871001e6d18503f05733ae770538e622313584 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:24:43 -0400 Subject: [PATCH 34/94] Changes1... --- src/class/usbtmc/usbtmc.h | 9 ++ src/class/usbtmc/usbtmc_device.c | 268 ++++++++++++++++++++++++------- 2 files changed, 220 insertions(+), 57 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 2e4999c2d..6893c3743 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -228,6 +228,15 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); +// Used for both abort bulk IN and bulk OUT +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; +} usbtmc_initiate_abort_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index cf8a5069a..6d562641e 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -8,7 +8,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 N Conrad + * Copyright (c) 2019 Nathan Conrad * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,31 +33,53 @@ #include "tusb_option.h" -// We don't do any cross-task anything here (everything is in tud or interrupt context). -// You must ensure thread safety in your own app. +// Synchronization is needed in some spots. +// These functions should NOT be called from interrupts. + +/* The library is designed that its functions can be called by any user task, with need for + * additional locking. In the case of "no OS", this task is never preempted other than by + * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. In the case + * of an OS, this class driver uses the OSAL to perform locking. The code uses a single lock + * and does not call outside of this class with a lock held, so deadlocks won't happen. + * + * This module's application-facing functions are not reentrant. The application must + * only call them from a single thread (or implement its own locking). + */ -//Limitations (not planned to be implemented): -// "vendor-specific" commands are not handled +//Limitations: +// "vendor-specific" commands are not handled. // Dealing with "termchar" must be handled by the application layer, // though additional error checking is does in this module. +// talkOnly and listenOnly are NOT supported. They're no permitted +// in USB488, anyway. + +/* Supported: + * + * Notification pulse + * Trigger + * Read status byte (both by interrupt endpoint and control message) + * + */ + // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. // Cannot handle clear. -// Not all "capabilities" supported // Clear message available status byte at the correct time? (488 4.3.1.3) -// Split transfers +// Abort bulk in/out // No CLEAR_FEATURE/HALT no EP (yet) -// No aborting transfers. #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) +#include #include "usbtmc.h" #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" +#include "uart_util.h" +static char logMsg[150]; // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" @@ -70,21 +92,31 @@ typedef enum STATE_IDLE, STATE_RCV, STATE_TX_REQUESTED, - STATE_TX_INITIATED + STATE_TX_INITIATED, + STATE_CLEARING, + STATE_ABORTING_BULK_IN, + STATE_ABORTING_BULK_OUT, + STATE_NUM_STATES } usbtmcd_state_enum; typedef struct { - usbtmcd_state_enum state; + volatile usbtmcd_state_enum state; + uint8_t itf_id; uint8_t ep_bulk_in; uint8_t ep_bulk_out; uint8_t ep_int_in; - uint8_t ep_bulk_in_buf[64]; - uint8_t ep_bulk_out_buf[64]; - uint8_t lastTag; + // IN buffer is only used for first packet, not the remainder + // in order to deal with prepending header + uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; + // OUT buffer receives one packet at a time + uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; + uint32_t transfer_size_remaining; // also used for requested length for bulk IN. + + uint8_t lastBulkOutTag; // used for aborts (mostly) + uint8_t lastBulkInTag; // used for aborts (mostly) - uint32_t transfer_size_remaining; uint8_t const * devInBuffer; } usbtmc_interface_state_t; @@ -97,39 +129,63 @@ static usbtmc_interface_state_t usbtmc_state = .ep_int_in = 0 }; -// We want everything to fit nicely in a single packet, so lets require EP size >32 -// I'm not sure if this is really necessary, though. +// We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); - +TU_VERIFY_STATIC( + (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0, + "packet buffer must be a multiple of the packet size"); static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + +osal_mutex_def_t usbtmcLockBuffer; +static osal_mutex_t usbtmcLock; + +// Our own private lock, mostly for the state variable. +#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) +#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. // length of data is specified in the hdr. + +// We can't just send the whole thing at once because we need to concatanate the +// header with the data. bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, - usbtmc_msg_dev_dep_msg_in_header_t const * hdr, - const void *data) + const void * data, size_t len, + bool usingTermChar) { - TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); + const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); + #ifndef NDEBUG - TU_ASSERT(hdr->TransferSize > 0u); - if(hdr->bmTransferAttributes.UsingTermChar) + TU_ASSERT(len > 0u); + TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); + if(usingTermChar) { TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); + TU_ASSERT(((uint8_t*)data)[len-1] == termChar); } #endif + TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); + usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; + memset(hdr, 0x00, sizeof(*hdr)); + hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; + hdr->header.bTag = usbtmc_state.lastBulkInTag; + hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); + hdr->TransferSize = len; + hdr->bmTransferAttributes.EOM = 1u; + hdr->bmTransferAttributes.UsingTermChar = usingTermChar; + // Copy in the header - memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); size_t packetLen = sizeof(*hdr); - // Single-packet transfer - if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) + + // If it fits in a single trasnmission: + if((packetLen + hdr->TransferSize) <= txBufLen) { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); packetLen = (uint16_t)(packetLen+ hdr->TransferSize); @@ -142,15 +198,23 @@ bool usbtmcd_transmit_dev_msg_data( usbtmc_state.transfer_size_remaining = 0; usbtmc_state.devInBuffer = NULL; } - else + else /* partial packet */ { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, USBTMCD_MAX_PACKET_SIZE - packetLen); - usbtmc_state.transfer_size_remaining = hdr->TransferSize - (USBTMCD_MAX_PACKET_SIZE - packetLen); - usbtmc_state.devInBuffer += (USBTMCD_MAX_PACKET_SIZE - packetLen); - packetLen = USBTMCD_MAX_PACKET_SIZE; + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); + usbtmc_state.devInBuffer += txBufLen - packetLen; + usbtmc_state.transfer_size_remaining = hdr->TransferSize - (txBufLen - packetLen); + packetLen = txBufLen; } - usbtmc_state.state = STATE_TX_INITIATED; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + + + criticalEnter(); + { + TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); + usbtmc_state.state = STATE_TX_INITIATED; + } + criticalLeave(); + + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } @@ -158,12 +222,17 @@ void usbtmcd_init(void) { #ifndef NDEBUG # if USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + // Per USB488 spec: table 8 + TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); #endif + + usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -226,10 +295,17 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 #ifndef NDEBUG TU_ASSERT(usbtmc_state.ep_bulk_in != 0); TU_ASSERT(usbtmc_state.ep_bulk_out != 0); - if (itf_desc->bNumEndpoints == 2) { + if (itf_desc->bNumEndpoints == 2) + { TU_ASSERT(usbtmc_state.ep_int_in == 0); } - else if (itf_desc->bNumEndpoints == 2) + else if (itf_desc->bNumEndpoints == 3) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0); + } + + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || + usbtmcd_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -286,12 +362,22 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - TU_VERIFY(usbtmc_state.state == STATE_IDLE); - usbtmc_state.state = STATE_TX_REQUESTED; - usbtmc_state.transfer_size_remaining = msg->TransferSize; + + sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); + uart_tx_str_sync(logMsg); + + criticalEnter(); + { + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + usbtmc_state.state = STATE_TX_REQUESTED; + usbtmc_state.lastBulkInTag = msg->header.bTag; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + } + criticalLeave(); termCharRequested = msg->bmTransferAttributes.TermCharEnabled; termChar = msg->TermChar; + if(termCharRequested) TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); @@ -302,8 +388,17 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { TU_VERIFY(result == XFER_RESULT_SUCCESS); + uart_tx_str_sync("USBTMC Xfer CB" ); + sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); + uart_tx_str_sync(logMsg); + + if(usbtmc_state.state == STATE_CLEARING) { + return true; /* I think we can ignore everything here */ + } + if(ep_addr == usbtmc_state.ep_bulk_out) { + uart_tx_str_sync("OUT"); switch(usbtmc_state.state) { case STATE_IDLE: @@ -312,15 +407,19 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); - usbtmc_state.lastTag = msg->header.bTag; + + sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); + uart_tx_str_sync(logMsg); switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); + usbtmc_state.lastBulkOutTag = msg->header.bTag; break; case USBTMC_MSGID_DEV_DEP_MSG_IN: + uart_tx_sync("Handling msg in req\r\n", 21); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -336,6 +435,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: default: + TU_VERIFY(false); return false; } @@ -347,12 +447,22 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_REQUESTED: case STATE_TX_INITIATED: + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: default: + if(msg == NULL) + sprintf(logMsg," Unknown received control?\r\n "); + else { + sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); + } + uart_tx_str_sync(logMsg); TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { + sprintf(logMsg,"IN\r\n"); + uart_tx_str_sync(logMsg); TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); if(usbtmc_state.transfer_size_remaining == 0) { @@ -360,14 +470,14 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); } - else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) + else if(usbtmc_state.transfer_size_remaining > sizeof(usbtmc_state.devInBuffer)) { - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, USBTMCD_MAX_PACKET_SIZE); - usbtmc_state.devInBuffer += USBTMCD_MAX_PACKET_SIZE; - usbtmc_state.transfer_size_remaining -= USBTMCD_MAX_PACKET_SIZE; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,USBTMCD_MAX_PACKET_SIZE)); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); } - else // short packet + else // last packet { size_t packetLen = usbtmc_state.transfer_size_remaining; memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); @@ -401,6 +511,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { + uart_tx_str_sync("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -426,23 +537,48 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USBTMC required requests case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); - return true; - } + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } + + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + { + usbtmc_initiate_abort_rsp_t rsp = {0}; + uart_tx_str_sync("init abort bulk in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_int_in); + // wValue is the requested bTag to abort + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.state = STATE_ABORTING_BULK_IN; + TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + return true; + } case USBTMC_bREQUEST_INITIATE_CLEAR: { + uart_tx_str_sync("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.state = STATE_CLEARING; TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; @@ -450,17 +586,31 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + uart_tx_str_sync("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) + { + // Stuff stuck in TX buffer? + clearStatusRsp.bmClear.BulkInFifoBytes = 1; + clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; + } + else + { + // Let app check if it's clear + TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + } + if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) + usbtmc_state.state = STATE_IDLE; TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } case USBTMC_bREQUEST_GET_CAPABILITIES: { + uart_tx_str_sync("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -470,6 +620,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { + uart_tx_str_sync("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -482,6 +633,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { + uart_tx_str_sync("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -520,6 +672,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { + uart_tx_str_sync("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -527,6 +680,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: + uart_tx_str_sync("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } From 91cd247c97a7376133638d960b6c650c0f71d376 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:26:10 -0400 Subject: [PATCH 35/94] changes 2 --- examples/device/usbtmc/src/usb_descriptors.c | 10 ++++----- examples/device/usbtmc/src/usbtmc_app.c | 23 +++++++++++++++----- src/class/usbtmc/usbtmc_device.h | 4 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 9567bcab5..792fff87c 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -106,7 +106,7 @@ uint8_t const * tud_hid_descriptor_report_cb(void) #if defined(CFG_TUD_USBTMC) # define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ - USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 7u, USBTMC_PROTOCOL_USB488), \ + USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, USBTMC_PROTOCOL_USB488), \ USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) @@ -209,10 +209,7 @@ char const* string_desc_arr [] = "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product "123456", // 3: Serials, should use chip ID - "TinyUSB CDC", // 4: CDC Interface - "TinyUSB MSC", // 5: MSC Interface - "TinyUSB HID", // 6: HID - "TinyUSB USBTMC", // 7: USBTMC + "TinyUSB USBTMC", // 4: USBTMC }; static uint16_t _desc_str[32]; @@ -227,7 +224,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) { memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; - }else + } + else { // Convert ASCII string into UTF-16 diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7328b6598..e21c3ca22 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -64,8 +64,8 @@ usbtmcd_app_capabilities = } #endif }; - -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; +//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps?\n"; static volatile uint8_t status; // 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? @@ -86,6 +86,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; + uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); return true; } bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { @@ -99,6 +100,11 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) + uart_tx_str_sync("MSG_OUT_DATA: <<<"); + uart_tx_sync(data,len); + uart_tx_str_sync(">>>\r\n"); + if(transfer_complete) + uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; @@ -115,13 +121,18 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) return true; } +static unsigned int msgReqLen; + bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { (void)rhport; + rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; + msgReqLen = request->TransferSize; + uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -143,14 +154,14 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 1000u) { + if( (board_millis() - queryDelayStart) > 5u) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV } break; case 3: - if( (board_millis() - queryDelayStart) > 1000u) { + if( (board_millis() - queryDelayStart) > 10u) { queryState = 4; } break; @@ -158,8 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - rspMsg.TransferSize = sizeof(idn)-1; - usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } break; @@ -189,6 +199,7 @@ bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } + void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) { (void)rhport; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 35d4da438..a0ba82e30 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -86,8 +86,8 @@ TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, - usbtmc_msg_dev_dep_msg_in_header_t const * hdr, - const void *data); + const void * data, size_t len, + bool usingTermChar); /* "callbacks" from USB device core */ From c7006a254b167dc5b2c6994c5bcce70fd877f84c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:27:35 -0400 Subject: [PATCH 36/94] change 3 --- docs/concurrency.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 docs/concurrency.md diff --git a/docs/concurrency.md b/docs/concurrency.md new file mode 100644 index 000000000..e05ca6ffe --- /dev/null +++ b/docs/concurrency.md @@ -0,0 +1,36 @@ +# Concurrency + +The TinyUSB library is designed to operate on single-core MCUs with multi-threaded applications in mind. Interaction with interrupts is especially important to pay attention to. +It is compatible with optionally using a RTOS. + +## General + +When writing code, keep in mind that the OS (if using a RTOS) may swap out your code at any time. Also, your code can be preempted by an interrupt at any time. + +## Application Code + +The USB core does not execute application callbacks while in an interrupt context. Calls to application code are from within the USB core task context. Note that the application core will call class drivers from within their own task. + +## Class Drivers + +Class driver code should never be called from an interrupt context by the USB core, though the application is allowed to call class driver functions from interrupts. USB core functions may be called simultaneously by multiple tasks. Use care that proper locking is used to guard the USBD core functions from this case. + +Class drivers are allowed to call `usbd_*` functions, but not `dcd_*` functions. + +## USB Core + +All functions that may be called from an (USB core) interrupt context have a `bool in_isr` parameter to remind the implementer that special care must be taken. + +Interrupt handlers must not directly call class driver code, they must pass a message to the USB core's task. + + `usbd_*` functions may be called from interrupts without any notice. They may also be called simultaneously by multiple tasks. + +## Device Drivers + +Much of the processing of the USB stack is done in an interrupt context, and care must be taken in order to ensure variables are handled in the appropriate ways by the compiler and optimizer. + +In particular: + +- Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory access (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like `_I`, `_O`, or `_IO'. +- All defined global variables are marked as `static`. + From 45b69a30a81a7353f625352efc143a91b02506bd Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 12 Sep 2019 14:32:16 -0400 Subject: [PATCH 37/94] Correct port assigned on the STM32F070 BSP --- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index 50f174b34..6ee73bcc2 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -29,13 +29,13 @@ #include "stm32f0xx.h" #include "stm32f0xx_hal_conf.h" -#define LED_PORT GPIOC -#define LED_PIN GPIO_PIN_13 +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_5 #define LED_STATE_ON 1 -#define BUTTON_PORT GPIOA -#define BUTTON_PIN GPIO_PIN_5 -#define BUTTON_STATE_ACTIVE 1 +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 0 void board_init(void) { @@ -75,7 +75,7 @@ void board_init(void) SystemCoreClockUpdate(); // LED - __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; @@ -84,7 +84,7 @@ void board_init(void) HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); // Button - __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; From 44013e6e85e859abe6c47c567415a0acea003b1b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:42:58 +0700 Subject: [PATCH 38/94] Update boards.md --- docs/boards.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index 96650b20b..de6328aa2 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -48,8 +48,8 @@ This code base already had supported for a handful of following boards - [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) - [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) - [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [Nucleo STM32F767zi](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [Nucleo H743zi](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From fd4be239004946cd295b8a85215999a308f0b6ed Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:43:46 +0700 Subject: [PATCH 39/94] Update boards.md --- docs/boards.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index de6328aa2..30b0eb958 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -41,15 +41,15 @@ This code base already had supported for a handful of following boards ### ST STM32 -- [STM32F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) -- [STM32F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) -- [STM32F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) -- [STM32F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) -- [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) -- [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) -- [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) +- [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) +- [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) +- [STM32 F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) +- [STM32 F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) +- [STM32 F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) +- [STM32 F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) +- [STM32 F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From a0b6b8187c036b386f09188a9017301f730096b8 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 20:28:26 -0400 Subject: [PATCH 40/94] TI compiler quirks, and le byte swapping functions. --- src/common/tusb_compiler.h | 85 +++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 09768ef88..ca294c20f 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -53,6 +53,9 @@ // for declaration of reserved field, make use of _TU_COUNTER_ #define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) +#define TU_LITTLE_ENDIAN (0x12u) +#define TU_BIG_ENDIAN (0x21u) + //--------------------------------------------------------------------+ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ @@ -67,20 +70,80 @@ // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define tu_htonl(u32) __builtin_bswap32(u32) - #define tu_ntohl(u32) __builtin_bswap32(u32) - - #define tu_htons(u16) __builtin_bswap16(u16) - #define tu_ntohs(u16) __builtin_bswap16(u16) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN #else - #define tu_htonl(u32) (u32) - #define tu_ntohl(u32) (u32) - - #define tu_htons(u16) (u16) - #define tu_ntohs(u16) (u16) + #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } + + #define TU_BSWAP16 + +#elif defined(__TI_COMPILER_VERSION__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_PREPACKED + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) + #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } #else - #error "Compiler attribute porting are required" + #error "Compiler attribute porting is required" +#endif + +#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) + #define tu_htonl(u32) tu_bswap32(u32) + #define tu_ntohl(u32) tu_bswap32(u32) + + #define tu_htons(u16) tu_bswap16(u16) + #define tu_ntohs(u16) tu_bswap16(u16) + + #define tu_htole16(x) (x) + #define tu_le16toh(x) (x) + + #define tu_htole32(x) (x) + #define tu_le32toh(x) (x) + +#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) + #define tu_htonl(u32) (x) + #define tu_ntohl(u32) (x) + + #define tu_htons(u16) (x) + #define tu_ntohs(u16) (x) + + #define tu_htole16(x) tu_bswap16(u32) + #define tu_le16toh(x) tu_bswap16(u32) + + #define tu_htole32(x) tu_bswap32(u32) + #define tu_le32toh(x) tu_bswap32(u32) + +#else + #error Byte order is undefined #endif #endif /* _TUSB_COMPILER_H_ */ From 41e8b8752e421ccb63a48eec316f353854abc8a0 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 15:20:01 -0400 Subject: [PATCH 41/94] Massive copy&paste typo of mine in the 32-bit byte swapping function.... --- src/common/tusb_compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index ca294c20f..df0326afd 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -80,7 +80,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } @@ -108,7 +108,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } From 8d05b70a72d8132eb67523c789499cd4cdf5d562 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:37:47 -0400 Subject: [PATCH 42/94] Off-by-one error in Synopsys assertions. (and move some braces to their own lines. --- src/portable/st/synopsys/dcd_synopsys.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b0e7e04bd..2daa16a26 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -268,21 +268,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - // Unsupported endpoint numbers/size. - if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > EP_MAX)) { - return false; - } - + + TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; - if(dir == TUSB_DIR_OUT) { + if(dir == TUSB_DIR_OUT) + { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | \ desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos | \ desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos; dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); - } else { + } + else + { // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // From 1ceeab2702c6f5407c00dab8deeade338d176a45 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:52:43 -0400 Subject: [PATCH 43/94] This demonstrates that I don't pre-build things before committing them... oops. --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2daa16a26..f15b92edc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -269,7 +269,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); From 192e1de66ed512fdab448bd4862c57259330df59 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 10 Sep 2019 14:10:33 -0400 Subject: [PATCH 44/94] Add pyboard (v1.1) BSP. cdc_msc_hid example tested. --- hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld | 189 +++++++++ hw/bsp/pyboardv11/board.mk | 50 +++ hw/bsp/pyboardv11/pyboardv11.c | 200 +++++++++ hw/bsp/pyboardv11/stm32f4xx_hal_conf.h | 489 +++++++++++++++++++++++ 4 files changed, 928 insertions(+) create mode 100644 hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld create mode 100644 hw/bsp/pyboardv11/board.mk create mode 100644 hw/bsp/pyboardv11/pyboardv11.c create mode 100644 hw/bsp/pyboardv11/stm32f4xx_hal_conf.h diff --git a/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld new file mode 100644 index 000000000..57ef61e26 --- /dev/null +++ b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld @@ -0,0 +1,189 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F405RGTx Device with +** 1024KByte FLASH, 128KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk new file mode 100644 index 000000000..9e328072b --- /dev/null +++ b/hw/bsp/pyboardv11/board.mk @@ -0,0 +1,50 @@ +CFLAGS += \ + -DHSE_VALUE=120000000 \ + -DSTM32F405xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F4 + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = synopsys + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = stm32f407vg +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c new file mode 100644 index 000000000..85c0eb58f --- /dev/null +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32f4xx.h" +#include "stm32f4xx_hal_conf.h" + +// Blue LED is chosen because the other LEDs are connected to ST-LINK lines. +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_4 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOB +#define BUTTON_PIN GPIO_PIN_3 +#define BUTTON_STATE_ACTIVE 1 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 168000000 + * HCLK(Hz) = 168000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 4 + * APB2 Prescaler = 2 + * HSE Frequency(Hz) = 12000000 + * PLL_M = 12 + * PLL_N = 336 + * PLL_P = 2 + * PLL_Q = 7 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + /* Enable Power Control clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 336; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+/D- + __HAL_RCC_GPIOB_CLK_ENABLE(); // button, LED + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOD_CLK_ENABLE(); + + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // Enable USB OTG clock + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + // USB Pin Init + // PA9- VUSB, PA10- ID, PA11- DM, PA12- DP + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure DM DP Pins */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* This for ID line debug */ + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h new file mode 100644 index 000000000..dbef20e0a --- /dev/null +++ b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2019 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)12000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* Copied over manually- STM32Cube didn't generate these for some reason. */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From ff36957c05cf40c8b73f56f3e039cc00864ca492 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 14 Sep 2019 04:31:43 -0400 Subject: [PATCH 45/94] pyboardv11: Fix typo in HSE_VALUE define so that SysTick runs at correct frequency. --- hw/bsp/pyboardv11/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 9e328072b..2ba1d3900 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -1,5 +1,5 @@ CFLAGS += \ - -DHSE_VALUE=120000000 \ + -DHSE_VALUE=12000000 \ -DSTM32F405xx \ -mthumb \ -mabi=aapcs \ From 8e17fb49106eeb291a36ff5f82ead624e867e6b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 11:13:17 +0700 Subject: [PATCH 46/94] follow up to suggestion to pr 155 --- src/common/tusb_types.h | 3 ++- src/device/usbd.c | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a50e89934..ad42baad7 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -125,7 +125,8 @@ typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, - TUSB_REQ_TYPE_VENDOR + TUSB_REQ_TYPE_VENDOR, + TUSB_REQ_TYPE_INVALID } tusb_request_type_t; typedef enum diff --git a/src/device/usbd.c b/src/device/usbd.c index 572708f7d..2f8967fae 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -62,7 +62,7 @@ typedef struct { static usbd_device_t _usbd_dev = { 0 }; // Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xff }; +enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver @@ -365,6 +365,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { @@ -486,7 +488,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // GET HID REPORT DESCRIPTOR falls into this case // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); break; } }else @@ -494,7 +497,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // forward to class driver: "non-STD request to Interface" // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); } } break; @@ -515,7 +519,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // We will forward all request targeted endpoint to its class driver // - For non-standard request: driver can ACK or Stall the request by return true/false // - For standard request: usbd decide the ACK stage regardless of driver return value - bool ret; + bool ret = false; if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { @@ -523,8 +527,11 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete); } - // Invoke class driver first - ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + // Invoke class driver first if available + if ( usbd_class_drivers[drv_id].control_request ) + { + ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + } // Then handle if it is standard request if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) From 5a2e510af73e84284343420fd76388369e70f7f5 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 09:02:21 -0400 Subject: [PATCH 47/94] Interpretation of assert vs verify. --- src/common/tusb_verify.h | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 2727ce043..fae0c88ae 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -36,10 +36,34 @@ * as C++ for the sake of code simplicity. Beware of a headache macro * manipulation that you are told to stay away. * - * e.g * - * - TU_VERIFY( cond ) will return false if cond is false - * - TU_VERIFY( cond, err) will return err instead if cond is false + * This contains macros for both VERIFY and ASSERT: + * + * VERIFY: Used when there is an error condition which is not the + * fault of the MCU. For example, bounds checking on data + * sent to the micro over USB should use this function. + * Another example is checking for buffer overflows, where + * returning from the active function causes a NAK. + * + * ASSERT: Used for error conditions that are caused by MCU firmware + * bugs. This is used to discover bugs in the code more + * quickly. One example would be adding assertions in library + * function calls to confirm a function's (untainted) + * parameters are valid. + * + * + * The difference in behaviour is that ASSERT triggers a breakpoint while + * verify does not. + * + * #define TU_VERIFY(cond) if(cond) return false; + * #define TU_VERIFY(cond,ret) if(cond) return ret; + * + * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} + * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} + * + * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} + * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} + * *------------------------------------------------------------------*/ #ifdef __cplusplus From 237c32b976d605087dd0b2c5013f7f2ae4bae46f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 13:32:47 +0700 Subject: [PATCH 48/94] fix #143 --- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 2b49f52e9..d5f90d2a7 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -293,7 +293,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) break; case TUSB_XFER_ISOCHRONOUS: - TU_ASSERT((epnum % 3) == 3 && (epnum != 15)); + TU_ASSERT((epnum % 3) == 0 && (epnum != 0) && (epnum != 15)); break; default: From 6dd2296cfc1b2cd871e577c42de96ee444d4a1d3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 11:27:05 -0400 Subject: [PATCH 49/94] Change inline functions to macros, and make all parameter names uniform. --- src/common/tusb_compiler.h | 58 +++++++++++++++----------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index df0326afd..58732b871 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -75,17 +75,8 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } - - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } - - #define TU_BSWAP16 +#define TU_BSWAP16(u16) (__builtin_bswap16(u16)) +#define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__TI_COMPILER_VERSION__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -103,44 +94,41 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } + #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) + #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } #else #error "Compiler attribute porting is required" #endif #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) - #define tu_htonl(u32) tu_bswap32(u32) - #define tu_ntohl(u32) tu_bswap32(u32) - #define tu_htons(u16) tu_bswap16(u16) - #define tu_ntohs(u16) tu_bswap16(u16) + #define tu_htons(u16) (TU_BSWAP16(u16)) + #define tu_ntohs(u16) (TU_BSWAP16(u16)) - #define tu_htole16(x) (x) - #define tu_le16toh(x) (x) + #define tu_htonl(u32) (TU_BSWAP32(u32)) + #define tu_ntohl(u32) (TU_BSWAP32(u32)) - #define tu_htole32(x) (x) - #define tu_le32toh(x) (x) + #define tu_htole16(u16) (u16) + #define tu_le16toh(u16) (u16) + + #define tu_htole32(u32) (u32) + #define tu_le32toh(u32) (u32) #elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) - #define tu_htonl(u32) (x) - #define tu_ntohl(u32) (x) - #define tu_htons(u16) (x) - #define tu_ntohs(u16) (x) + #define tu_htons(u16) (u16) + #define tu_ntohs(u16) (u16) - #define tu_htole16(x) tu_bswap16(u32) - #define tu_le16toh(x) tu_bswap16(u32) + #define tu_htonl(u32) (u32) + #define tu_ntohl(u32) (u32) - #define tu_htole32(x) tu_bswap32(u32) - #define tu_le32toh(x) tu_bswap32(u32) + + #define tu_htole16(u16) (tu_bswap16(u16)) + #define tu_le16toh(u16) (tu_bswap16(u16)) + + #define tu_htole32(u32) (tu_bswap32(u32)) + #define tu_le32toh(u32) (tu_bswap32(u32)) #else #error Byte order is undefined From 3440083bfd11245936b9d65831713d014a188b74 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Sep 2019 14:38:56 +0700 Subject: [PATCH 50/94] added board feather stm32f045 --- docs/boards.md | 1 + .../feather_stm32f405/STM32F405RGTx_FLASH.ld | 189 +++++++ hw/bsp/feather_stm32f405/board.mk | 50 ++ hw/bsp/feather_stm32f405/feather_stm32f405.c | 198 +++++++ hw/bsp/feather_stm32f405/stm32f4xx_hal_conf.h | 489 ++++++++++++++++++ hw/bsp/pyboardv11/board.mk | 2 +- 6 files changed, 928 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/feather_stm32f405/STM32F405RGTx_FLASH.ld create mode 100644 hw/bsp/feather_stm32f405/board.mk create mode 100644 hw/bsp/feather_stm32f405/feather_stm32f405.c create mode 100644 hw/bsp/feather_stm32f405/stm32f4xx_hal_conf.h diff --git a/docs/boards.md b/docs/boards.md index 5e33c3ee3..fef682f48 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -41,6 +41,7 @@ This code base already had supported for a handful of following boards ### ST STM32 +- Adafruit Feather STM32F405 - [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1) - [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) - [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) diff --git a/hw/bsp/feather_stm32f405/STM32F405RGTx_FLASH.ld b/hw/bsp/feather_stm32f405/STM32F405RGTx_FLASH.ld new file mode 100644 index 000000000..57ef61e26 --- /dev/null +++ b/hw/bsp/feather_stm32f405/STM32F405RGTx_FLASH.ld @@ -0,0 +1,189 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F405RGTx Device with +** 1024KByte FLASH, 128KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/feather_stm32f405/board.mk b/hw/bsp/feather_stm32f405/board.mk new file mode 100644 index 000000000..ef9777976 --- /dev/null +++ b/hw/bsp/feather_stm32f405/board.mk @@ -0,0 +1,50 @@ +CFLAGS += \ + -DHSE_VALUE=12000000 \ + -DSTM32F405xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F4 + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = synopsys + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = stm32f405rg +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/feather_stm32f405/feather_stm32f405.c b/hw/bsp/feather_stm32f405/feather_stm32f405.c new file mode 100644 index 000000000..02c33a0a8 --- /dev/null +++ b/hw/bsp/feather_stm32f405/feather_stm32f405.c @@ -0,0 +1,198 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32f4xx.h" +#include "stm32f4xx_hal_conf.h" + +// Blue LED is chosen because the other LEDs are connected to ST-LINK lines. +#define LED_PORT GPIOC +#define LED_PIN GPIO_PIN_4 +#define LED_STATE_ON 1 + +// Pin D5 +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_7 +#define BUTTON_STATE_ACTIVE 0 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 168000000 + * HCLK(Hz) = 168000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 4 + * APB2 Prescaler = 2 + * HSE Frequency(Hz) = 12000000 + * PLL_M = 12 + * PLL_N = 336 + * PLL_P = 2 + * PLL_Q = 7 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + /* Enable Power Control clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 336; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOC_CLK_ENABLE(); + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + //__HAL_RCC_GPIOC_CLK_ENABLE(); + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // Enable USB OTG clock + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + // USB Pin Init + // PA9- VUSB, PA10- ID, PA11- DM, PA12- DP + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure DM DP Pins */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* This for ID line debug */ + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/feather_stm32f405/stm32f4xx_hal_conf.h b/hw/bsp/feather_stm32f405/stm32f4xx_hal_conf.h new file mode 100644 index 000000000..dbef20e0a --- /dev/null +++ b/hw/bsp/feather_stm32f405/stm32f4xx_hal_conf.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2019 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)12000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* Copied over manually- STM32Cube didn't generate these for some reason. */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 2ba1d3900..ef9777976 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -39,7 +39,7 @@ CHIP_FAMILY = synopsys FREERTOS_PORT = ARM_CM4F # For flash-jlink target -JLINK_DEVICE = stm32f407vg +JLINK_DEVICE = stm32f405rg JLINK_IF = swd # Path to STM32 Cube Programmer CLI, should be added into system path From eea71a8b3b080299ad95ac79a7d45b2dc0d5b6f6 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 19:24:54 -0400 Subject: [PATCH 51/94] usbtmc updates.... --- examples/device/usbtmc/src/tusb_config.h | 4 +- examples/device/usbtmc/src/usbtmc_app.c | 32 ++- src/class/usbtmc/usbtmc.h | 14 ++ src/class/usbtmc/usbtmc_device.c | 279 +++++++++++++++++------ src/class/usbtmc/usbtmc_device.h | 6 +- 5 files changed, 261 insertions(+), 74 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 022dc7691..16484424a 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -56,8 +56,8 @@ //------------- CLASS -------------// #define CFG_TUD_USBTMC 1 -#define CFG_TUD_USBTMC_ENABLE_INT_EP -//#define USBTMC_CFG_ENABLE_488 0 +#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 +#define USBTMC_CFG_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index e21c3ca22..03800ab17 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -64,8 +64,8 @@ usbtmcd_app_capabilities = } #endif }; -//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps?\n"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n"; +//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps? lets make it three transfers...\n"; static volatile uint8_t status; // 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? @@ -154,14 +154,14 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 5u) { + if( (board_millis() - queryDelayStart) > 200u) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV } break; case 3: - if( (board_millis() - queryDelayStart) > 10u) { + if( (board_millis() - queryDelayStart) > 400u) { queryState = 4; } break; @@ -169,6 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; + uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } @@ -189,7 +190,7 @@ bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) return true; } -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { (void)rhport; queryState = 0; @@ -199,6 +200,27 @@ bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } +bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) +{ + bulkInStarted = 0; + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; +} +bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +{ + return true; +} + +bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) +{ + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; + +} +bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +{ + return true; +} void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) { diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 6893c3743..0944c907a 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -237,6 +237,20 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); +// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued + } bmAbortBulkIn; + uint8_t _reserved[2]; ///< Must be zero + uint32_t NBYTES_RXD_TXD; +} usbtmc_check_abort_bulk_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6d562641e..c71d4d963 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -93,8 +93,11 @@ typedef enum STATE_RCV, STATE_TX_REQUESTED, STATE_TX_INITIATED, + STATE_TX_SHORTED, STATE_CLEARING, STATE_ABORTING_BULK_IN, + STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been queued for transmission STATE_ABORTING_BULK_OUT, STATE_NUM_STATES } usbtmcd_state_enum; @@ -113,6 +116,7 @@ typedef struct // OUT buffer receives one packet at a time uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; uint32_t transfer_size_remaining; // also used for requested length for bulk IN. + uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) uint8_t lastBulkOutTag; // used for aborts (mostly) uint8_t lastBulkInTag; // used for aborts (mostly) @@ -128,6 +132,11 @@ static usbtmc_interface_state_t usbtmc_state = .ep_bulk_out = 0, .ep_int_in = 0 }; +#ifdef xDEBUG +#define TRACE(str) uart_tx_str_sync(str) +#else +#define TRACE(STR) do {} while (0) +#endif // We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); @@ -188,7 +197,7 @@ bool usbtmcd_transmit_dev_msg_data( if((packetLen + hdr->TransferSize) <= txBufLen) { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); - packetLen = (uint16_t)(packetLen+ hdr->TransferSize); + packetLen = (uint16_t)(packetLen + hdr->TransferSize); // Pad up to multiple of 4 bytes while((packetLen % 4) != 0) { @@ -196,13 +205,15 @@ bool usbtmcd_transmit_dev_msg_data( packetLen++; } usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_sent = len; usbtmc_state.devInBuffer = NULL; } else /* partial packet */ { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); - usbtmc_state.devInBuffer += txBufLen - packetLen; - usbtmc_state.transfer_size_remaining = hdr->TransferSize - (txBufLen - packetLen); + usbtmc_state.devInBuffer = (uint8_t*)data + (txBufLen - packetLen); + usbtmc_state.transfer_size_remaining = len - (txBufLen - packetLen); + usbtmc_state.transfer_size_sent = txBufLen - packetLen; packetLen = txBufLen; } @@ -210,7 +221,8 @@ bool usbtmcd_transmit_dev_msg_data( criticalEnter(); { TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_state.state = STATE_TX_INITIATED; + // We used packetlen as a max, not the buffer size, so this is OK here, no need for modulus + usbtmc_state.state = (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED; } criticalLeave(); @@ -322,6 +334,8 @@ void usbtmcd_reset(uint8_t rhport) usbtmc_state.ep_bulk_in = 0; usbtmc_state.ep_bulk_out = 0; usbtmc_state.ep_int_in = 0; + usbtmc_state.lastBulkInTag = 0; + usbtmc_state.lastBulkOutTag = 0; (void)rhport; } @@ -351,10 +365,16 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; usbtmcd_app_msg_data(rhport,data, len, atEnd); + + usbtmc_state.transfer_size_sent += len; if(atEnd) + { usbtmc_state.state = STATE_IDLE; + } else + { usbtmc_state.state = STATE_RCV; + } return true; } @@ -363,8 +383,10 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; +#ifdef xDebug sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif criticalEnter(); { @@ -387,10 +409,13 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + TRACE("USBTMC Xfer CB" ); TU_VERIFY(result == XFER_RESULT_SUCCESS); - uart_tx_str_sync("USBTMC Xfer CB" ); + +#ifdef xDebug sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ @@ -398,23 +423,26 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(ep_addr == usbtmc_state.ep_bulk_out) { - uart_tx_str_sync("OUT"); + usbtmc_msg_generic_t *msg = NULL; + TRACE("OUT"); switch(usbtmc_state.state) { case STATE_IDLE: TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - usbtmc_msg_generic_t *msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); + msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); +#ifdef xDebug sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: + usbtmc_state.transfer_size_sent = 0u; TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); usbtmc_state.lastBulkOutTag = msg->header.bTag; break; @@ -428,7 +456,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); break; #endif @@ -439,58 +466,95 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(false); return false; } + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_RCV: TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; + case STATE_ABORTING_BULK_OUT: + TU_VERIFY(false); + return false; // Shold be stalled by now... case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: + case STATE_ABORTING_BULK_IN_SHORTED: + case STATE_ABORTING_BULK_IN_ABORTED: default: + +#ifdef xDebug if(msg == NULL) sprintf(logMsg," Unknown received control?\r\n "); else { sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); } - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { +#ifdef xDebug sprintf(logMsg,"IN\r\n"); - uart_tx_str_sync(logMsg); - TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); - if(usbtmc_state.transfer_size_remaining == 0) - { + TRACE(logMsg); +#endif + switch(usbtmc_state.state) { + case STATE_TX_SHORTED: + + TRACE("IN TX shorted done\r\n"); + usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); - } - else if(usbtmc_state.transfer_size_remaining > sizeof(usbtmc_state.devInBuffer)) - { - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) + break; + + case STATE_TX_INITIATED: + if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0; - packetLen++; + TRACE("IN TX continuing\r\n"); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); } - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + else // last packet + { + TRACE("IN TX last packet\r\n"); + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; + packetLen++; + } + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) + { + usbtmc_state.state = STATE_TX_SHORTED; + } + } + return true; + case STATE_ABORTING_BULK_IN: + // need to send short packet (ZLP?) + TRACE("IN aborting\r\n"); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + return true; + case STATE_ABORTING_BULK_IN_SHORTED: + /* Done. :)*/ + TRACE("IN shorted\r\n"); + usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; + return true; + default: + TRACE("IN unknown\r\n"); + TU_ASSERT(false); + return false; } - return true; } else if (ep_addr == usbtmc_state.ep_int_in) { // Good? @@ -505,13 +569,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif + TRACE("xfer cb\r\n"); if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - uart_tx_str_sync("feature clear\r\n"); + TRACE("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -536,42 +601,124 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { // USBTMC required requests case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkOutTag, + }; + TRACE("init abort bulk out\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + + // wValue is the requested bTag to abort + if(usbtmc_state.state != STATE_RCV) + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + TRACE("init abort bulk out failed\r\n"); + } + else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) + { + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + TRACE("init abort bulk out not inprogress\r\n"); + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + // Check if we've queued a short packet + usbtmc_state.state = STATE_ABORTING_BULK_OUT; + TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TRACE("init abort bulk out success\r\n"); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { + TRACE("init check abort bulk out\r\n"); + usbtmc_check_abort_bulk_rsp_t rsp = { + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent + }; TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: { - usbtmc_initiate_abort_rsp_t rsp = {0}; - uart_tx_str_sync("init abort bulk in\r\n"); - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_int_in); + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkInTag, + }; + TRACE("init abort bulk in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); // wValue is the requested bTag to abort - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.state = STATE_ABORTING_BULK_IN; - TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && + usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.transfer_size_remaining = 0; + // Check if we've queued a short packet + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? + STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); + TRACE("init abort bulk success\r\n"); + } + else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) + { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + TRACE("init abort bulk in not in progress\r\n"); + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + TRACE("init abort bulk in failed\r\n"); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; + } + + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + { + TRACE("xfer check abort in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 8u); + + usbtmc_check_abort_bulk_rsp_t rsp = + { + .USBTMC_status = USBTMC_STATUS_FAILED, + .bmAbortBulkIn = + { + .BulkInFifoBytes = (usbtmc_state.state == STATE_ABORTING_BULK_IN_ABORTED) + }, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, + }; + TU_VERIFY(usbtmcd_app_check_abort_bulk_in(rhport, &rsp)); + switch(usbtmc_state.state) + { + case STATE_ABORTING_BULK_IN_ABORTED: + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + break; + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: + rsp.USBTMC_status = USBTMC_STATUS_PENDING; + break; + default: + break; + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; } case USBTMC_bREQUEST_INITIATE_CLEAR: { - uart_tx_str_sync("init clear\r\n"); + TRACE("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the @@ -586,7 +733,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - uart_tx_str_sync("check clear\r\n"); + TRACE("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); @@ -600,7 +747,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ else { // Let app check if it's clear - TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + TU_VERIFY(usbtmcd_app_check_clear(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) usbtmc_state.state = STATE_IDLE; @@ -610,7 +757,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { - uart_tx_str_sync("get capabilities\r\n"); + TRACE("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -620,7 +767,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { - uart_tx_str_sync("indicate\r\n"); + TRACE("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -633,7 +780,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { - uart_tx_str_sync("read stb\r\n"); + TRACE("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -672,7 +819,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { - uart_tx_str_sync("Unsupported REN/GTL/LLO\r\n"); + TRACE("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -680,7 +827,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: - uart_tx_str_sync("Default CTRL handler\r\n"); + TRACE("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a0ba82e30..4c991d5ff 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,9 +64,13 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult); +bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult); bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); From 99d03fcaee64104df96e332a2347aa7ecc1b6172 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 19:30:44 -0400 Subject: [PATCH 52/94] small fixes --- examples/device/usbtmc/src/usbtmc_app.c | 10 +++++----- src/class/usbtmc/usbtmc_device.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 03800ab17..7132f5143 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -86,7 +86,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; - uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); + //uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); return true; } bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { @@ -100,12 +100,12 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) - uart_tx_str_sync("MSG_OUT_DATA: <<<"); + /*uart_tx_str_sync("MSG_OUT_DATA: <<<"); uart_tx_sync(data,len); uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); - +*/ if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; } @@ -132,7 +132,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; - uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); + //uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -169,7 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); + //uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index c71d4d963..0f14fdfb4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -31,8 +31,6 @@ * This file is part of the TinyUSB stack. */ -#include "tusb_option.h" - // Synchronization is needed in some spots. // These functions should NOT be called from interrupts. @@ -71,6 +69,9 @@ // Abort bulk in/out // No CLEAR_FEATURE/HALT no EP (yet) + +#include "tusb_option.h" + #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) #include @@ -78,8 +79,12 @@ #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" + +#ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; +#endif + // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" @@ -447,7 +452,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - uart_tx_sync("Handling msg in req\r\n", 21); + TRACE("Handling msg in req\r\n"); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -643,7 +648,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } From 9a726dc7ed9af8f9b035b18a667105a48d8d6d8a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 21:31:38 -0400 Subject: [PATCH 53/94] More fixes, and a bit of SRQ. --- examples/device/usbtmc/src/usbtmc_app.c | 78 ++++++++++++++++++------- examples/device/usbtmc/visaQuery.py | 69 ++++++++++++++++++++++ src/class/usbtmc/usbtmc_device.c | 44 +++++++------- 3 files changed, 150 insertions(+), 41 deletions(-) create mode 100644 examples/device/usbtmc/visaQuery.py diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7132f5143..024f7de10 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 N Conrad + * Copyright (c) 2019 Nathan Conrad * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -73,6 +73,11 @@ static volatile uint8_t status; static volatile uint16_t queryState = 0; static volatile uint32_t queryDelayStart; static volatile uint32_t bulkInStarted; +static volatile uint32_t idnQuery; + +static size_t buffer_len; +static uint8_t buffer[225]; // A few packets long should be enough. + static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { .bmTransferAttributes = @@ -82,16 +87,20 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; +bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { + (void)rhport; + (void)msg; + return true; +} + bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)rhport; (void)msgHeader; - //uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); - return true; -} -bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { - (void)rhport; - (void)msg; +#ifdef xDEBUG + uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); +#endif + buffer_len = 0; return true; } @@ -100,14 +109,25 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) - /*uart_tx_str_sync("MSG_OUT_DATA: <<<"); +#ifdef xDEBUG + uart_tx_str_sync("MSG_OUT_DATA: <<<"); uart_tx_sync(data,len); uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); -*/ - if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { - queryState = 1; +#endif + + if(len + buffer_len < sizeof(buffer)) + { + memcpy(&(buffer[buffer_len]), data, len); + buffer_len += len; + } + queryState = transfer_complete; + idnQuery = 0; + + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) + { + idnQuery = 1; } return true; } @@ -116,7 +136,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; - status &= (uint8_t)~(0x10u); // clear MAV + status &= (uint8_t)~(0x50u); // clear MAV and SRQ return true; } @@ -131,8 +151,9 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; - - //uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); +#ifdef xDEBUG + uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); +#endif TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -145,7 +166,11 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; - + uint32_t board_delay = 5u; + if(idnQuery) + { + board_delay = 350u; + } switch(queryState) { case 0: break; @@ -154,14 +179,15 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 200u) { + if( (board_millis() - queryDelayStart) > board_delay) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV + status |= 0x40u; // SRQ } break; case 3: - if( (board_millis() - queryDelayStart) > 400u) { + if( (board_millis() - queryDelayStart) > board_delay) { queryState = 4; } break; @@ -169,8 +195,17 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - //uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); +#ifdef xDEBUG + uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); +#endif + if(idnQuery) + { + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + } + else + { + usbtmcd_transmit_dev_msg_data(rhport, buffer, tu_min32(buffer_len,msgReqLen),false); + } // MAV is cleared in the transfer complete callback. } break; @@ -235,10 +270,13 @@ void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; + uint8_t old_status = status; + status = status & ~(0x40); // clear SRQ + *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... - return status; + return old_status; } bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py new file mode 100644 index 000000000..fa3d7f5e8 --- /dev/null +++ b/examples/device/usbtmc/visaQuery.py @@ -0,0 +1,69 @@ +import visa +import time +import sys + + +def test_idn(): + idn = inst.query("*idn?"); + assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" + +def test_echo(): + longstr = "0123456789abcdef" * 50 + + #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) + for i in range(49,175): + x = longstr[0:i] + xt = x + inst.write_termination + y = inst.query(x) + assert(xt == y), f"echo {i}" + +def test_mav(): + assert (inst.read_stb() == 0) + inst.write("123") + time.sleep(0.3) + assert (inst.read_stb() & 0x10), "MAV not set after 0.5 seconds" + + rsp = inst.read() + assert(rsp == "123\r\n") + + +def test_srq(): + assert (inst.read_stb() == 0) + inst.write("123") + + #inst.enable_event(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE) + #waitrsp = inst.wait_on_event(visa.constants.VI_EVENT_SERVICE_REQ, 5000) + #inst.discard_events(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE) + #inst.wait_for_srq() + time.sleep(0.3) + stb = inst.read_stb() + msg = "SRQ not set after 0.5 seconds, was {:02x}".format(stb) + assert (stb == 0x50),msg + + assert (inst.read_stb() == 0x10), "SRQ set at second read!" + + rsp = inst.read() + assert(rsp == "123\r\n") + + +rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") +reslist = rm.list_resources("USB?::?*::INSTR") +print(reslist) + +if (len(reslist) == 0): + sys.exit() + +inst = rm.open_resource(reslist[0]); +inst.timeout = 3000 +inst.clear() + +#print(idn); +inst.clear() + +test_idn() +test_echo() +test_mav() +test_srq() + +inst.close() +print("Test complete") diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 0f14fdfb4..27876852d 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -371,6 +371,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack len = usbtmc_state.transfer_size_remaining; usbtmcd_app_msg_data(rhport,data, len, atEnd); + usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; if(atEnd) { @@ -476,11 +477,12 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_RCV: TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_ABORTING_BULK_OUT: TU_VERIFY(false); - return false; // Shold be stalled by now... + return false; // Should be stalled by now... case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: @@ -516,32 +518,32 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { + { TRACE("IN TX continuing\r\n"); - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); + } + else // last packet + { TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) - { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; - packetLen++; - } + packetLen++; + } usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: @@ -554,7 +556,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint /* Done. :)*/ TRACE("IN shorted\r\n"); usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; + return true; default: TRACE("IN unknown\r\n"); TU_ASSERT(false); @@ -667,7 +669,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_remaining = 0; // Check if we've queued a short packet usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; From d4b2dff7c40f005be3ce4d383efcb59182a9a228 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 23:53:28 -0400 Subject: [PATCH 54/94] Fix more TX bugs... and add variable response delay to the example project. --- examples/device/usbtmc/src/usbtmc_app.c | 27 ++++++++++------ examples/device/usbtmc/visaQuery.py | 37 +++++++++++++++++----- src/class/usbtmc/usbtmc_device.c | 42 ++++++++++--------------- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 024f7de10..7c7431928 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -24,6 +24,7 @@ */ #include +#include /* atoi */ #include "class/usbtmc/usbtmc_device.h" #include "bsp/board.h" #include "main.h" @@ -75,6 +76,7 @@ static volatile uint32_t queryDelayStart; static volatile uint32_t bulkInStarted; static volatile uint32_t idnQuery; +static uint32_t resp_delay = 125u; // Adjustable delay, to allow for better testing static size_t buffer_len; static uint8_t buffer[225]; // A few packets long should be enough. @@ -115,6 +117,8 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); + sprintf(bigMsg, "len=%u complete=%u\r\n",len,(uint32_t)transfer_complete); + uart_tx_str_sync(bigMsg); #endif if(len + buffer_len < sizeof(buffer)) @@ -129,6 +133,13 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ { idnQuery = 1; } + if(transfer_complete && !strncasecmp("delay ",data,5)) + { + queryState = 0; + resp_delay = atoi((char*)data + 5); + if(resp_delay > 10000u) + resp_delay = 10000u; + } return true; } @@ -166,11 +177,6 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; - uint32_t board_delay = 5u; - if(idnQuery) - { - board_delay = 350u; - } switch(queryState) { case 0: break; @@ -179,7 +185,7 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > board_delay) { + if( (board_millis() - queryDelayStart) > resp_delay) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV @@ -187,7 +193,7 @@ void usbtmc_app_task_iter(void) { } break; case 3: - if( (board_millis() - queryDelayStart) > board_delay) { + if( (board_millis() - queryDelayStart) > resp_delay) { queryState = 4; } break; @@ -200,7 +206,7 @@ void usbtmc_app_task_iter(void) { #endif if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); } else { @@ -237,17 +243,20 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) } bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { + (void)rhport; return true; } bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; @@ -271,7 +280,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; - status = status & ~(0x40); // clear SRQ + status = status & ~(0x40u); // clear SRQ *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index fa3d7f5e8..2034e6ff7 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -7,15 +7,20 @@ def test_idn(): idn = inst.query("*idn?"); assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" -def test_echo(): - longstr = "0123456789abcdef" * 50 +def test_echo(m,n): + longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) - for i in range(49,175): + for i in range(m,n): + #print(i) x = longstr[0:i] xt = x + inst.write_termination y = inst.query(x) - assert(xt == y), f"echo {i}" + #print(x) + #print (":".join("{:02x}".format(ord(c)) for c in xt)) + #print (":".join("{:02x}".format(ord(c)) for c in y)) + assert(xt == y), f"failed i={i}" + inst.read_stb();# Just to make USB logging easier by sending a control query def test_mav(): assert (inst.read_stb() == 0) @@ -57,12 +62,28 @@ inst = rm.open_resource(reslist[0]); inst.timeout = 3000 inst.clear() -#print(idn); -inst.clear() +#print("+ IDN") +#test_idn() -test_idn() -test_echo() +print("+ random trigger") +#inst.assert_trigger(); + +print("+ echo delay=0") +inst.write("delay 0") +test_echo(1,175) + +print("+ echo delay=2") +inst.write("delay 2") +test_echo(1,175) + +print("+ echo delay=200") +inst.write("delay 200") +test_echo(50,90) +test_echo(165,170) + +print("+ MAV") test_mav() +print("+ SRQ") test_srq() inst.close() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 27876852d..eab4397ba 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -203,12 +203,6 @@ bool usbtmcd_transmit_dev_msg_data( { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); packetLen = (uint16_t)(packetLen + hdr->TransferSize); - // Pad up to multiple of 4 bytes - while((packetLen % 4) != 0) - { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0; - packetLen++; - } usbtmc_state.transfer_size_remaining = 0; usbtmc_state.transfer_size_sent = len; usbtmc_state.devInBuffer = NULL; @@ -518,32 +512,28 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - TRACE("IN TX continuing\r\n"); - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { - TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; - packetLen++; + TRACE("IN TX continuing\r\n"); + // FIXME! This removes const below! + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, + (void*)usbtmc_state.devInBuffer,sizeof(usbtmc_state.ep_bulk_in_buf))); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); } + else // last packet + { + TRACE("IN TX last packet\r\n"); + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: From 85623584f99dfa0a974ffe62639e58a0f2589674 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 09:24:52 -0400 Subject: [PATCH 55/94] Remove debug assertions. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 46 +------------------ 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index e2df2abe4..71c7ff7ce 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -168,11 +168,6 @@ static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; static xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) { -#ifndef NDEBUG - TU_ASSERT(epnum < MAX_EP_COUNT); - TU_ASSERT(dir < 2u); -#endif - return &xfer_status[epnum][dir]; } @@ -587,32 +582,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); const uint16_t epMaxPktSize = p_endpoint_desc->wMaxPacketSize.size; // Isochronous not supported (yet), and some other driver assumptions. -#ifndef NDEBUG + TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); - switch(p_endpoint_desc->bmAttributes.xfer) { - case TUSB_XFER_CONTROL: - // USB 2.0 spec on FS packets, 5.5.3 (control) - TU_ASSERT((epMaxPktSize == 8) ||(epMaxPktSize == 16) || (epMaxPktSize == 32) || (epMaxPktSize == 64)); - break; - case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported - TU_ASSERT(epMaxPktSize <= 1023); - break; - case TUSB_XFER_BULK: - // USB 2.0 spec on FS packets, 5.8.3 (bulk) - TU_ASSERT((epMaxPktSize == 8) ||(epMaxPktSize == 16) ||(epMaxPktSize == 32) ||(epMaxPktSize == 64)); - break; - case TUSB_XFER_INTERRUPT: - // USB 2.0 spec on FS packets, 5.5.3 (interrupt); interestingly 0 is allowed. - TU_ASSERT(epMaxPktSize <= 64); - break; - default: - TU_ASSERT(false); - return false; - } -#endif - // Set type switch(p_endpoint_desc->bmAttributes.xfer) { case TUSB_XFER_CONTROL: @@ -776,14 +749,6 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si uint16_t temp1, temp2; const uint8_t * srcVal; -#ifndef NDEBUG -# if (DCD_STM32_BTABLE_BASE > 0u) - TU_ASSERT(dst >= DCD_STM32_BTABLE_BASE); -# endif - TU_ASSERT((dst%2) == 0); - TU_ASSERT((dst + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); -#endif - // The GCC optimizer will combine access to 32-bit sizes if we let it. Force // it volatile so that it won't do that. __IO uint16_t *pdwVal; @@ -818,15 +783,6 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN __IO const uint16_t *pdwVal; uint32_t temp; -#ifndef NDEBUG -# if (DCD_STM32_BTABLE_BASE > 0u) - TU_ASSERT(src >= DCD_STM32_BTABLE_BASE); -# endif - TU_ASSERT((src%2) == 0); - TU_ASSERT((src + wNBytes) <= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH)); -#endif - - pdwVal = &pma[PMA_STRIDE*(src>>1)]; uint8_t *dstVal = (uint8_t*)dst; From 642afeea8b7189cd37e2bbf87427df95f5587c72 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 09:28:19 -0400 Subject: [PATCH 56/94] s/static const/define/ --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index e205979fc..ff25df048 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -46,7 +46,7 @@ defined(STM32F072xB) | \ defined(STM32F078xx) #include "stm32f0xx.h" -#define PMA_LENGTH 1024 +#define PMA_LENGTH (1024u) // F0x2 models are crystal-less // All have internal D+ pull-up // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support @@ -55,7 +55,7 @@ defined(STM32F103x6) | defined(STM32F103xB) | \ defined(STM32F103xE) | defined(STM32F103xB) #include "stm32f1xx.h" -#define PMA_LENGTH 512u +#define PMA_LENGTH (512u) // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word #error The F102/F103 driver is expected not to work, but it might? Try it? @@ -64,7 +64,7 @@ defined(STM32F303xB) | defined(STM32F303xC) | \ defined(STM32F373xC) #include "stm32f3xx.h" -#define PMA_LENGTH 512u +#define PMA_LENGTH (512u) // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) @@ -72,7 +72,7 @@ defined(STM32F302xD) | defined(STM32F302xE) | \ defined(STM32F303xD) | defined(STM32F303xE) | \ #include "stm32f3xx.h" -#define PMA_LENGTH 1024u +#define PMA_LENGTH (1024u) // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support // When CAN clock is enabled, USB can use first 768 bytes ONLY. @@ -83,9 +83,9 @@ // For purposes of accessing the packet #if ((PMA_LENGTH) == 512u) -const size_t PMA_STRIDE = 2u; +#define PMA_STRIDE (2u) #elif ((PMA_LENGTH) == 1024u) -const size_t PMA_STRIDE = 1u; +#define PMA_STRIDE (1u) #endif // And for type-safety create a new macro for the volatile address of PMAADDR From 525b4cdb720d79836d80be2664037bf89961111a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 09:51:40 -0400 Subject: [PATCH 57/94] Use ESOF for wakeup timing. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 71c7ff7ce..aec8ea0c7 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -121,7 +121,6 @@ #undef USE_HAL_DRIVER #include "device/dcd.h" -#include "bsp/board.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" @@ -174,6 +173,7 @@ static xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; static uint8_t newDADDR; // Used to set the new device address during the CTR IRQ handler +static uint8_t remoteWakeCountdown; // When wake is requested // EP Buffers assigned from end of memory location, to minimize their chance of crashing // into the stack. @@ -235,7 +235,7 @@ void dcd_init (uint8_t rhport) { pma[PMA_STRIDE*(DCD_STM32_BTABLE_BASE + i)] = 0u; } - USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); // And finally enable pull-up, which may trigger the RESET IRQ if the host is connected. @@ -304,17 +304,9 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - uint32_t start; USB->CNTR |= (uint16_t)USB_CNTR_RESUME; - /* Wait 1 to 15 ms */ - /* Busy loop is bad, but the osal_task_delay() isn't implemented for the "none" OSAL */ - start = board_millis(); - while ((board_millis() - start) < 2) - { - ; - } - USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); + remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } // I'm getting a weird warning about missing braces here that I don't @@ -566,6 +558,18 @@ static void dcd_fs_irqHandler(void) { reg16_clear_bits(&USB->ISTR, USB_ISTR_SOF); dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } + + if(int_status & USB_ISTR_ESOF) { + if(remoteWakeCountdown == 1u) + { + USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); + } + if(remoteWakeCountdown > 0u) + { + remoteWakeCountdown--; + } + reg16_clear_bits(&USB->ISTR, USB_ISTR_ESOF); + } } //--------------------------------------------------------------------+ From 0548f97d3300edb4d57f6920f6307211833917f2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 16:25:59 -0400 Subject: [PATCH 58/94] Remove debug printf. --- examples/device/usbtmc/src/usbtmc_app.c | 16 +---- src/class/usbtmc/usbtmc_device.c | 82 ++++--------------------- 2 files changed, 12 insertions(+), 86 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7c7431928..8ce468561 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -99,9 +99,6 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; -#ifdef xDEBUG - uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); -#endif buffer_len = 0; return true; } @@ -111,15 +108,6 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) -#ifdef xDEBUG - uart_tx_str_sync("MSG_OUT_DATA: <<<"); - uart_tx_sync(data,len); - uart_tx_str_sync(">>>\r\n"); - if(transfer_complete) - uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); - sprintf(bigMsg, "len=%u complete=%u\r\n",len,(uint32_t)transfer_complete); - uart_tx_str_sync(bigMsg); -#endif if(len + buffer_len < sizeof(buffer)) { @@ -201,9 +189,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; -#ifdef xDEBUG - uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); -#endif + if(idnQuery) { usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index eab4397ba..3a4e9e3e0 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -137,11 +137,6 @@ static usbtmc_interface_state_t usbtmc_state = .ep_bulk_out = 0, .ep_int_in = 0 }; -#ifdef xDEBUG -#define TRACE(str) uart_tx_str_sync(str) -#else -#define TRACE(STR) do {} while (0) -#endif // We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); @@ -383,11 +378,6 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; -#ifdef xDebug - sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); - TRACE(logMsg); -#endif - criticalEnter(); { TU_VERIFY(usbtmc_state.state == STATE_IDLE); @@ -409,14 +399,8 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - TRACE("USBTMC Xfer CB" ); TU_VERIFY(result == XFER_RESULT_SUCCESS); -#ifdef xDebug - sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); - TRACE(logMsg); -#endif - if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ } @@ -424,7 +408,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(ep_addr == usbtmc_state.ep_bulk_out) { usbtmc_msg_generic_t *msg = NULL; - TRACE("OUT"); + switch(usbtmc_state.state) { case STATE_IDLE: @@ -434,11 +418,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); -#ifdef xDebug - sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); - TRACE(logMsg); -#endif - switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: usbtmc_state.transfer_size_sent = 0u; @@ -447,7 +426,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - TRACE("Handling msg in req\r\n"); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -484,71 +462,52 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_IN_ABORTED: default: -#ifdef xDebug - if(msg == NULL) - sprintf(logMsg," Unknown received control?\r\n "); - else { - sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); - } - TRACE(logMsg); -#endif TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { -#ifdef xDebug - sprintf(logMsg,"IN\r\n"); - TRACE(logMsg); -#endif switch(usbtmc_state.state) { case STATE_TX_SHORTED: - TRACE("IN TX shorted done\r\n"); - usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); break; case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - TRACE("IN TX continuing\r\n"); + { // FIXME! This removes const below! TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, (void*)usbtmc_state.devInBuffer,sizeof(usbtmc_state.ep_bulk_in_buf))); usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + } + else // last packet + { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: // need to send short packet (ZLP?) - TRACE("IN aborting\r\n"); TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; return true; case STATE_ABORTING_BULK_IN_SHORTED: /* Done. :)*/ - TRACE("IN shorted\r\n"); usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; return true; default: - TRACE("IN unknown\r\n"); TU_ASSERT(false); return false; } @@ -566,14 +525,12 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif - TRACE("xfer cb\r\n"); if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - TRACE("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -602,7 +559,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_initiate_abort_rsp_t rsp = { .bTag = usbtmc_state.lastBulkOutTag, }; - TRACE("init abort bulk out\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); @@ -611,12 +567,10 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ if(usbtmc_state.state != STATE_RCV) { rsp.USBTMC_status = USBTMC_STATUS_FAILED; - TRACE("init abort bulk out failed\r\n"); } else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) { rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - TRACE("init abort bulk out not inprogress\r\n"); } else { @@ -625,14 +579,12 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.state = STATE_ABORTING_BULK_OUT; TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TRACE("init abort bulk out success\r\n"); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { - TRACE("init check abort bulk out\r\n"); usbtmc_check_abort_bulk_rsp_t rsp = { .USBTMC_status = USBTMC_STATUS_SUCCESS, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent @@ -650,7 +602,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_initiate_abort_rsp_t rsp = { .bTag = usbtmc_state.lastBulkInTag, }; - TRACE("init abort bulk in\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); @@ -664,17 +615,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); - TRACE("init abort bulk success\r\n"); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - TRACE("init abort bulk in not in progress\r\n"); } else { rsp.USBTMC_status = USBTMC_STATUS_FAILED; - TRACE("init abort bulk in failed\r\n"); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; @@ -682,7 +630,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: { - TRACE("xfer check abort in\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == 8u); @@ -715,7 +662,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INITIATE_CLEAR: { - TRACE("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the @@ -730,7 +676,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - TRACE("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); @@ -754,7 +699,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { - TRACE("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -764,7 +708,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { - TRACE("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -777,7 +720,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { - TRACE("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -816,7 +758,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { - TRACE("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -824,7 +765,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: - TRACE("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } From 0f1435177b15b739188d08d08563e02e1bf2edde Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 16:43:59 -0400 Subject: [PATCH 59/94] Add trigger test code. --- examples/device/usbtmc/src/usbtmc_app.c | 24 +++++++++++++++++++----- examples/device/usbtmc/visaQuery.py | 23 +++++++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 8ce468561..ea6e6aa6f 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -65,6 +65,12 @@ usbtmcd_app_capabilities = } #endif }; + +#define IEEE4882_STB_QUESTIONABLE (0x08u) +#define IEEE4882_STB_MAV (0x10u) +#define IEEE4882_STB_SER (0x20u) +#define IEEE4882_STB_SRQ (0x40u) + static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n"; //static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps? lets make it three transfers...\n"; static volatile uint8_t status; @@ -92,6 +98,8 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; + // Let trigger set the SRQ + status |= IEEE4882_STB_SRQ; return true; } @@ -124,9 +132,12 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ if(transfer_complete && !strncasecmp("delay ",data,5)) { queryState = 0; - resp_delay = atoi((char*)data + 5); - if(resp_delay > 10000u) - resp_delay = 10000u; + int d = atoi((char*)data + 5); + if(d > 10000) + d = 10000; + if(d<0) + d=0; + resp_delay = (uint32_t)d; } return true; } @@ -135,7 +146,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; - status &= (uint8_t)~(0x50u); // clear MAV and SRQ + status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV return true; } @@ -237,6 +248,7 @@ bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; + (void)rsp; return true; } @@ -249,6 +261,8 @@ bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) } bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { + (void)rhport; + (void)rsp; return true; } @@ -266,7 +280,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; - status = status & ~(0x40u); // clear SRQ + status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 2034e6ff7..9610cbc8f 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -22,6 +22,16 @@ def test_echo(m,n): assert(xt == y), f"failed i={i}" inst.read_stb();# Just to make USB logging easier by sending a control query +def test_trig(): + # clear SRQ + inst.read_stb() + assert (inst.read_stb() == 0) + inst.assert_trigger() + time.sleep(0.3) # SRQ may have some delay + assert (inst.read_stb() & 0x40), "SRQ not set after 0.3 seconds" + assert (inst.read_stb() == 0) + + def test_mav(): assert (inst.read_stb() == 0) inst.write("123") @@ -65,9 +75,6 @@ inst.clear() #print("+ IDN") #test_idn() -print("+ random trigger") -#inst.assert_trigger(); - print("+ echo delay=0") inst.write("delay 0") test_echo(1,175) @@ -76,15 +83,19 @@ print("+ echo delay=2") inst.write("delay 2") test_echo(1,175) -print("+ echo delay=200") -inst.write("delay 200") -test_echo(50,90) +print("+ echo delay=150") +inst.write("delay 150") +test_echo(53,76) test_echo(165,170) print("+ MAV") test_mav() + print("+ SRQ") test_srq() +print("+ TRIG") +test_trig() + inst.close() print("Test complete") From 346443118fa9f22611ca1382ff999e43b6a40b43 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 18:58:15 -0400 Subject: [PATCH 60/94] Add testcase for aborting bulk in with no data queued (and fix aborting bulk in) --- examples/device/usbtmc/src/usbtmc_app.c | 2 +- examples/device/usbtmc/visaQuery.py | 29 +++++++++++++++++++++++-- src/class/usbtmc/usbtmc_device.c | 14 +++++++++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index ea6e6aa6f..0d03a5ef1 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -203,7 +203,7 @@ void usbtmc_app_task_iter(void) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); } else { diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 9610cbc8f..368b66053 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -3,6 +3,7 @@ import time import sys + def test_idn(): idn = inst.query("*idn?"); assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" @@ -60,6 +61,24 @@ def test_srq(): rsp = inst.read() assert(rsp == "123\r\n") + + +def test_read_timeout(): + inst.timeout = 500 + # First read with no MAV + inst.read_stb() + assert (inst.read_stb() == 0) + inst.write("delay 500") + t0 = time.time() + try: + rsp = inst.read() + assert(false), "Read should have resulted in timeout" + except visa.VisaIOError: + print("Got expected exception") + t = time.time() - t0 + assert ((t*1000.0) > (inst.timeout - 300)) + assert ((t*1000.0) < (inst.timeout + 300)) + print(f"Delay was {t}") rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") reslist = rm.list_resources("USB?::?*::INSTR") @@ -72,8 +91,11 @@ inst = rm.open_resource(reslist[0]); inst.timeout = 3000 inst.clear() -#print("+ IDN") -#test_idn() +print("+ IDN") +test_idn() + +inst.timeout = 3000 + print("+ echo delay=0") inst.write("delay 0") @@ -88,6 +110,9 @@ inst.write("delay 150") test_echo(53,76) test_echo(165,170) +print("+ Read timeout (no MAV") +test_read_timeout() + print("+ MAV") test_mav() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 3a4e9e3e0..db00b841f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -102,7 +102,7 @@ typedef enum STATE_CLEARING, STATE_ABORTING_BULK_IN, STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted STATE_ABORTING_BULK_OUT, STATE_NUM_STATES } usbtmcd_state_enum; @@ -384,6 +384,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) usbtmc_state.state = STATE_TX_REQUESTED; usbtmc_state.lastBulkInTag = msg->header.bTag; usbtmc_state.transfer_size_remaining = msg->TransferSize; + usbtmc_state.transfer_size_sent = 0u; } criticalLeave(); @@ -612,8 +613,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; usbtmc_state.transfer_size_remaining = 0; // Check if we've queued a short packet - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + if(usbtmc_state.transfer_size_sent == 0) + { + // Send short packet, nothing is in the buffer yet + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + } TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) @@ -638,7 +645,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ .USBTMC_status = USBTMC_STATUS_FAILED, .bmAbortBulkIn = { - .BulkInFifoBytes = (usbtmc_state.state == STATE_ABORTING_BULK_IN_ABORTED) + .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; @@ -647,6 +654,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { case STATE_ABORTING_BULK_IN_ABORTED: rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.state = STATE_IDLE; break; case STATE_ABORTING_BULK_IN: case STATE_ABORTING_BULK_OUT: From 7e0490bbf32ed4a25e1917a1e5856338b9dc9346 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:51:37 -0400 Subject: [PATCH 61/94] Move descriptors to usbd.h --- examples/device/usbtmc/src/usb_descriptors.c | 20 ++++++------- src/class/usbtmc/usbtmc_device.c | 5 ++-- src/class/usbtmc/usbtmc_device.h | 30 ------------------- src/device/usbd.c | 3 +- src/device/usbd.h | 31 ++++++++++++++++++++ 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 792fff87c..45e1001ea 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -105,16 +105,16 @@ uint8_t const * tud_hid_descriptor_report_cb(void) #if defined(CFG_TUD_USBTMC) -# define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ - USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, USBTMC_PROTOCOL_USB488), \ - USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) +# define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ + TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \ + TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83, /* packet size = */USBTMCD_MAX_PACKET_SIZE) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) // Interrupt endpoint should be 2 bytes on a FS USB link -# define USBTMC_DESC(_itfnum) \ - USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) -# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) +# define TUD_USBTMC_DESC(_itfnum) \ + TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ + TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) +# define USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN) #else @@ -174,7 +174,7 @@ uint8_t const desc_configuration[] = #endif #if CFG_TUD_USBTMC - USBTMC_DESC(ITF_NUM_USBTMC), + TUD_USBTMC_DESC(ITF_NUM_USBTMC), #endif #if CFG_TUD_MSC @@ -218,7 +218,7 @@ static uint16_t _desc_str[32]; // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index) { - uint8_t chr_count; + size_t chr_count; if ( index == 0) { @@ -246,7 +246,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) } // first byte is length (including header), second byte is string type - _desc_str[0] = (((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u); + _desc_str[0] = (uint16_t)((((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u)); return _desc_str; } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index db00b841f..f62bcd2b7 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -251,9 +251,9 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 usbtmcd_reset(rhport); // Perhaps there are other application specific class drivers, so don't assert here. - if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) + if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) return false; - if( itf_desc->bInterfaceSubClass != USBTMC_APP_SUBCLASS) + if( itf_desc->bInterfaceSubClass != TUD_USBTMC_APP_SUBCLASS) return false; // Only 2 or 3 endpoints are allowed for USBTMC. @@ -272,6 +272,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; switch(ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: + TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE); if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 4c991d5ff..1e28563dd 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -107,35 +107,5 @@ void usbtmcd_init(void); * USBTMC Descriptor Templates *************************************************************/ -#define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC -#define USBTMC_APP_SUBCLASS 0x03u - -#define USBTMC_PROTOCOL_STD 0x00u -#define USBTMC_PROTOCOL_USB488 0x01u - -// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, -// bulk-in endpoint ID -#define USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ -/* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, USBTMC_APP_CLASS, USBTMC_APP_SUBCLASS, _itfProtocol, _stridx - -#define USBTMC_IF_DESCRIPTOR_LEN 9u - -// bulk-out Size must be a multiple of 4 bytes -#define USBTMC_BULK_DESCRIPTORS(_epout, _epin) \ -/* Endpoint Out */ \ -7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u, \ -/* Endpoint In */ \ -7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u - -#define USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) - -/* optional interrupt endpoint */ \ -// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? -#define USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ -7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 - -#define USBTMC_INT_DESCRIPTOR_LEN (7u) - #endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 2f8967fae..f8f1da82e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -151,7 +151,8 @@ static usbd_class_driver_t const usbd_class_drivers[] = // We maybe need to add subclass codes here, or a callback to ask if a driver can // handle a particular interface. { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .class_code = TUD_USBTMC_APP_CLASS, + //.subclass_code = TUD_USBTMC_APP_SUBCLASS .init = usbtmcd_init, .reset = usbtmcd_reset, .open = usbtmcd_open, diff --git a/src/device/usbd.h b/src/device/usbd.h index 5f96e55a4..f0887f0db 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -261,6 +261,37 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* MS Endpoint (connected to embedded jack out) */\ 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3 +//------------- TUD_USBTMC/USB488 -------------// +#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) +#define TUD_USBTMC_APP_SUBCLASS 0x03u + +#define TUD_USBTMC_PROTOCOL_STD 0x00u +#define TUD_USBTMC_PROTOCOL_USB488 0x01u + +// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, +// bulk-in endpoint ID +#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ +/* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + +#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u + +#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ +/* Endpoint Out */ \ +7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ +/* Endpoint In */ \ +7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + +#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) + +/* optional interrupt endpoint */ \ +// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? +#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ +7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + +#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) + + //------------- Vendor -------------// #define TUD_VENDOR_DESC_LEN (9+7+7) From d742c3e15cb2233e927d6fdc4702863dc41eb65a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:54:37 -0400 Subject: [PATCH 62/94] s/USBTMC488/USB488/ ; fix types in bitfield --- src/class/usbtmc/usbtmc.h | 14 +++++++------- src/class/usbtmc/usbtmc_device.c | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 0944c907a..810b523c5 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -139,9 +139,9 @@ TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct w /* typedef struct TU_ATTR_PACKED { struct { - uint8_t Recipient : 5 ; ///< EOM set on last byte - uint8_t Type : 2 ; ///< EOM set on last byte - uint8_t DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN + unsigned int Recipient : 5 ; ///< EOM set on last byte + unsigned int Type : 2 ; ///< EOM set on last byte + unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN } bmRequestType; uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum uint16_t wValue ; @@ -176,10 +176,10 @@ typedef enum { USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional /****** USBTMC 488 *************/ - USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, - USBTMC488_bREQUEST_REN_CONTROL = 160u, - USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, - USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, + USB488_bREQUEST_READ_STATUS_BYTE = 128u, + USB488_bREQUEST_REN_CONTROL = 160u, + USB488_bREQUEST_GO_TO_LOCAL = 161u, + USB488_bREQUEST_LOCAL_LOCKOUT = 162u, } usmtmc_request_type_enum; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index f62bcd2b7..6306ab074 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -727,7 +727,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) // USB488 required requests - case USBTMC488_bREQUEST_READ_STATUS_BYTE: + case USB488_bREQUEST_READ_STATUS_BYTE: { usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface @@ -763,9 +763,9 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ return true; } // USB488 optional requests - case USBTMC488_bREQUEST_REN_CONTROL: - case USBTMC488_bREQUEST_GO_TO_LOCAL: - case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + case USB488_bREQUEST_REN_CONTROL: + case USB488_bREQUEST_GO_TO_LOCAL: + case USB488_bREQUEST_LOCAL_LOCKOUT: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); From f3d6d0127b4e4f1c7d986e27b5c8b42378dda999 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:59:44 -0400 Subject: [PATCH 63/94] Rename USBTMC_CFG_ENABLE_488, and fix build with it off. --- examples/device/usbtmc/src/tusb_config.h | 2 +- examples/device/usbtmc/src/usbtmc_app.c | 4 ++-- src/class/usbtmc/usbtmc_device.c | 11 ++++++----- src/class/usbtmc/usbtmc_device.h | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 16484424a..688fb02be 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -57,7 +57,7 @@ #define CFG_TUD_USBTMC 1 #define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define USBTMC_CFG_ENABLE_488 1 +#define CFG_USBTMC_CFG_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 0d03a5ef1..895c65b26 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "main.h" -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const @@ -48,7 +48,7 @@ usbtmcd_app_capabilities = .canEndBulkInOnTermChar = 0 }, -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6306ab074..d4a6a0db0 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -227,7 +227,7 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { #ifndef NDEBUG -# if USBTMC_CFG_ENABLE_488 +# if CFG_USBTMC_CFG_ENABLE_488 if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); // Per USB488 spec: table 8 @@ -310,12 +310,13 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 { TU_ASSERT(usbtmc_state.ep_int_in != 0); } - +#if (USBTMC_CFG_ENABLE_488) if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || usbtmcd_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } +#endif #endif TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); @@ -431,7 +432,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; -#ifdef USBTMC_CFG_ENABLE_488 +#if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); @@ -524,7 +525,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif @@ -724,7 +725,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) // USB488 required requests case USB488_bREQUEST_READ_STATUS_BYTE: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 1e28563dd..3c8d10572 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -37,8 +37,8 @@ #include "usbtmc.h" // Enable 488 mode by default -#if !defined(USBTMC_CFG_ENABLE_488) -#define USBTMC_CFG_ENABLE_488 (1) +#if !defined(CFG_USBTMC_CFG_ENABLE_488) +#define CFG_CFG_USBTMC_CFG_ENABLE_488 (1) #endif // USB spec says that full-speed must be 8,16,32, or 64. @@ -49,7 +49,7 @@ * Functions to be implemeted by the class implementation */ -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; #else extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; @@ -75,7 +75,7 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); From 2a7ca15e2ce7df5f0271438bd58007ccf558eb4d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 20:08:45 -0400 Subject: [PATCH 64/94] Rename functions to include tud_ and _cb --- examples/device/usbtmc/src/usbtmc_app.c | 34 ++++++------ src/class/usbtmc/usbtmc.h | 2 +- src/class/usbtmc/usbtmc_device.c | 72 ++++++++++++------------- src/class/usbtmc/usbtmc_device.h | 46 ++++++++-------- src/device/usbd.c | 10 ++-- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 895c65b26..f8c350f68 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,7 +25,7 @@ #include #include /* atoi */ -#include "class/usbtmc/usbtmc_device.h" +#include "tusb.h" #include "bsp/board.h" #include "main.h" @@ -34,7 +34,7 @@ usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const #endif -usbtmcd_app_capabilities = +tud_usbtmc_app_capabilities = { .USBTMC_status = USBTMC_STATUS_SUCCESS, .bcdUSBTMC = USBTMC_VERSION, @@ -95,7 +95,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { +bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; // Let trigger set the SRQ @@ -103,7 +103,7 @@ bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { return true; } -bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)rhport; (void)msgHeader; @@ -111,7 +111,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out return true; } -bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete) { (void)rhport; @@ -142,7 +142,7 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ return true; } -bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) +bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) { (void)rhport; @@ -153,7 +153,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) static unsigned int msgReqLen; -bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { (void)rhport; @@ -218,7 +218,7 @@ void usbtmc_app_task_iter(void) { } } -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; @@ -228,7 +228,7 @@ bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) return true; } -bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { (void)rhport; queryState = 0; @@ -238,45 +238,45 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; (void)rsp; return true; } -bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; (void)rsp; return true; } -void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) +void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) { (void)rhport; } -void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) +void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) { (void)rhport; } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; @@ -288,7 +288,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)rhport; (void)msg; diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 810b523c5..7d7005c2e 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -300,7 +300,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); -typedef struct TU_ATTR_PACKET +typedef struct TU_ATTR_PACKED { struct TU_ATTR_PACKED { diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d4a6a0db0..d550a716f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -174,7 +174,7 @@ bool usbtmcd_transmit_dev_msg_data( TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); if(usingTermChar) { - TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[len-1] == termChar); } @@ -224,31 +224,31 @@ bool usbtmcd_transmit_dev_msg_data( return true; } -void usbtmcd_init(void) +void usbtmcd_init_cb(void) { #ifndef NDEBUG # if CFG_USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 - TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.talkOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif - if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } -bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; uint8_t const * p_desc; uint8_t found_endpoints = 0; - usbtmcd_reset(rhport); + usbtmcd_reset_cb(rhport); // Perhaps there are other application specific class drivers, so don't assert here. if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) @@ -311,8 +311,8 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 TU_ASSERT(usbtmc_state.ep_int_in != 0); } #if (USBTMC_CFG_ENABLE_488) - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || - usbtmcd_app_capabilities.bmDevCapabilities488.SR1) + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || + tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -322,7 +322,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 return true; } -void usbtmcd_reset(uint8_t rhport) +void usbtmcd_reset_cb(uint8_t rhport) { // FIXME: Do endpoints need to be closed here? usbtmc_state.state = STATE_IDLE; @@ -343,7 +343,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(usbtmcd_app_msgBulkOut_start(rhport,msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); return true; @@ -360,7 +360,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - usbtmcd_app_msg_data(rhport,data, len, atEnd); + tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd); usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; @@ -394,9 +394,9 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) termChar = msg->TermChar; if(termCharRequested) - TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(rhport, msg)); return true; } @@ -435,8 +435,8 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(rhport, msg)); break; #endif @@ -474,7 +474,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_SHORTED: usbtmc_state.state = STATE_IDLE; - TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); break; case STATE_TX_INITIATED: @@ -522,7 +522,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return false; } -bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_USBTMC_CFG_ENABLE_488) @@ -536,11 +536,11 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { if((request->wIndex) == usbtmc_state.ep_bulk_out) { - usmtmcd_app_bulkOut_clearFeature(rhport); + usmtmcd_app_bulkOut_clearFeature_cb(rhport); } else if ((request->wIndex) == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature(rhport); + usmtmcd_app_bulkIn_clearFeature_cb(rhport); } return false; // We want USBD core to handle sending the status response, and clear the stall condition } @@ -580,7 +580,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; // Check if we've queued a short packet usbtmc_state.state = STATE_ABORTING_BULK_OUT; - TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -595,7 +595,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(rhport, &rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -623,7 +623,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(rhport, &(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -651,7 +651,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(usbtmcd_app_check_abort_bulk_in(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); switch(usbtmc_state.state) { case STATE_ABORTING_BULK_IN_ABORTED: @@ -679,7 +679,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); usbtmc_state.transfer_size_remaining = 0; usbtmc_state.state = STATE_CLEARING; - TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -699,7 +699,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ else { // Let app check if it's clear - TU_VERIFY(usbtmcd_app_check_clear(rhport, &clearStatusRsp)); + TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) usbtmc_state.state = STATE_IDLE; @@ -710,8 +710,8 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + TU_VERIFY(request->wLength == sizeof(tud_usbtmc_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tud_usbtmc_app_capabilities, sizeof(tud_usbtmc_app_capabilities))); return true; } // USBTMC Optional Requests @@ -720,8 +720,8 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(tud_usbtmc_app_indicator_pluse_cb(rhport, request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -752,13 +752,13 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); } else { - rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; @@ -781,7 +781,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(false); } -bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) { (void)rhport; //------------- Class Specific Request -------------// diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 3c8d10572..5c6ee2a8d 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -50,35 +50,35 @@ */ #if (CFG_USBTMC_CFG_ENABLE_488) -extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; +extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; #else -extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; +extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif -bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer -bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); -bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); -void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport); +void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer -bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); -TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg); +//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(uint8_t rhport); #endif /******************************************* @@ -96,12 +96,12 @@ bool usbtmcd_transmit_dev_msg_data( /* "callbacks" from USB device core */ -bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -void usbtmcd_reset(uint8_t rhport); +bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +void usbtmcd_reset_cb(uint8_t rhport); bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request); -void usbtmcd_init(void); +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init_cb(void); /************************************************************ * USBTMC Descriptor Templates diff --git a/src/device/usbd.c b/src/device/usbd.c index f8f1da82e..8125d0093 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -153,11 +153,11 @@ static usbd_class_driver_t const usbd_class_drivers[] = { .class_code = TUD_USBTMC_APP_CLASS, //.subclass_code = TUD_USBTMC_APP_SUBCLASS - .init = usbtmcd_init, - .reset = usbtmcd_reset, - .open = usbtmcd_open, - .control_request = usbtmcd_control_request, - .control_complete = usbtmcd_control_complete, + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_request = usbtmcd_control_request_cb, + .control_complete = usbtmcd_control_complete_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL }, From 05164c5a27eaad25f28a4fc8926297d6cd32e3fc Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 21:04:51 -0400 Subject: [PATCH 65/94] Cache pointer to HID descriptor. --- src/class/hid/hid_device.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2d579f475..7dabdbc17 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -46,12 +46,13 @@ typedef struct uint8_t boot_protocol; // Boot mouse or keyboard bool boot_mode; // default = false (Report) uint8_t idle_rate; // up to application to handle idle rate - uint16_t reprot_desc_len; + uint16_t report_desc_len; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_BUFSIZE]; -}hidd_interface_t; + tusb_hid_descriptor_hid_t const * hid_descriptor; +} hidd_interface_t; CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; @@ -167,8 +168,8 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -178,7 +179,7 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->reprot_desc_len, &desc_hid->wReportLength, 2); + memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); *p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -205,6 +206,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) { // FIXME: Should check which is the active configuration, but no callback in usbd currently exists to do that + TU_VERIFY(p_hid->hid_descriptor != NULL); tusb_desc_configuration_t const* desc_cfg = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(0); uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); @@ -227,7 +229,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque else if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { uint8_t const * desc_report = tud_hid_descriptor_report_cb(); - tud_control_xfer(rhport, p_request, (void*) desc_report, p_hid->reprot_desc_len); + tud_control_xfer(rhport, p_request, (void*) desc_report, p_hid->report_desc_len); }else { return false; // stall unsupported request @@ -273,7 +275,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque case HID_REQ_CONTROL_GET_PROTOCOL: { - uint8_t protocol = 1-p_hid->boot_mode; // 0 is Boot, 1 is Report protocol + uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); // 0 is Boot, 1 is Report protocol tud_control_xfer(rhport, p_request, &protocol, 1); } break; From 02b468f56a883ee81d1f635f0548cf43ce454c0d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 21:20:04 -0400 Subject: [PATCH 66/94] (little typo fix) --- src/class/usbtmc/usbtmc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d550a716f..fcd3376f3 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -310,7 +310,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { TU_ASSERT(usbtmc_state.ep_int_in != 0); } -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { From 80b430fcfcf4dfe4d397212330e8eaba57a4a87e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Sep 2019 13:02:17 +0700 Subject: [PATCH 67/94] added stm32L0538 discovery board, board test exmaple works --- examples/device/board_test/Makefile | 3 + hw/bsp/stm32l0538disco/STM32L053C8Tx_FLASH.ld | 169 +++++++++ hw/bsp/stm32l0538disco/board.mk | 52 +++ hw/bsp/stm32l0538disco/stm32l0538disco.c | 187 ++++++++++ hw/bsp/stm32l0538disco/stm32l0xx_hal_conf.h | 331 ++++++++++++++++++ 5 files changed, 742 insertions(+) create mode 100644 hw/bsp/stm32l0538disco/STM32L053C8Tx_FLASH.ld create mode 100644 hw/bsp/stm32l0538disco/board.mk create mode 100644 hw/bsp/stm32l0538disco/stm32l0538disco.c create mode 100644 hw/bsp/stm32l0538disco/stm32l0xx_hal_conf.h diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 5a455078e..e0c6d6ce2 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -5,6 +5,9 @@ INC += \ src \ $(TOP)/hw \ +# stop on the first build error, which is quite a lot of porting new board +CFLAGS += -Wfatal-errors + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) diff --git a/hw/bsp/stm32l0538disco/STM32L053C8Tx_FLASH.ld b/hw/bsp/stm32l0538disco/STM32L053C8Tx_FLASH.ld new file mode 100644 index 000000000..787418e09 --- /dev/null +++ b/hw/bsp/stm32l0538disco/STM32L053C8Tx_FLASH.ld @@ -0,0 +1,169 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32L053C8Tx Device with +** 64KByte FLASH, 8KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20002000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x200; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk new file mode 100644 index 000000000..f4088ba77 --- /dev/null +++ b/hw/bsp/stm32l0538disco/board.mk @@ -0,0 +1,52 @@ +CFLAGS += \ + -DHSE_VALUE=8000000 \ + -DSTM32L053xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m0plus \ + -mfloat-abi=soft \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32L0 + +# -DCFG_EXAMPLE_MSC_READONLY \ + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L0xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L0xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/$(BOARD)/STM32L053C8Tx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32l0xx.c \ + $(ST_HAL_DRIVER)/Src/stm32l0xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l053xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = stm32_fsdev + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# For flash-jlink target +JLINK_DEVICE = STM32L053R8 +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/stm32l0538disco/stm32l0538disco.c b/hw/bsp/stm32l0538disco/stm32l0538disco.c new file mode 100644 index 000000000..a3daaf0d2 --- /dev/null +++ b/hw/bsp/stm32l0538disco/stm32l0538disco.c @@ -0,0 +1,187 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32l0xx.h" +#include "stm32l0xx_hal_conf.h" + +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_5 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PIN_0 +#define BUTTON_STATE_ACTIVE 1 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow: + * HSI48 used as USB clock source + * - System Clock source = HSI + * - HSI Frequency(Hz) = 16000000 + * - SYSCLK(Hz) = 16000000 + * - HCLK(Hz) = 16000000 + * - AHB Prescaler = 1 + * - APB1 Prescaler = 1 + * - APB2 Prescaler = 1 + * - Flash Latency(WS) = 0 + * - Main regulator output voltage = Scale1 mode + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + static RCC_CRSInitTypeDef RCC_CRSInitStruct; + + /* Enable HSI Oscillator to be used as System clock source + Enable HSI48 Oscillator to be used as USB clock source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select HSI48 as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select HSI as system clock source and configure the HCLK, PCLK1 and PCLK2 + clock dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); + + /*Configure the clock recovery system (CRS)**********************************/ + + /*Enable CRS Clock*/ + __HAL_RCC_CRS_CLK_ENABLE(); + + /* Default Synchro Signal division factor (not divided) */ + RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + /* Set the SYNCSRC[1:0] bits according to CRS_Source value */ + RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + /* HSI48 is synchronized with USB SOF at 1KHz rate */ + RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000); + RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; + /* Set the TRIM[5:0] to the default value*/ + RCC_CRSInitStruct.HSI48CalibrationValue = 0x20; + /* Start automatic synchronization */ + HAL_RCCEx_CRSConfig (&RCC_CRSInitStruct); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + //__HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // USB + /* Configure DM DP Pins */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Enable USB FS Clock */ + __HAL_RCC_USB_CLK_ENABLE(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/stm32l0538disco/stm32l0xx_hal_conf.h b/hw/bsp/stm32l0538disco/stm32l0xx_hal_conf.h new file mode 100644 index 000000000..773b74e29 --- /dev/null +++ b/hw/bsp/stm32l0538disco/stm32l0xx_hal_conf.h @@ -0,0 +1,331 @@ +/** + ****************************************************************************** + * @file stm32l0xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * + * Copyright (c) 2016 STMicroelectronics International N.V. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L0xx_HAL_CONF_H +#define __STM32L0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +// #define HAL_ADC_MODULE_ENABLED +/* #define HAL_COMP_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_FIREWALL_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LCD_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +//#define HAL_RNG_MODULE_ENABLED +/* #define HAL_RTC_MODULE_ENABLED */ +//#define HAL_SPI_MODULE_ENABLED +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_TSC_MODULE_ENABLED */ +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +//#define HAL_PCD_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +/* #define HAL_PCD_MODULE_ENABLED */ + + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE ((uint32_t)2097152U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator for USB (HSI48) value. + */ +#if !defined (HSI48_VALUE) +#define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB in Hz. + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)37000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +/** + * @brief Time out for LSE start up value in ms. + */ +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define PREREAD_ENABLE 1U +#define BUFFER_CACHE_DISABLE 0U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32l0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32l0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32l0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32l0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32l0xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32l0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32l0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32l0xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32l0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FIREWALL_MODULE_ENABLED + #include "stm32l0xx_hal_firewall.h" +#endif /* HAL_FIREWALL_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32l0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32l0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32l0xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32l0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32l0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32l0xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32l0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32l0xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32l0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32l0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32l0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32l0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32l0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32l0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32l0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32l0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32l0xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32l0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32l0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L0xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 7b2f8cc73a758eefc2a308813d0081f08ddfeb2b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Sep 2019 13:49:33 +0700 Subject: [PATCH 68/94] added stm32 L0 support close #125 --- examples/device/board_test/Makefile | 3 - examples/make.mk | 1 + hw/bsp/stm32l0538disco/board.mk | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 38 ++++----- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 77 ++++++++++--------- 5 files changed, 63 insertions(+), 58 deletions(-) diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index e0c6d6ce2..5a455078e 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -5,9 +5,6 @@ INC += \ src \ $(TOP)/hw \ -# stop on the first build error, which is quite a lot of porting new board -CFLAGS += -Wfatal-errors - # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) diff --git a/examples/make.mk b/examples/make.mk index b0aa5659e..f35195fde 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -58,6 +58,7 @@ CFLAGS += \ -Wall \ -Werror \ -Werror-implicit-function-declaration \ + -Wfatal-errors \ -Wfloat-equal \ -Wundef \ -Wshadow \ diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk index f4088ba77..3b84159d1 100644 --- a/hw/bsp/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0538disco/board.mk @@ -6,9 +6,9 @@ CFLAGS += \ -mcpu=cortex-m0plus \ -mfloat-abi=soft \ -nostdlib -nostartfiles \ + -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32L0 -# -DCFG_EXAMPLE_MSC_READONLY \ ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L0xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L0xx diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index aec8ea0c7..d83098fd9 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -106,14 +106,17 @@ #include "tusb_option.h" +#define STM32F1_FSDEV ( \ + defined(STM32F102x6) || defined(STM32F102xB) || \ + defined(STM32F103x6) || defined(STM32F103xB) || \ + defined(STM32F103xE) || defined(STM32F103xG) \ +) + #if (TUSB_OPT_DEVICE_ENABLED) && ( \ - ((CFG_TUSB_MCU) == OPT_MCU_STM32F0) || \ - (((CFG_TUSB_MCU) == OPT_MCU_STM32F1) && ( \ - defined(stm32f102x6) || defined(stm32f102xb) || \ - defined(stm32f103x6) || defined(stm32f103xb) || \ - defined(stm32f103xe) || defined(stm32f103xg) \ - )) || \ - ((CFG_TUSB_MCU) == OPT_MCU_STM32F3) \ + (CFG_TUSB_MCU == OPT_MCU_STM32F0 ) || \ + (CFG_TUSB_MCU == OPT_MCU_STM32F1 && STM32F1_FSDEV ) || \ + (CFG_TUSB_MCU == OPT_MCU_STM32F3 ) || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) \ ) // In order to reduce the dependance on HAL, we undefine this. @@ -165,7 +168,7 @@ typedef struct static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; -static xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) +static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t epnum, uint32_t dir) { return &xfer_status[epnum][dir]; } @@ -252,9 +255,10 @@ void dcd_init (uint8_t rhport) void dcd_int_enable (uint8_t rhport) { (void)rhport; -#if defined(STM32F0) + +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_EnableIRQ(USB_IRQn); -#elif defined(STM32F3) +#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); @@ -265,14 +269,15 @@ void dcd_int_enable (uint8_t rhport) void dcd_int_disable(uint8_t rhport) { (void)rhport; -#if defined(STM32F0) + +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_DisableIRQ(USB_IRQn); -#elif defined(STM32F3) +#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn); NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); #else -#error Unknown arch in USB driver + #error Unknown arch in USB driver #endif // I'm not convinced that memory synchronization is completely necessary, but // it isn't a bad idea. @@ -305,7 +310,7 @@ void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - USB->CNTR |= (uint16_t)USB_CNTR_RESUME; + USB->CNTR |= (uint16_t) USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } @@ -448,14 +453,11 @@ static uint16_t dcd_ep_ctr_handler(void) { pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);// Await next SETUP } - } - } } else /* Decode and service non control endpoints interrupt */ { - /* process related endpoint register */ wEPVal = pcd_get_endpoint(USB, EPindex); if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT @@ -809,7 +811,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN // Interrupt handlers -#if (CFG_TUSB_MCU) == (OPT_MCU_STM32F0) +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 void USB_IRQHandler(void) { dcd_fs_irqHandler(); diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index ff25df048..30538541a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -41,51 +41,56 @@ #ifndef PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ #define PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ -#if defined(STM32F042x6) | \ - defined(STM32F070x6) | defined(STM32F070xB) | \ - defined(STM32F072xB) | \ +#if defined(STM32F042x6) || \ + defined(STM32F070x6) || defined(STM32F070xB) || \ + defined(STM32F072xB) || \ defined(STM32F078xx) -#include "stm32f0xx.h" -#define PMA_LENGTH (1024u) -// F0x2 models are crystal-less -// All have internal D+ pull-up -// 070RB: 2 x 16 bits/word memory LPM Support, BCD Support -// PMA dedicated to USB (no sharing with CAN) -#elif defined(STM32F102x6) | defined(STM32F102x6) | \ - defined(STM32F103x6) | defined(STM32F103xB) | \ - defined(STM32F103xE) | defined(STM32F103xB) -#include "stm32f1xx.h" -#define PMA_LENGTH (512u) -// NO internal Pull-ups -// *B, and *C: 2 x 16 bits/word -#error The F102/F103 driver is expected not to work, but it might? Try it? + #include "stm32f0xx.h" + #define PMA_LENGTH (1024u) + // F0x2 models are crystal-less + // All have internal D+ pull-up + // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support + // PMA dedicated to USB (no sharing with CAN) -#elif defined(STM32F302xB) | defined(STM32F302xC) | \ - defined(STM32F303xB) | defined(STM32F303xC) | \ +#elif STM32F1_FSDEV + #include "stm32f1xx.h" + #define PMA_LENGTH (512u) + // NO internal Pull-ups + // *B, and *C: 2 x 16 bits/word + #error The F102/F103 driver is expected not to work, but it might? Try it? + +#elif defined(STM32F302xB) || defined(STM32F302xC) || \ + defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) -#include "stm32f3xx.h" -#define PMA_LENGTH (512u) -// NO internal Pull-ups -// *B, and *C: 1 x 16 bits/word -// PMA dedicated to USB (no sharing with CAN) -#elif defined(STM32F302x6) | defined(STM32F302x8) | \ - defined(STM32F302xD) | defined(STM32F302xE) | \ - defined(STM32F303xD) | defined(STM32F303xE) | \ -#include "stm32f3xx.h" -#define PMA_LENGTH (1024u) -// NO internal Pull-ups -// *6, *8, *D, and *E: 2 x 16 bits/word LPM Support -// When CAN clock is enabled, USB can use first 768 bytes ONLY. + #include "stm32f3xx.h" + #define PMA_LENGTH (512u) + // NO internal Pull-ups + // *B, and *C: 1 x 16 bits/word + // PMA dedicated to USB (no sharing with CAN) + +#elif defined(STM32F302x6) || defined(STM32F302x8) || \ + defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) + #include "stm32f3xx.h" + #define PMA_LENGTH (1024u) + // NO internal Pull-ups + // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support + // When CAN clock is enabled, USB can use first 768 bytes ONLY. + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 + #include "stm32l0xx.h" + #define PMA_LENGTH (1024u) + #else -#error You are using an untested or unimplemented STM32 variant. Please update the driver. -// This includes L0x2, L0x3, L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 + #error You are using an untested or unimplemented STM32 variant. Please update the driver. + // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 #endif // For purposes of accessing the packet #if ((PMA_LENGTH) == 512u) -#define PMA_STRIDE (2u) + #define PMA_STRIDE (2u) #elif ((PMA_LENGTH) == 1024u) -#define PMA_STRIDE (1u) + #define PMA_STRIDE (1u) #endif // And for type-safety create a new macro for the volatile address of PMAADDR From 94c9cf0eff7973475e4f6d93cc96c2c86b541b08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Sep 2019 16:14:35 +0700 Subject: [PATCH 69/94] doc update --- README.md | 26 +++++++++---------- docs/boards.md | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 5 +--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0fbfaec37..a811e3b49 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,17 @@ TinyUSB is an open-source cross-platform USB Host/Device stack for embedded syst └── tools # Files used internally ``` +## Supported MCUs + +The stack supports the following MCUs + +- **Nordic:** nRF52840 +- **NXP:** LPC11Uxx, LPC13xx, LPC175x_6x, LPC177x_8x, LPC18xx, LPC40xx, LPC43xx, LPC51Uxx +- **MicroChip:** SAMD21, SAMD51 (device only) +- **ST:** STM32 series: L0, F0, F2, F3, F4, F7, H7 (device only) + +[Here is the list of supported Boards](docs/boards.md) that can be used with provided examples. + ## Device Stack Support multiple device configurations by dynamically changing usb descriptors. Low power functions such as suspend, resume and remote wakeup. Following device classes are supported: @@ -42,23 +53,12 @@ Support multiple device configurations by dynamically changing usb descriptors. ## OS Abtraction layer -Currently the following OS are supported with tinyusb out of the box with a simple change of **CFG_TUSB_OS** macro. +TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context. It also uses semphore/mutex to access shared resource such as CDC fifo. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box. -- **No OS** +- **No OS** : Disabling USB IRQ is used as way to provide mutex - **FreeRTOS** - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) -## Supported MCUs - -The stack supports the following MCUs - -- **Nordic:** nRF52840 -- **NXP:** LPC11Uxx, LPC13xx, LPC175x_6x, LPC177x_8x, LPC18xx, LPC40xx, LPC43xx, LPC51Uxx -- **MicroChip:** SAMD21, SAMD51 (device only) -- **ST:** STM32F0, STM32F2, STM32F3, STM32F4, STM32F7, STM32H7 (device only) - -[Here is the list of supported Boards](docs/boards.md) - ## Compiler & IDE The stack is developed with GCC compiler, and should be compilable with others. Folder `examples` provide Makefile and Segger Embedded Studio build support. [Here is instruction to build example](examples/readme.md). diff --git a/docs/boards.md b/docs/boards.md index fef682f48..b6b48a7f1 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -43,6 +43,7 @@ This code base already had supported for a handful of following boards - Adafruit Feather STM32F405 - [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1) +- [STM32 L035c8 Discovery](https://www.st.com/en/evaluation-tools/32l0538discovery.html) - [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) - [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) - [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index d83098fd9..9bd4d2362 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -30,10 +30,7 @@ /********************************************** * This driver has been tested with the following MCUs: - * - * - * STM32F070RB - * + * - F070, F072, L053 * * It also should work with minimal changes for any ST MCU with an "USB A"/"PCD"/"HCD" peripheral. This * covers: From a8a65d6ceae244971405a13bc493ee923861be1f Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 20 Sep 2019 08:46:17 -0400 Subject: [PATCH 70/94] Use cached HID descriptor. --- src/class/hid/hid_device.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7dabdbc17..fee44e30c 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -205,32 +205,15 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) { - // FIXME: Should check which is the active configuration, but no callback in usbd currently exists to do that TU_VERIFY(p_hid->hid_descriptor != NULL); - tusb_desc_configuration_t const* desc_cfg = - (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(0); - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; - - while( p_desc < desc_end ) - { - tusb_hid_descriptor_hid_t *p_desc_hid =(tusb_hid_descriptor_hid_t*)p_desc; - if(p_desc_hid->bDescriptorType == HID_DESC_TYPE_HID) { - tud_control_xfer(rhport, p_request, (void*) p_desc_hid, p_desc_hid->bLength); - break; - } - p_desc += p_desc_hid->bLength; // next desc - } - if(p_desc >= desc_end) - { - return false; - } + TU_VERIFY(tud_control_xfer(rhport, p_request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); } else if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { uint8_t const * desc_report = tud_hid_descriptor_report_cb(); tud_control_xfer(rhport, p_request, (void*) desc_report, p_hid->report_desc_len); - }else + } + else { return false; // stall unsupported request } From f241ff389f9494836cdc45e621726c0b69b8daed Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 20 Sep 2019 08:56:46 -0400 Subject: [PATCH 71/94] Also need to just return false in the case that it isn't an interface control event. We shouldn't assert. This normally isn't an error, either, so I don't want to use TU_VERIFY. --- src/class/hid/hid_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index fee44e30c..b57d6219f 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -193,6 +193,10 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t // return false to stall control endpoint (e.g unsupported request) bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { + if (p_request->bmRequestType_bit.recipient != TUSB_REQ_RCPT_INTERFACE) + { + return false; + } hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); TU_ASSERT(p_hid); From c975976a7565a6186f503b0ce106b6ba84805091 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Sep 2019 23:05:08 +0700 Subject: [PATCH 72/94] update doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a811e3b49..0a9cd770c 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Support multiple device configurations by dynamically changing usb descriptors. ## OS Abtraction layer -TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context. It also uses semphore/mutex to access shared resource such as CDC fifo. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box. +TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context. It also uses semphore/mutex to access shared resource such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box. - **No OS** : Disabling USB IRQ is used as way to provide mutex - **FreeRTOS** From 2281a514846402af68aa4c97fcd206611c0969a1 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 20 Sep 2019 12:27:41 -0400 Subject: [PATCH 73/94] Revert "Also need to just return false in the case that it isn't an interface control event. We shouldn't assert. This normally isn't an" This reverts commit f241ff389f9494836cdc45e621726c0b69b8daed. --- src/class/hid/hid_device.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b57d6219f..fee44e30c 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -193,10 +193,6 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t // return false to stall control endpoint (e.g unsupported request) bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { - if (p_request->bmRequestType_bit.recipient != TUSB_REQ_RCPT_INTERFACE) - { - return false; - } hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); TU_ASSERT(p_hid); From 8a688cd8d0fed2325aaacdfbb5159a04dfe03ac1 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 20 Sep 2019 12:58:26 -0400 Subject: [PATCH 74/94] Revert "Revert "Also need to just return false in the case that it isn't an interface control event. We shouldn't assert. This normally isn't an"" This reverts commit 2281a514846402af68aa4c97fcd206611c0969a1. --- src/class/hid/hid_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index fee44e30c..b57d6219f 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -193,6 +193,10 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t // return false to stall control endpoint (e.g unsupported request) bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { + if (p_request->bmRequestType_bit.recipient != TUSB_REQ_RCPT_INTERFACE) + { + return false; + } hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); TU_ASSERT(p_hid); From ce9f133d258fe173211063b06c87c7c5d1384986 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:00:04 -0400 Subject: [PATCH 75/94] FSDEV: go to NAK when unstalling; on reset, set EP0 to NAK, prioritize reset interrupt, fix small typos. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9bd4d2362..00f5b1239 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -331,7 +331,9 @@ static const tusb_desc_endpoint_t ep0IN_desc = .bEndpointAddress = 0x80 }; +#if defined(__GNUC__) && (__GNUC__ >= 7) #pragma GCC diagnostic pop +#endif static void dcd_handle_bus_reset(void) { @@ -349,7 +351,6 @@ static void dcd_handle_bus_reset(void) dcd_edpt_open (0, &ep0IN_desc); newDADDR = 0u; USB->DADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. - pcd_set_ep_rx_status(USB, 0, USB_EP_RX_VALID); // And start accepting SETUP on EP0 } // FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed. @@ -518,8 +519,22 @@ static uint16_t dcd_ep_ctr_handler(void) static void dcd_fs_irqHandler(void) { - uint16_t int_status = USB->ISTR; - // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | USB_ISTR_ESOF | USB_ISTR_L1REQ ) + uint32_t int_status = USB->ISTR; + //const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP + // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; + // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) + + // The ST driver loops here on the CTR bit, but that loop has been moved into the + // dcd_ep_ctr_handler(), so less need to loop here. The other interrupts shouldn't + // be triggered repeatedly. + + if(int_status & USB_ISTR_RESET) { + // USBRST is start of reset. + reg16_clear_bits(&USB->ISTR, USB_ISTR_RESET); + dcd_handle_bus_reset(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + return; // Don't do the rest of the things here; perhaps they've been cleared? + } if (int_status & USB_ISTR_CTR) { @@ -528,12 +543,7 @@ static void dcd_fs_irqHandler(void) { dcd_ep_ctr_handler(); reg16_clear_bits(&USB->ISTR, USB_ISTR_CTR); } - if(int_status & USB_ISTR_RESET) { - // USBRST is start of reset. - reg16_clear_bits(&USB->ISTR, USB_ISTR_RESET); - dcd_handle_bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); - } + if (int_status & USB_ISTR_WKUP) { reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); @@ -544,6 +554,9 @@ static void dcd_fs_irqHandler(void) { if (int_status & USB_ISTR_SUSP) { + /* Suspend is asserted for both suspend and unplug events. without Vbus monitoring, + * these events cannot be differentiated, so we only trigger suspend. */ + /* Force low-power mode in the macrocell */ USB->CNTR |= USB_CNTR_FSUSP; USB->CNTR |= USB_CNTR_LPMODE; @@ -696,25 +709,19 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void)rhport; - if (ep_addr == 0) { // CTRL EP0 (OUT for setup) - pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_STALL); + if (ep_addr & 0x80) + { // IN + pcd_set_ep_tx_status(USB, ep_addr & 0x7F, USB_EP_TX_STALL); } - - if (ep_addr & 0x80) { // IN - ep_addr &= 0x7F; - pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_STALL); - } else { // OUT - pcd_set_ep_rx_status(USB,ep_addr, USB_EP_RX_STALL); + else + { // OUT + pcd_set_ep_rx_status(USB, ep_addr, USB_EP_RX_STALL); } } void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void)rhport; - if (ep_addr == 0) - { - pcd_set_ep_tx_status(USB,ep_addr, USB_EP_TX_NAK); - } if (ep_addr & 0x80) { // IN @@ -730,7 +737,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /* Reset to DATA0 if clearing stall condition. */ pcd_clear_rx_dtog(USB,ep_addr); - pcd_set_ep_rx_status(USB,ep_addr, USB_EP_RX_VALID); + pcd_set_ep_rx_status(USB,ep_addr, USB_EP_RX_NAK); } } From b6590490a8e2ad3debac4508f65af001dc1753af Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:00:36 -0400 Subject: [PATCH 76/94] USB Control: Pointer arithmetic on void* is forbiden --- src/device/usbd_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 4ec432185..eecc95edb 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -122,7 +122,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result } _control_state.total_transferred += xferred_bytes; - _control_state.buffer += xferred_bytes; + _control_state.buffer = ((uint8_t*)_control_state.buffer) + xferred_bytes; if ( _control_state.total_len == _control_state.total_transferred || xferred_bytes < CFG_TUD_ENDOINT0_SIZE ) { From aebecf169abff62b022da2c0e70f7416d62c91ef Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:02:06 -0400 Subject: [PATCH 77/94] Reorder handling of EP control requests, --- src/device/usbd.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 0366d1ece..146da5420 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -499,10 +499,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const drv_id = _usbd_dev.ep2drv[ep_num][ep_dir]; TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); - // Some classes such as TMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request - // We will forward all request targeted endpoint to its class driver - // - For non-standard request: driver can ACK or Stall the request by return true/false - // - For standard request: usbd decide the ACK stage regardless of driver return value bool ret = false; if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) @@ -511,12 +507,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete); } - // Invoke class driver first if available - if ( usbd_class_drivers[drv_id].control_request ) - { - ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); - } - // Then handle if it is standard request if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) { @@ -552,7 +542,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const default: TU_BREAKPOINT(); return false; } } + // Some classes such as TMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request + // We will forward all request targeted endpoint to its class driver + // For class-type requests: must (call tud_control_status(); return true) or (return false) + // For std-type requests: non-std requests codes are already discarded. + // must not call tud_control_status(), and return value will have no effect + // Invoke class driver last, so that EP is already stalled + if ( usbd_class_drivers[drv_id].control_request ) + { + ret = ret | usbd_class_drivers[drv_id].control_request(rhport, p_request); + } return ret; } break; From 55abb3d71763037ffcc4a55c5ecd72c1ef8e47b5 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:02:52 -0400 Subject: [PATCH 78/94] Calling EP open with bad parameters should be considered a bug. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 146da5420..67c5bdebc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -804,7 +804,7 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count { tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_VERIFY(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); TU_ASSERT(dcd_edpt_open(rhport, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) From be28a05409f80f9fe983306b1fc60e1ea30da0bc Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:03:36 -0400 Subject: [PATCH 79/94] Make type casting explicit --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 67c5bdebc..b7a44d24e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -633,7 +633,7 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - len += tu_desc_len(p_desc); + len = (uint16_t)(len + tu_desc_len(p_desc)); p_desc = tu_desc_next(p_desc); } } From a187f0268c9c42bfbfb22338692dfffed3f9bac5 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:04:49 -0400 Subject: [PATCH 80/94] When unstalling, EP must be marked as not busy. Also, mark EP as busy when stalling as xfer requests should fail. --- src/device/usbd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device/usbd.c b/src/device/usbd.c index b7a44d24e..e0148dc97 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -870,6 +870,7 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) dcd_edpt_stall(rhport, ep_addr); _usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_stall_map[dir], epnum); + _usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_busy_map[dir], epnum); } void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) @@ -878,6 +879,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[dir], epnum); _usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_stall_map[dir], epnum); } From 37b52e354fe4089be04e167e2a5483ae31383274 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 12:17:17 -0400 Subject: [PATCH 81/94] Correct wording of comment on handling EP requests. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index e0148dc97..6401a2d9e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -545,9 +545,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Some classes such as TMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will forward all request targeted endpoint to its class driver // For class-type requests: must (call tud_control_status(); return true) or (return false) - // For std-type requests: non-std requests codes are already discarded. + // For std-type requests: non-std request codes are already discarded. // must not call tud_control_status(), and return value will have no effect - // Invoke class driver last, so that EP is already stalled + // class driver is invoked last, so that EP already has EP stall cleared (in event of clear feature EP halt) if ( usbd_class_drivers[drv_id].control_request ) { From fbb8520acdb7137ef695c03b05e1a3d6c4d33ba2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 14:34:29 -0400 Subject: [PATCH 82/94] logical or. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 6401a2d9e..fb28ff0e6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -551,7 +551,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const if ( usbd_class_drivers[drv_id].control_request ) { - ret = ret | usbd_class_drivers[drv_id].control_request(rhport, p_request); + ret = ret || usbd_class_drivers[drv_id].control_request(rhport, p_request); } return ret; } From 9498adef71fe2816d336061b38ed801dc980a8bb Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 19:29:57 -0400 Subject: [PATCH 83/94] Changing the bitwise to a logical OR created a huge hard to find bug. It shortcutted the call to the class function, so, lets use shortcutting anyway? --- src/device/usbd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index fb28ff0e6..50964bdee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -549,9 +549,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // must not call tud_control_status(), and return value will have no effect // class driver is invoked last, so that EP already has EP stall cleared (in event of clear feature EP halt) - if ( usbd_class_drivers[drv_id].control_request ) + if ( usbd_class_drivers[drv_id].control_request && + usbd_class_drivers[drv_id].control_request(rhport, p_request)) { - ret = ret || usbd_class_drivers[drv_id].control_request(rhport, p_request); + ret = true; } return ret; } From fa5b5e4561869e26832d817b4a709ba31e666143 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 21:46:46 -0400 Subject: [PATCH 84/94] Lots of updates (especially error handling) --- examples/device/usbtmc/src/usb_descriptors.c | 4 +- examples/device/usbtmc/src/usbtmc_app.c | 51 +++- examples/device/usbtmc/visaQuery.py | 70 +++++- src/class/usbtmc/usbtmc_device.c | 242 ++++++++++--------- src/class/usbtmc/usbtmc_device.h | 2 +- 5 files changed, 234 insertions(+), 135 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 45e1001ea..1175ebb99 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -107,13 +107,13 @@ uint8_t const * tud_hid_descriptor_report_cb(void) # define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \ - TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83, /* packet size = */USBTMCD_MAX_PACKET_SIZE) + TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */USBTMCD_MAX_PACKET_SIZE) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) // Interrupt endpoint should be 2 bytes on a FS USB link # define TUD_USBTMC_DESC(_itfnum) \ TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) + TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x82, /* epMaxSize = */ 2, /* bInterval = */16u ) # define USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN) #else diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index f8c350f68..495746e07 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -84,6 +84,7 @@ static volatile uint32_t idnQuery; static uint32_t resp_delay = 125u; // Adjustable delay, to allow for better testing static size_t buffer_len; +static size_t buffer_tx_ix; // for transmitting using multiple transfers static uint8_t buffer[225]; // A few packets long should be enough. @@ -108,6 +109,11 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_d (void)rhport; (void)msgHeader; buffer_len = 0; + if(msgHeader->TransferSize > sizeof(buffer)) + { + + return false; + } return true; } @@ -122,6 +128,10 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra memcpy(&(buffer[buffer_len]), data, len); buffer_len += len; } + else + { + return false; // buffer overflow! + } queryState = transfer_complete; idnQuery = 0; @@ -145,8 +155,13 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) { (void)rhport; - - status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV + if((buffer_tx_ix == buffer_len) || idnQuery) // done + { + status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV + queryState = 0; + bulkInStarted = 0; + buffer_tx_ix = 0; + } return true; } @@ -161,15 +176,25 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; + #ifdef xDEBUG uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); #endif - TU_ASSERT(bulkInStarted == 0); - bulkInStarted = 1; - - // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message - // that expects a response, the device must NAK the request + if(queryState == 0 || (buffer_tx_ix == 0)) + { + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; + // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message + // that expects a response, the device must NAK the request (*not stall*) + } + else + { + size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); + usbtmcd_transmit_dev_msg_data(rhport, &buffer[buffer_tx_ix], txlen, + (buffer_tx_ix+txlen) == buffer_len, false); + buffer_tx_ix += txlen; + } // Always return true indicating not to stall the EP. return true; } @@ -197,17 +222,17 @@ void usbtmc_app_task_iter(void) { } break; case 4: // time to transmit; - if(bulkInStarted) { - queryState = 0; - bulkInStarted = 0; - + if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + queryState = 0; + bulkInStarted = 0; } else { - usbtmcd_transmit_dev_msg_data(rhport, buffer, tu_min32(buffer_len,msgReqLen),false); + buffer_tx_ix = tu_min32(buffer_len,msgReqLen); + usbtmcd_transmit_dev_msg_data(rhport, buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 368b66053..4d4b50c4b 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -6,7 +6,8 @@ import sys def test_idn(): idn = inst.query("*idn?"); - assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" + assert (idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n") + assert (inst.is_4882_compliant) def test_echo(m,n): longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 @@ -34,6 +35,8 @@ def test_trig(): def test_mav(): + inst.write("delay 50") + inst.read_stb() # clear STB assert (inst.read_stb() == 0) inst.write("123") time.sleep(0.3) @@ -60,8 +63,6 @@ def test_srq(): rsp = inst.read() assert(rsp == "123\r\n") - - def test_read_timeout(): inst.timeout = 500 @@ -78,7 +79,53 @@ def test_read_timeout(): t = time.time() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) - print(f"Delay was {t}") + print(f"Delay was {t:0.3}") + # Response is still in queue, so send a clear (to be more helpful to the next test) + inst.clear() + time.sleep(0.3) + assert(0 == (inst.read_stb() & 0x10)), "MAV not reset after clear" + +def test_abort_in(): + inst.timeout = 200 + # First read with no MAV + inst.read_stb() + assert (inst.read_stb() == 0) + inst.write("delay 500") + inst.write("xxx") + t0 = time.time() + try: + rsp = inst.read() + assert(false), "Read should have resulted in timeout" + except visa.VisaIOError: + print("Got expected exception") + t = time.time() - t0 + assert ((t*1000.0) > (inst.timeout - 300)) + assert ((t*1000.0) < (inst.timeout + 300)) + print(f"Delay was {t:0.3}") + # Response is still in queue, so send a clear (to be more helpful to the next test) + inst.timeout = 800 + y = inst.read() + assert(y == "xxx\r\n") + +def test_indicate(): + # perform indicator pulse + usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM) + retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=64, request_value=0x0000, index=usb_iface, length=0x0001) + assert((retv[1] == visa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}" + + +def test_multi_read(): + old_chunk_size = inst.chunk_size + longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 10 + timeout = 10 + x = longstr[0:174] + inst.chunk_size = 50 # Seems chunk size only applies to read but not write + inst.write(x) + # I'm not sure how to request just the remaining bit using a max count... so just read it all. + y = inst.read() + assert (x + "\r\n" == y) + #inst.chunk_size = old_chunk_size + rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") reslist = rm.list_resources("USB?::?*::INSTR") @@ -89,12 +136,20 @@ if (len(reslist) == 0): inst = rm.open_resource(reslist[0]); inst.timeout = 3000 + inst.clear() print("+ IDN") test_idn() -inst.timeout = 3000 +print("+test abort in") +test_abort_in() + + +inst.timeout = 2000 + +print("+ multi read") +test_multi_read() print("+ echo delay=0") @@ -110,7 +165,7 @@ inst.write("delay 150") test_echo(53,76) test_echo(165,170) -print("+ Read timeout (no MAV") +print("+ Read timeout (no MAV)") test_read_timeout() print("+ MAV") @@ -119,6 +174,9 @@ test_mav() print("+ SRQ") test_srq() +print("+ indicate") +test_indicate() + print("+ TRIG") test_trig() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index fcd3376f3..2c6c88cf5 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -31,25 +31,31 @@ * This file is part of the TinyUSB stack. */ -// Synchronization is needed in some spots. -// These functions should NOT be called from interrupts. - -/* The library is designed that its functions can be called by any user task, with need for - * additional locking. In the case of "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. In the case - * of an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. +/* + * This library is not fully reentrant, though it is reentrant from the view + * of either the application layer or the USB stack. Due to its locking, + * it is not safe to call its functions from interrupts. * - * This module's application-facing functions are not reentrant. The application must - * only call them from a single thread (or implement its own locking). + * The one exception is that its functions may not be called from the application + * until the USB stack is initialized. This should not be a problem since the + * device shouldn't be sending messages until it receives a request from the + * host. */ +/* + * In the case of single-CPU "no OS", this task is never preempted other than by + * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", + * the mutex structure's main effect is to disable the USB interrupts. + * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock + * and does not call outside of this class with a lock held, so deadlocks won't happen. + */ + //Limitations: // "vendor-specific" commands are not handled. // Dealing with "termchar" must be handled by the application layer, // though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're no permitted +// talkOnly and listenOnly are NOT supported. They're not permitted // in USB488, anyway. /* Supported: @@ -64,10 +70,7 @@ // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. -// Cannot handle clear. // Clear message available status byte at the correct time? (488 4.3.1.3) -// Abort bulk in/out -// No CLEAR_FEATURE/HALT no EP (yet) #include "tusb_option.h" @@ -79,21 +82,24 @@ #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" +#include "osal/osal.h" + +// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy +#include "device/usbd_pvt.h" #ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; #endif - -// FIXME: I shouldn't need to include _pvt headers. -#include "device/usbd_pvt.h" - -static uint8_t termChar; -static uint8_t termCharRequested = false; +/* + * The state machine does not allow simultaneous reading and writing. This is + * consistent with USBTMC. + */ typedef enum { + STATE_CLOSED, STATE_IDLE, STATE_RCV, STATE_TX_REQUESTED, @@ -126,16 +132,12 @@ typedef struct uint8_t lastBulkOutTag; // used for aborts (mostly) uint8_t lastBulkInTag; // used for aborts (mostly) - uint8_t const * devInBuffer; + uint8_t const * devInBuffer; // pointer to application-layer used for transmissions } usbtmc_interface_state_t; static usbtmc_interface_state_t usbtmc_state = { - .state = STATE_IDLE, .itf_id = 0xFF, - .ep_bulk_in = 0, - .ep_bulk_out = 0, - .ep_int_in = 0 }; // We need all headers to fit in a single packet in this implementation. @@ -147,6 +149,9 @@ TU_VERIFY_STATIC( static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); +static uint8_t termChar; +static uint8_t termCharRequested = false; + osal_mutex_def_t usbtmcLockBuffer; static osal_mutex_t usbtmcLock; @@ -155,6 +160,23 @@ static osal_mutex_t usbtmcLock; #define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) #define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) +bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) +{ + bool ret = true; + criticalEnter(); + usbtmcd_state_enum oldState = usbtmc_state.state; + if (oldState == expectedState) + { + usbtmc_state.state = newState; + } + else + { + ret = false; + } + criticalLeave(); + return ret; +} + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. @@ -165,6 +187,7 @@ static osal_mutex_t usbtmcLock; bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, const void * data, size_t len, + bool endOfMessage, bool usingTermChar) { const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); @@ -172,68 +195,53 @@ bool usbtmcd_transmit_dev_msg_data( #ifndef NDEBUG TU_ASSERT(len > 0u); TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); + TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); if(usingTermChar) { TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t*)data)[len-1] == termChar); + TU_ASSERT(((uint8_t*)data)[len-1u] == termChar); } #endif TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - memset(hdr, 0x00, sizeof(*hdr)); + tu_varclr(hdr); hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; hdr->header.bTag = usbtmc_state.lastBulkInTag; hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = 1u; + hdr->bmTransferAttributes.EOM = endOfMessage; hdr->bmTransferAttributes.UsingTermChar = usingTermChar; // Copy in the header - size_t packetLen = sizeof(*hdr); + const size_t headerLen = sizeof(*hdr); + const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? + len : (txBufLen - headerLen); + const size_t packetLen = headerLen + dataLen; - // If it fits in a single trasnmission: - if((packetLen + hdr->TransferSize) <= txBufLen) - { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); - packetLen = (uint16_t)(packetLen + hdr->TransferSize); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.transfer_size_sent = len; - usbtmc_state.devInBuffer = NULL; - } - else /* partial packet */ - { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); - usbtmc_state.devInBuffer = (uint8_t*)data + (txBufLen - packetLen); - usbtmc_state.transfer_size_remaining = len - (txBufLen - packetLen); - usbtmc_state.transfer_size_sent = txBufLen - packetLen; - packetLen = txBufLen; - } + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); + usbtmc_state.transfer_size_remaining = len - dataLen; + usbtmc_state.transfer_size_sent = dataLen; + usbtmc_state.devInBuffer = (uint8_t*)data + (dataLen); - - criticalEnter(); - { - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - // We used packetlen as a max, not the buffer size, so this is OK here, no need for modulus - usbtmc_state.state = (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED; - } - criticalLeave(); - - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); + bool stateChanged = + atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); + TU_VERIFY(stateChanged); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } void usbtmcd_init_cb(void) { #ifndef NDEBUG -# if CFG_USBTMC_CFG_ENABLE_488 - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); - // Per USB488 spec: table 8 - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); -# endif +# if CFG_USBTMC_CFG_ENABLE_488 + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); + // Per USB488 spec: table 8 + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); +# endif if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); #endif @@ -244,20 +252,16 @@ void usbtmcd_init_cb(void) bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; + TU_ASSERT(usbtmc_state.state == STATE_CLOSED); uint8_t const * p_desc; uint8_t found_endpoints = 0; - - usbtmcd_reset_cb(rhport); - - // Perhaps there are other application specific class drivers, so don't assert here. - if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) - return false; - if( itf_desc->bInterfaceSubClass != TUD_USBTMC_APP_SUBCLASS) - return false; - +#ifndef NDEBUG + TU_ASSERT(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); + TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); // Only 2 or 3 endpoints are allowed for USBTMC. TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); +#endif // Interface (*p_length) = 0u; @@ -318,28 +322,27 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } #endif #endif + usbtmc_state.state = STATE_IDLE; TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; } void usbtmcd_reset_cb(uint8_t rhport) { - // FIXME: Do endpoints need to be closed here? - usbtmc_state.state = STATE_IDLE; - usbtmc_state.itf_id = 0xFF; - usbtmc_state.ep_bulk_in = 0; - usbtmc_state.ep_bulk_out = 0; - usbtmc_state.ep_int_in = 0; - usbtmc_state.lastBulkInTag = 0; - usbtmc_state.lastBulkOutTag = 0; - (void)rhport; + + criticalEnter(); + tu_varclr(&usbtmc_state); + usbtmc_state.itf_id = 0xFFu; + criticalLeave(); } static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - TU_VERIFY(usbtmc_state.state == STATE_IDLE); + bool stateChanged = atomicChangeState(STATE_IDLE, STATE_RCV); + TU_VERIFY(stateChanged); + // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; @@ -352,6 +355,9 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) { (void)rhport; + + TU_VERIFY(usbtmc_state.state == STATE_RCV); + bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); // Packet is to be considered complete when we get enough data or at a short packet. @@ -360,18 +366,14 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd); + TU_VERIFY(tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)); + // TODO: Go to an error state upon failure other than just stalling the EP? usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; - if(atEnd) - { - usbtmc_state.state = STATE_IDLE; - } - else - { - usbtmc_state.state = STATE_RCV; - } + bool stateChanged = atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV); + TU_VERIFY(stateChanged); + return true; } @@ -379,16 +381,11 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - - criticalEnter(); - { - TU_VERIFY(usbtmc_state.state == STATE_IDLE); - usbtmc_state.state = STATE_TX_REQUESTED; - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - } - criticalLeave(); + bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); + TU_VERIFY(stateChanged); + usbtmc_state.lastBulkInTag = msg->header.bTag; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + usbtmc_state.transfer_size_sent = 0u; termCharRequested = msg->bmTransferAttributes.TermCharEnabled; termChar = msg->TermChar; @@ -403,7 +400,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { TU_VERIFY(result == XFER_RESULT_SUCCESS); - + //uart_tx_str_sync("TMC XFER CB\r\n"); if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ } @@ -457,7 +454,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_OUT: TU_VERIFY(false); - return false; // Should be stalled by now... + return false; // Should be stalled by now, shouldn't have received a packet. case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: @@ -534,19 +531,26 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - if((request->wIndex) == usbtmc_state.ep_bulk_out) + uint32_t ep_addr = (request->wIndex); + + if(ep_addr == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature_cb(rhport); + // And start a new OUT xfer request now that things are clear + TU_ASSERT( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); } - else if ((request->wIndex) == usbtmc_state.ep_bulk_in) + else if (ep_addr == usbtmc_state.ep_bulk_in) { usmtmcd_app_bulkIn_clearFeature_cb(rhport); } - return false; // We want USBD core to handle sending the status response, and clear the stall condition + else + { + return false; + } + return true; } - // We only handle class requests, IN direction. - // (for now) + // Otherwise, we only handle class requests. if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) { return false; @@ -571,7 +575,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { rsp.USBTMC_status = USBTMC_STATUS_FAILED; } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) + else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) { rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; } @@ -579,7 +583,9 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; // Check if we've queued a short packet + criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; + criticalLeave(); TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } @@ -610,13 +616,15 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); // wValue is the requested bTag to abort if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) + usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_remaining = 0u; // Check if we've queued a short packet + criticalEnter(); usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + criticalLeave(); if(usbtmc_state.transfer_size_sent == 0) { // Send short packet, nothing is in the buffer yet @@ -652,6 +660,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); + criticalEnter(); switch(usbtmc_state.state) { case STATE_ABORTING_BULK_IN_ABORTED: @@ -665,6 +674,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r default: break; } + criticalLeave(); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; @@ -678,7 +688,9 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); usbtmc_state.transfer_size_remaining = 0; + criticalEnter(); usbtmc_state.state = STATE_CLEARING; + criticalLeave(); TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; @@ -702,7 +714,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) + { + criticalEnter(); usbtmc_state.state = STATE_IDLE; + criticalLeave(); + } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } @@ -754,7 +770,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { @@ -785,7 +801,7 @@ bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * { (void)rhport; //------------- Class Specific Request -------------// - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); return true; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 5c6ee2a8d..d33d73905 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -91,7 +91,7 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_gener bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, const void * data, size_t len, - bool usingTermChar); + bool endOfMessage, bool usingTermChar); /* "callbacks" from USB device core */ From 108f756e22c07d066f9d3079100872df71416991 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 21 Sep 2019 22:40:01 -0400 Subject: [PATCH 85/94] dcd_synopsys: Fix off-by-one error in FIFO allocation. --- src/portable/st/synopsys/dcd_synopsys.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index f15b92edc..1a7f86219 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -268,10 +268,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); - + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; @@ -305,18 +305,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | \ - (epnum - 1) << USB_OTG_DIEPCTL_TXFNUM_Pos | \ + epnum << USB_OTG_DIEPCTL_TXFNUM_Pos | \ desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos | \ (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | \ desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos; dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); - // Both TXFD and TXSA are in unit of 32-bit words + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". uint16_t const allocated_size = (USB_OTG_FS->GRXFSIZ & 0x0000ffff) + 16; uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); + + // DIEPTXF starts at FIFO #1. USB_OTG_FS->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | fifo_offset; } From e61f2b7393382387634ab38e14ac5fab70e3c122 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 22 Sep 2019 09:55:28 -0400 Subject: [PATCH 86/94] Retool stalling EP on xfer errors. --- src/class/usbtmc/usbtmc_device.c | 43 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 2c6c88cf5..e3d2c316e 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -340,8 +340,9 @@ void usbtmcd_reset_cb(uint8_t rhport) static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_RCV); - TU_VERIFY(stateChanged); + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); + usbtmc_state.transfer_size_sent = 0u; // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; @@ -349,30 +350,36 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + usbtmc_state.lastBulkOutTag = msg->header.bTag; return true; } static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) { (void)rhport; - - TU_VERIFY(usbtmc_state.state == STATE_RCV); + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(usbtmc_state.state == STATE_RCV,true); bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); // Packet is to be considered complete when we get enough data or at a short packet. bool atEnd = false; if(len >= usbtmc_state.transfer_size_remaining || shortPacket) + { atEnd = true; - if(len > usbtmc_state.transfer_size_remaining) - len = usbtmc_state.transfer_size_remaining; - TU_VERIFY(tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)); - // TODO: Go to an error state upon failure other than just stalling the EP? + } + + len = tu_min32(len, usbtmc_state.transfer_size_remaining); + + if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) + { + // TODO: Go to an error state upon failure other than just stalling the EP? + return false; + } usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; - bool stateChanged = atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV); - TU_VERIFY(stateChanged); + TU_VERIFY(atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV)); return true; } @@ -420,9 +427,11 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: - usbtmc_state.transfer_size_sent = 0u; - TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; + if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } break; case USBTMC_MSGID_DEV_DEP_MSG_IN: @@ -440,7 +449,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: default: - + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(false); return false; } @@ -448,7 +457,11 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return true; case STATE_RCV: - TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); + if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; From 11de9f0ffd4666891347e97729ea252b9ff305f5 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 23 Sep 2019 23:11:47 -0400 Subject: [PATCH 87/94] examples: Allow user to override EP0 size. --- examples/device/cdc_msc/src/tusb_config.h | 3 ++- examples/device/cdc_msc_hid_freertos/src/tusb_config.h | 4 +++- examples/device/hid_composite/src/tusb_config.h | 4 +++- examples/device/hid_generic_inout/src/tusb_config.h | 4 +++- examples/device/midi_test/src/tusb_config.h | 4 +++- examples/device/msc_dual_lun/src/tusb_config.h | 4 +++- examples/device/webusb_serial/src/tusb_config.h | 4 +++- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index ff7fafd8f..e307870ed 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -68,8 +68,9 @@ //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- - +#ifndef CFG_TUD_ENDOINT0_SIZE #define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 1 diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h index bb31eac06..7869e24cc 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- +#ifndef CFG_TUD_ENDOINT0_SIZE #define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 1 diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 57fcbd595..13ecfa415 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDOINT0_SIZE +#define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_HID 1 diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index c55529fcb..c82588c2f 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDOINT0_SIZE +#define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 0 diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index d588b4df9..4a84812c5 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDOINT0_SIZE +#define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 0 diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 2e40b9e86..073e2379f 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDOINT0_SIZE +#define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 0 diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index ffedb997d..b2f09cac0 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -69,7 +69,9 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDOINT0_SIZE +#define CFG_TUD_ENDOINT0_SIZE 64 +#endif //------------- CLASS -------------// #define CFG_TUD_CDC 1 From 10105557dc5d9bd315f70243f947386728c7d86c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:11:45 -0400 Subject: [PATCH 88/94] Let application control interface latency... --- examples/device/usbtmc/src/usbtmc_app.c | 16 ++++++- src/class/usbtmc/usbtmc_device.c | 62 ++++++++++++++++++------- src/class/usbtmc/usbtmc_device.h | 15 +++++- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 495746e07..2982675b1 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,6 +96,13 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; +void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id) +{ + (void)interface_id; + usbtmcd_start_bus_read(rhport); +} + + bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; @@ -149,6 +156,7 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra d=0; resp_delay = (uint32_t)d; } + usbtmcd_start_bus_read(rhport); return true; } @@ -162,6 +170,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) bulkInStarted = 0; buffer_tx_ix = 0; } + usbtmcd_start_bus_read(rhport); return true; } @@ -259,6 +268,8 @@ bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t queryState = 0; bulkInStarted = false; status = 0; + buffer_tx_ix = 0u; + buffer_len = 0u; rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; rsp->bmClear.BulkInFifoBytes = 0u; return true; @@ -274,6 +285,7 @@ bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bu { (void)rhport; (void)rsp; + usbtmcd_start_bus_read(rhport); return true; } @@ -288,6 +300,7 @@ bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_b { (void)rhport; (void)rsp; + usbtmcd_start_bus_read(rhport); return true; } @@ -298,6 +311,7 @@ void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) { (void)rhport; + usbtmcd_start_bus_read(rhport); } // Return status byte, but put the transfer result status code in the rspResult argument. @@ -313,7 +327,7 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)rhport; (void)msg; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index e3d2c316e..401b4acc4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -99,9 +99,10 @@ static char logMsg[150]; typedef enum { - STATE_CLOSED, - STATE_IDLE, - STATE_RCV, + STATE_CLOSED, // Endpoints have not yet been opened since USB reset + STATE_NAK, // Bulk-out endpoint is in NAK state. + STATE_IDLE, // Bulk-out endpoint is waiting for CMD. + STATE_RCV, // Bulk-out is receiving DEV_DEP message STATE_TX_REQUESTED, STATE_TX_INITIATED, STATE_TX_SHORTED, @@ -243,7 +244,7 @@ void usbtmcd_init_cb(void) TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); + TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); @@ -322,11 +323,37 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } #endif #endif - usbtmc_state.state = STATE_IDLE; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + atomicChangeState(STATE_CLOSED, STATE_NAK); + tud_usbtmc_app_open_cb(rhport, itf_desc->iInterface); return true; } +// Tell USBTMC class to set its bulk-in EP to ACK so that it can +// receive USBTMC commands. +// Returns false if it was already in an ACK state or is busy +// processing a command (such as a clear). Returns true if it was +// in the NAK state and successfully transitioned to the ACK wait +// state. +bool usbtmcd_start_bus_read(uint8_t rhport) +{ + usbtmcd_state_enum oldState = usbtmc_state.state; + switch(oldState) + { + // These may transition to IDLE + case STATE_NAK: + case STATE_ABORTING_BULK_IN_ABORTED: + TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); + break; + // When receiving, let it remain receiving + case STATE_RCV: + break; + default: + TU_VERIFY(false); + } + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + return true; +} + void usbtmcd_reset_cb(uint8_t rhport) { (void)rhport; @@ -367,19 +394,21 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack if(len >= usbtmc_state.transfer_size_remaining || shortPacket) { atEnd = true; + TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); } len = tu_min32(len, usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining -= len; + usbtmc_state.transfer_size_sent += len; + + // App may (should?) call the wait_for_bus() command at this point if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; } - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - TU_VERIFY(atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV)); return true; } @@ -453,7 +482,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(false); return false; } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_RCV: @@ -462,7 +490,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(false); } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_ABORTING_BULK_OUT: @@ -482,8 +509,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint { switch(usbtmc_state.state) { case STATE_TX_SHORTED: - - usbtmc_state.state = STATE_IDLE; + TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); break; @@ -508,7 +534,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: @@ -548,9 +574,10 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r if(ep_addr == usbtmc_state.ep_bulk_out) { + criticalEnter(); + usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us + criticalLeave(); usmtmcd_app_bulkOut_clearFeature_cb(rhport); - // And start a new OUT xfer request now that things are clear - TU_ASSERT( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); } else if (ep_addr == usbtmc_state.ep_bulk_in) { @@ -605,6 +632,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { usbtmc_check_abort_bulk_rsp_t rsp = { @@ -750,7 +778,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pluse_cb(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(rhport, request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index d33d73905..3638b5527 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -55,6 +55,17 @@ extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif +// In order to proceed, app must call call usbtmcd_start_bus_read(rhport) during or soon after: +// * tud_usbtmc_app_open_cb +// * tud_usbtmc_app_msg_data_cb +// * tud_usbtmc_app_msgBulkIn_complete_cb +// * tud_usbtmc_app_msg_trigger_cb +// * (successful) tud_usbtmc_app_check_abort_bulk_out_cb +// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb +// * (successful) usmtmcd_app_bulkOut_clearFeature_cb + +void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id); + bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); @@ -73,7 +84,7 @@ bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_b bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); @@ -93,6 +104,8 @@ bool usbtmcd_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); +bool usbtmcd_start_bus_read(uint8_t rhport); + /* "callbacks" from USB device core */ From 624f4bf4ceaf1cd334326ccb3777efa2c954de1b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:42:29 -0400 Subject: [PATCH 89/94] Remove rhport from app code. If anything, it should be the interface_id. Assume a single interface, for now. --- examples/device/usbtmc/src/usbtmc_app.c | 68 +++++++++---------------- src/class/usbtmc/usbtmc_device.c | 41 +++++++-------- src/class/usbtmc/usbtmc_device.h | 37 +++++++------- 3 files changed, 64 insertions(+), 82 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 2982675b1..b622d6b9b 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,24 +96,22 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id) +void tud_usbtmc_app_open_cb(uint8_t interface_id) { (void)interface_id; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); } -bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { - (void)rhport; +bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; // Let trigger set the SRQ status |= IEEE4882_STB_SRQ; return true; } -bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) { - (void)rhport; (void)msgHeader; buffer_len = 0; if(msgHeader->TransferSize > sizeof(buffer)) @@ -124,10 +122,8 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_d return true; } -bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) { - (void)rhport; - // If transfer isn't finished, we just ignore it (for now) if(len + buffer_len < sizeof(buffer)) @@ -156,13 +152,12 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra d=0; resp_delay = (uint32_t)d; } - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) +bool tud_usbtmc_app_msgBulkIn_complete_cb() { - (void)rhport; if((buffer_tx_ix == buffer_len) || idnQuery) // done { status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV @@ -170,17 +165,15 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) bulkInStarted = 0; buffer_tx_ix = 0; } - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } static unsigned int msgReqLen; -bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) { - (void)rhport; - rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; @@ -200,7 +193,7 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ else { size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); - usbtmcd_transmit_dev_msg_data(rhport, &buffer[buffer_tx_ix], txlen, + usbtmcd_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, (buffer_tx_ix+txlen) == buffer_len, false); buffer_tx_ix += txlen; } @@ -209,7 +202,6 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ } void usbtmc_app_task_iter(void) { - uint8_t const rhport = 0; switch(queryState) { case 0: break; @@ -234,14 +226,14 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + usbtmcd_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); queryState = 0; bulkInStarted = 0; } else { buffer_tx_ix = tu_min32(buffer_len,msgReqLen); - usbtmcd_transmit_dev_msg_data(rhport, buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); + usbtmcd_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } @@ -252,9 +244,8 @@ void usbtmc_app_task_iter(void) { } } -bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) { - (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; queryState = 0; bulkInStarted = false; @@ -262,9 +253,8 @@ bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) return true; } -bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) { - (void)rhport; queryState = 0; bulkInStarted = false; status = 0; @@ -274,50 +264,43 @@ bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) { - (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { - (void)rhport; (void)rsp; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) { - (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { - (void)rhport; (void)rsp; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) +void usmtmcd_app_bulkIn_clearFeature_cb(void) { - (void)rhport; } -void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) +void usmtmcd_app_bulkOut_clearFeature_cb(void) { - (void)rhport; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) { - (void)rhport; uint8_t old_status = status; status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ @@ -327,9 +310,8 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) { - (void)rhport; (void)msg; led_indicator_pulse(); *tmcResult = USBTMC_STATUS_SUCCESS; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 401b4acc4..a65c5e7c4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -119,6 +119,7 @@ typedef struct volatile usbtmcd_state_enum state; uint8_t itf_id; + uint8_t rhport; uint8_t ep_bulk_in; uint8_t ep_bulk_out; uint8_t ep_int_in; @@ -186,7 +187,6 @@ bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newS // We can't just send the whole thing at once because we need to concatanate the // header with the data. bool usbtmcd_transmit_dev_msg_data( - uint8_t rhport, const void * data, size_t len, bool endOfMessage, bool usingTermChar) @@ -229,7 +229,7 @@ bool usbtmcd_transmit_dev_msg_data( bool stateChanged = atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } @@ -269,6 +269,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin p_desc = (uint8_t const *) itf_desc; usbtmc_state.itf_id = itf_desc->bInterfaceNumber; + usbtmc_state.rhport = rhport; while (found_endpoints < itf_desc->bNumEndpoints) { @@ -324,7 +325,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_app_open_cb(rhport, itf_desc->iInterface); + tud_usbtmc_app_open_cb(itf_desc->iInterface); return true; } @@ -334,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool usbtmcd_start_bus_read(uint8_t rhport) +bool usbtmcd_start_bus_read() { usbtmcd_state_enum oldState = usbtmc_state.state; switch(oldState) @@ -350,7 +351,7 @@ bool usbtmcd_start_bus_read(uint8_t rhport) default: TU_VERIFY(false); } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; } @@ -374,7 +375,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); usbtmc_state.lastBulkOutTag = msg->header.bTag; @@ -403,7 +404,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack usbtmc_state.transfer_size_sent += len; // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) + if(!tud_usbtmc_app_msg_data_cb(data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; @@ -413,7 +414,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack return true; } -static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) +static bool handle_devMsgIn(void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; @@ -429,7 +430,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) if(termCharRequested) TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); return true; } @@ -464,14 +465,14 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); break; #if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); break; #endif @@ -626,7 +627,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -642,7 +643,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(&rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -672,7 +673,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -700,7 +701,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(&rsp)); criticalEnter(); switch(usbtmc_state.state) { @@ -732,7 +733,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_CLEARING; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(&tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -752,7 +753,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r else { // Let app check if it's clear - TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); + TU_VERIFY(tud_usbtmc_app_check_clear_cb(&clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) { @@ -778,7 +779,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -809,13 +810,13 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { - rsp.statusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 3638b5527..9f88e5e83 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,32 +64,32 @@ extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb // * (successful) usmtmcd_app_bulkOut_clearFeature_cb -void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id); +void tud_usbtmc_app_open_cb(uint8_t interface_id); -bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport); -void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_app_msgBulkIn_complete_cb(); +void usmtmcd_app_bulkIn_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(uint8_t rhport); +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); +//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); #endif /******************************************* @@ -100,11 +100,10 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_gener ******************************************/ bool usbtmcd_transmit_dev_msg_data( - uint8_t rhport, const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(uint8_t rhport); +bool usbtmcd_start_bus_read(); /* "callbacks" from USB device core */ From 412a279073b77c6f5d3b6796089eb90509322a7a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:54:45 -0400 Subject: [PATCH 90/94] I never understood why I need to write void as empty function arguments. --- src/class/usbtmc/usbtmc_device.c | 6 +++--- src/class/usbtmc/usbtmc_device.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a65c5e7c4..dad892f43 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -511,7 +511,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(usbtmc_state.state) { case STATE_TX_SHORTED: TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb()); break; case STATE_TX_INITIATED: @@ -578,11 +578,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - usmtmcd_app_bulkOut_clearFeature_cb(rhport); + usmtmcd_app_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature_cb(rhport); + usmtmcd_app_bulkIn_clearFeature_cb(); } else { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 9f88e5e83..a3f0e90e0 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -69,11 +69,11 @@ void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer +void usmtmcd_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(); -void usmtmcd_app_bulkIn_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_complete_cb(void); +void usmtmcd_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); @@ -103,7 +103,7 @@ bool usbtmcd_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(); +bool usbtmcd_start_bus_read(void); /* "callbacks" from USB device core */ From 2d4352bfe9d969c76374cd15c3332fbe9f98d66a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 11:34:27 -0400 Subject: [PATCH 91/94] Rename USBTMC functions. --- examples/device/usbtmc/src/tusb_config.h | 2 +- examples/device/usbtmc/src/usbtmc_app.c | 26 ++++++++++++------------ src/class/usbtmc/usbtmc_device.c | 18 ++++++++-------- src/class/usbtmc/usbtmc_device.h | 20 +++++++++--------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 688fb02be..c20b05fbb 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -57,7 +57,7 @@ #define CFG_TUD_USBTMC 1 #define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define CFG_USBTMC_CFG_ENABLE_488 1 +#define CFG_TUD_USBTMC_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index b622d6b9b..d06014ce8 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "main.h" -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const @@ -48,7 +48,7 @@ tud_usbtmc_app_capabilities = .canEndBulkInOnTermChar = 0 }, -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { @@ -99,7 +99,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { void tud_usbtmc_app_open_cb(uint8_t interface_id) { (void)interface_id; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); } @@ -152,7 +152,7 @@ bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) d=0; resp_delay = (uint32_t)d; } - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -165,7 +165,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb() bulkInStarted = 0; buffer_tx_ix = 0; } - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -193,7 +193,7 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * r else { size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); - usbtmcd_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, + tud_usbtmc_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, (buffer_tx_ix+txlen) == buffer_len, false); buffer_tx_ix += txlen; } @@ -226,14 +226,14 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + tud_usbtmc_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); queryState = 0; bulkInStarted = 0; } else { buffer_tx_ix = tu_min32(buffer_len,msgReqLen); - usbtmcd_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); + tud_usbtmc_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } @@ -273,7 +273,7 @@ bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -286,16 +286,16 @@ bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } -void usmtmcd_app_bulkIn_clearFeature_cb(void) +void tud_usbtmc_app_bulkIn_clearFeature_cb(void) { } -void usmtmcd_app_bulkOut_clearFeature_cb(void) +void tud_usmtmc_app_bulkOut_clearFeature_cb(void) { - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index dad892f43..f0b74fe38 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -186,7 +186,7 @@ bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newS // We can't just send the whole thing at once because we need to concatanate the // header with the data. -bool usbtmcd_transmit_dev_msg_data( +bool tud_usbtmc_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar) @@ -236,7 +236,7 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init_cb(void) { #ifndef NDEBUG -# if CFG_USBTMC_CFG_ENABLE_488 +# if CFG_TUD_USBTMC_ENABLE_488 if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 @@ -316,7 +316,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { TU_ASSERT(usbtmc_state.ep_int_in != 0); } -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { @@ -335,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool usbtmcd_start_bus_read() +bool tud_usbtmc_start_bus_read() { usbtmcd_state_enum oldState = usbtmc_state.state; switch(oldState) @@ -468,7 +468,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); break; -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); @@ -562,7 +562,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) uint8_t bTag; #endif @@ -578,11 +578,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - usmtmcd_app_bulkOut_clearFeature_cb(); + tud_usmtmc_app_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature_cb(); + tud_usbtmc_app_bulkIn_clearFeature_cb(); } else { @@ -783,7 +783,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) // USB488 required requests case USB488_bREQUEST_READ_STATUS_BYTE: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a3f0e90e0..9f1020e58 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -37,8 +37,8 @@ #include "usbtmc.h" // Enable 488 mode by default -#if !defined(CFG_USBTMC_CFG_ENABLE_488) -#define CFG_CFG_USBTMC_CFG_ENABLE_488 (1) +#if !defined(CFG_TUD_USBTMC_ENABLE_488) +#define CFG_TUD_USBTMC_ENABLE_488 (1) #endif // USB spec says that full-speed must be 8,16,32, or 64. @@ -49,31 +49,31 @@ * Functions to be implemeted by the class implementation */ -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; #else extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif -// In order to proceed, app must call call usbtmcd_start_bus_read(rhport) during or soon after: +// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: // * tud_usbtmc_app_open_cb // * tud_usbtmc_app_msg_data_cb // * tud_usbtmc_app_msgBulkIn_complete_cb // * tud_usbtmc_app_msg_trigger_cb // * (successful) tud_usbtmc_app_check_abort_bulk_out_cb // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb -// * (successful) usmtmcd_app_bulkOut_clearFeature_cb +// * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usmtmc_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); bool tud_usbtmc_app_msgBulkIn_complete_cb(void); -void usmtmcd_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usbtmc_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); @@ -86,7 +86,7 @@ bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); @@ -99,11 +99,11 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); * notified that the transfer is complete. ******************************************/ -bool usbtmcd_transmit_dev_msg_data( +bool tud_usbtmc_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(void); +bool tud_usbtmc_start_bus_read(void); /* "callbacks" from USB device core */ From 3a87dd65d735085845cbf799add77596cf737f44 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:17:49 -0400 Subject: [PATCH 92/94] Change getting the capabilities structure to a callback instead of an extern struct. --- examples/device/usbtmc/src/usbtmc_app.c | 14 ++++++++-- src/class/usbtmc/usbtmc_device.c | 36 ++++++++++++++++--------- src/class/usbtmc/usbtmc_device.h | 12 ++++----- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index d06014ce8..924a33fab 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -30,9 +30,9 @@ #include "main.h" #if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const +static usbtmc_response_capabilities_488_t const #else -usbtmc_response_capabilities_t const +static usbtmc_response_capabilities_t const #endif tud_usbtmc_app_capabilities = { @@ -102,6 +102,16 @@ void tud_usbtmc_app_open_cb(uint8_t interface_id) tud_usbtmc_start_bus_read(); } +#if (CFG_TUD_USBTMC_ENABLE_488) +usbtmc_response_capabilities_488_t const * +#else +usbtmc_response_capabilities_t const * +#endif +tud_usbtmc_get_capabilities_cb() +{ + return &tud_usbtmc_app_capabilities; +} + bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index f0b74fe38..927ac8ecf 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -114,6 +114,13 @@ typedef enum STATE_NUM_STATES } usbtmcd_state_enum; +#if (CFG_TUD_USBTMC_ENABLE_488) + typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; +#else + typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; +#endif + + typedef struct { volatile usbtmcd_state_enum state; @@ -135,6 +142,8 @@ typedef struct uint8_t lastBulkInTag; // used for aborts (mostly) uint8_t const * devInBuffer; // pointer to application-layer used for transmissions + + usbtmc_capabilities_specific_t const * capabilities; } usbtmc_interface_state_t; static usbtmc_interface_state_t usbtmc_state = @@ -199,7 +208,7 @@ bool tud_usbtmc_transmit_dev_msg_data( TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); if(usingTermChar) { - TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[len-1u] == termChar); } @@ -235,15 +244,16 @@ bool tud_usbtmc_transmit_dev_msg_data( void usbtmcd_init_cb(void) { + usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); #ifndef NDEBUG # if CFG_TUD_USBTMC_ENABLE_488 - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + if(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); # endif - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + if(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); #endif @@ -317,8 +327,8 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT(usbtmc_state.ep_int_in != 0); } #if (CFG_TUD_USBTMC_ENABLE_488) - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || - tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) + if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || + usbtmc_state.capabilities->bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -358,9 +368,11 @@ bool tud_usbtmc_start_bus_read() void usbtmcd_reset_cb(uint8_t rhport) { (void)rhport; + usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); criticalEnter(); tu_varclr(&usbtmc_state); + usbtmc_state.capabilities = capabilities; usbtmc_state.itf_id = 0xFFu; criticalLeave(); } @@ -428,7 +440,7 @@ static bool handle_devMsgIn(void *data, size_t len) termChar = msg->TermChar; if(termCharRequested) - TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); return true; @@ -471,7 +483,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if (CFG_TUD_USBTMC_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); break; @@ -768,8 +780,8 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r case USBTMC_bREQUEST_GET_CAPABILITIES: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tud_usbtmc_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tud_usbtmc_app_capabilities, sizeof(tud_usbtmc_app_capabilities))); + TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); return true; } // USBTMC Optional Requests @@ -778,7 +790,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 9f1020e58..adccd65e1 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -49,12 +49,6 @@ * Functions to be implemeted by the class implementation */ -#if (CFG_TUD_USBTMC_ENABLE_488) -extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; -#else -extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; -#endif - // In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: // * tud_usbtmc_app_open_cb // * tud_usbtmc_app_msg_data_cb @@ -64,6 +58,12 @@ extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb // * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb +#if (CFG_TUD_USBTMC_ENABLE_488) +usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); +#else +usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); +#endif + void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); From 6c6a01cbcdc98a1e1346fc74b0d79db90443c7e3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:18:10 -0400 Subject: [PATCH 93/94] USBTMC: Minor updates to testing script. --- examples/device/usbtmc/visaQuery.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 4d4b50c4b..44b5fd875 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -11,6 +11,7 @@ def test_idn(): def test_echo(m,n): longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 + t0 = time.monotonic() #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) for i in range(m,n): @@ -22,7 +23,9 @@ def test_echo(m,n): #print (":".join("{:02x}".format(ord(c)) for c in xt)) #print (":".join("{:02x}".format(ord(c)) for c in y)) assert(xt == y), f"failed i={i}" - inst.read_stb();# Just to make USB logging easier by sending a control query + #inst.read_stb();# Just to make USB logging easier by sending a control query (bad thing is that this made things slow) + t = time.monotonic() - t0 + print(f" elapsed: {t:0.3} sec") def test_trig(): # clear SRQ @@ -70,13 +73,13 @@ def test_read_timeout(): inst.read_stb() assert (inst.read_stb() == 0) inst.write("delay 500") - t0 = time.time() + t0 = time.monotonic() try: rsp = inst.read() assert(false), "Read should have resulted in timeout" except visa.VisaIOError: - print("Got expected exception") - t = time.time() - t0 + print(" Got expected exception") + t = time.monotonic() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) print(f"Delay was {t:0.3}") @@ -92,16 +95,16 @@ def test_abort_in(): assert (inst.read_stb() == 0) inst.write("delay 500") inst.write("xxx") - t0 = time.time() + t0 = time.monotonic() try: rsp = inst.read() assert(false), "Read should have resulted in timeout" except visa.VisaIOError: - print("Got expected exception") - t = time.time() - t0 + print(" Got expected exception") + t = time.monotonic() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) - print(f"Delay was {t:0.3}") + print(f" Delay was {t:0.3}") # Response is still in queue, so send a clear (to be more helpful to the next test) inst.timeout = 800 y = inst.read() @@ -180,5 +183,11 @@ test_indicate() print("+ TRIG") test_trig() +# Untested: +# abort bulk out +# LLO, GTL, etc +# Throughput rate? +# Transmitting a message using multiple transfers + inst.close() print("Test complete") From 6841b236e89cad45024280c44a77e43490635af2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:45:39 -0400 Subject: [PATCH 94/94] Remove _app from callback function names. --- examples/device/usbtmc/src/usbtmc_app.c | 32 ++++++++--------- src/class/usbtmc/usbtmc_device.c | 38 ++++++++++---------- src/class/usbtmc/usbtmc_device.h | 46 ++++++++++++------------- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 924a33fab..0e39b4227 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,7 +96,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -void tud_usbtmc_app_open_cb(uint8_t interface_id) +void tud_usbtmc_open_cb(uint8_t interface_id) { (void)interface_id; tud_usbtmc_start_bus_read(); @@ -113,14 +113,14 @@ tud_usbtmc_get_capabilities_cb() } -bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { +bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; // Let trigger set the SRQ status |= IEEE4882_STB_SRQ; return true; } -bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)msgHeader; buffer_len = 0; @@ -132,7 +132,7 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * m return true; } -bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_msg_data_cb(void *data, size_t len, bool transfer_complete) { // If transfer isn't finished, we just ignore it (for now) @@ -166,7 +166,7 @@ bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) return true; } -bool tud_usbtmc_app_msgBulkIn_complete_cb() +bool tud_usbtmc_msgBulkIn_complete_cb() { if((buffer_tx_ix == buffer_len) || idnQuery) // done { @@ -182,7 +182,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb() static unsigned int msgReqLen; -bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) { rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, @@ -254,7 +254,7 @@ void usbtmc_app_task_iter(void) { } } -bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult) { *tmcResult = USBTMC_STATUS_SUCCESS; queryState = 0; @@ -263,7 +263,7 @@ bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) return true; } -bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) { queryState = 0; bulkInStarted = false; @@ -274,42 +274,42 @@ bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult) { bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; tud_usbtmc_start_bus_read(); return true; } -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult) { *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; tud_usbtmc_start_bus_read(); return true; } -void tud_usbtmc_app_bulkIn_clearFeature_cb(void) +void tud_usbtmc_bulkIn_clearFeature_cb(void) { } -void tud_usmtmc_app_bulkOut_clearFeature_cb(void) +void tud_usmtmc_bulkOut_clearFeature_cb(void) { tud_usbtmc_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) +uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult) { uint8_t old_status = status; status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ @@ -320,7 +320,7 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)msg; led_indicator_pulse(); diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 927ac8ecf..c8e742fc5 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -248,13 +248,13 @@ void usbtmcd_init_cb(void) #ifndef NDEBUG # if CFG_TUD_USBTMC_ENABLE_488 if(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); + TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); # endif if(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); + TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); @@ -335,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_app_open_cb(itf_desc->iInterface); + tud_usbtmc_open_cb(itf_desc->iInterface); return true; } @@ -387,7 +387,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(msg)); + TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); usbtmc_state.lastBulkOutTag = msg->header.bTag; @@ -416,7 +416,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack usbtmc_state.transfer_size_sent += len; // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_app_msg_data_cb(data, len, atEnd)) + if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; @@ -442,7 +442,7 @@ static bool handle_devMsgIn(void *data, size_t len) if(termCharRequested) TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); + TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); return true; } @@ -484,7 +484,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); + TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); break; #endif @@ -523,7 +523,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(usbtmc_state.state) { case STATE_TX_SHORTED: TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb()); + TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); break; case STATE_TX_INITIATED: @@ -590,11 +590,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - tud_usmtmc_app_bulkOut_clearFeature_cb(); + tud_usmtmc_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - tud_usbtmc_app_bulkIn_clearFeature_cb(); + tud_usbtmc_bulkIn_clearFeature_cb(); } else { @@ -639,7 +639,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -655,7 +655,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(&rsp)); + TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -685,7 +685,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -713,7 +713,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(&rsp)); + TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); criticalEnter(); switch(usbtmc_state.state) { @@ -745,7 +745,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_CLEARING; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(&tmcStatusCode)); + TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -765,7 +765,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r else { // Let app check if it's clear - TU_VERIFY(tud_usbtmc_app_check_clear_cb(&clearStatusRsp)); + TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) { @@ -791,7 +791,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -822,13 +822,13 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { - rsp.statusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index adccd65e1..4c52989c2 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -50,13 +50,13 @@ */ // In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_app_open_cb -// * tud_usbtmc_app_msg_data_cb -// * tud_usbtmc_app_msgBulkIn_complete_cb -// * tud_usbtmc_app_msg_trigger_cb -// * (successful) tud_usbtmc_app_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb +// * tud_usbtmc_open_cb +// * tud_usbtmc_msg_data_cb +// * tud_usbtmc_msgBulkIn_complete_cb +// * tud_usbtmc_msg_trigger_cb +// * (successful) tud_usbtmc_check_abort_bulk_out_cb +// * (successful) tud_usbtmc_check_abort_bulk_in_cb +// * (successful) tud_usmtmc_bulkOut_clearFeature_cb #if (CFG_TUD_USBTMC_ENABLE_488) usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); @@ -64,31 +64,31 @@ usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); #endif -void tud_usbtmc_app_open_cb(uint8_t interface_id); +void tud_usbtmc_open_cb(uint8_t interface_id); -bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usmtmc_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); +void tud_usmtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(void); -void tud_usbtmc_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_msgBulkIn_complete_cb(void); +void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); +uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); #endif