From 41f2f8462a2dc71c8194703fb879e6a667fb723b Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Wed, 2 Oct 2019 15:14:28 -0300 Subject: Add fault handlers to ease ARM-v7m (Cortex M3/M4(F)/M7 debugging --- .../.cproject | 67 ++ .../RT-STM32F407-DISCOVERY-fault_handlers/.project | 100 +++ .../.settings/org.eclipse.cdt.core.prefs | 6 + .../RT-STM32F407-DISCOVERY-fault_handlers/Makefile | 189 ++++++ .../cfg/chconf.h | 714 +++++++++++++++++++++ .../cfg/halconf.h | 525 +++++++++++++++ .../cfg/mcuconf.h | 342 ++++++++++ .../crash_test.c | 169 +++++ .../crash_test_asm.S | 273 ++++++++ ...2F407-DISCOVERY (OpenOCD, Flash and Run).launch | 52 ++ ...-STM32F407-DISCOVERY (OpenOCD, Just Run).launch | 52 ++ .../RT-STM32F407-DISCOVERY-fault_handlers/main.c | 69 ++ .../readme.txt | 25 + .../compilers/GCC/utils/fault_handlers_v7m.c | 215 +++++++ .../compilers/GCC/utils/fault_handlers_v7m.mk | 4 + .../compilers/GCC/utils/hardfault_handler_v7m.S | 113 ++++ .../compilers/GCC/utils/port_fault_handlers.h | 52 ++ os/various/fault_handlers/fault_handlers.h | 22 + 18 files changed, 2989 insertions(+) create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.cproject create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.project create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.settings/org.eclipse.cdt.core.prefs create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/Makefile create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/chconf.h create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/halconf.h create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/mcuconf.h create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test.c create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test_asm.S create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Flash and Run).launch create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Just Run).launch create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/main.c create mode 100644 demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/readme.txt create mode 100644 os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c create mode 100644 os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.mk create mode 100644 os/common/ports/ARMCMx/compilers/GCC/utils/hardfault_handler_v7m.S create mode 100644 os/common/ports/ARMCMx/compilers/GCC/utils/port_fault_handlers.h create mode 100644 os/various/fault_handlers/fault_handlers.h diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.cproject b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.cproject new file mode 100644 index 0000000..84bb22d --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.cproject @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.project b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.project new file mode 100644 index 0000000..34d336b --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.project @@ -0,0 +1,100 @@ + + + RT-STM32F407-DISCOVERY-fault_handlers + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -j1 + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + board + 2 + $%7BPARENT-4-PROJECT_LOC%7D/ChibiOS/os/hal/boards/ST_STM32F4_DISCOVERY + + + contrib-os + 2 + $%7BPARENT-3-PROJECT_LOC%7D/os + + + os + 2 + $%7BPARENT-4-PROJECT_LOC%7D/ChibiOS/os + + + test + 2 + CHIBIOS/test + + + diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.settings/org.eclipse.cdt.core.prefs b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..2862090 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +environment/project/0.114656749/PATH/delimiter=; +environment/project/0.114656749/PATH/operation=replace +environment/project/0.114656749/PATH/value=${PATH};D\:\\toolchains\\gcc-arm-none-eabi-8-2018-q4-major-win32\\bin;${PATH};D\:\\toolchains\\gcc-arm-none-eabi-4_9-2014q4-20141203-win32\\bin;D\:\\toolchains\\msys64\\usr\\bin +environment/project/0.114656749/append=true +environment/project/0.114656749/appendContributed=true diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/Makefile b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/Makefile new file mode 100644 index 0000000..6127db4 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/Makefile @@ -0,0 +1,189 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -Og -ggdb -fomit-frame-pointer -falign-functions=16 +endif + +# C specific options here (added to USE_OPT). +ifeq ($(USE_COPT),) + USE_COPT = +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data. +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# Linker extra options here. +ifeq ($(USE_LDOPT),) + USE_LDOPT = +endif + +# Enable this if you want link time optimizations (LTO). +ifeq ($(USE_LTO),) + USE_LTO = no +endif + +# Enable this if you want to see the full log while compiling. +ifeq ($(USE_VERBOSE_COMPILE),) + USE_VERBOSE_COMPILE = no +endif + +# If enabled, this option makes the build process faster by not compiling +# modules not used in the current configuration. +ifeq ($(USE_SMART_BUILD),) + USE_SMART_BUILD = yes +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Stack size to be allocated to the Cortex-M process stack. This stack is +# the stack used by the main() thread. +ifeq ($(USE_PROCESS_STACKSIZE),) + USE_PROCESS_STACKSIZE = 0x400 +endif + +# Stack size to the allocated to the Cortex-M main/exceptions stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_EXCEPTIONS_STACKSIZE),) + USE_EXCEPTIONS_STACKSIZE = 0x400 +endif + +# Enables the use of FPU (no, softfp, hard). +ifeq ($(USE_FPU),) + USE_FPU = hard +endif + +# FPU-related options. +ifeq ($(USE_FPU_OPT),) + USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16 +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, target, sources and paths +# + +# Define project name here +PROJECT = ch + +# Target settings. +MCU = cortex-m4 + +# Imported source files and paths. +CHIBIOS := ../../../../ChibiOS +CHIBIOS_CONTRIB := ../../../ +CONFDIR := ./cfg +BUILDDIR := ./build +DEPDIR := ./.dep + +# Licensing files. +include $(CHIBIOS)/os/license/license.mk +# Startup files. +include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk +# HAL-OSAL files (optional). +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk +include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk +include $(CHIBIOS)/os/hal/osal/rt/osal.mk +# RTOS files (optional). +include $(CHIBIOS)/os/rt/rt.mk +include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk +# Auto-build files in ./source recursively. +include $(CHIBIOS)/tools/mk/autobuild.mk +# Other files (optional). +include $(CHIBIOS_CONTRIB)/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.mk +include $(CHIBIOS)/os/hal/lib/streams/streams.mk + +# Define linker script file here +LDSCRIPT= $(STARTUPLD)/STM32F407xG.ld + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(ALLCSRC) \ + $(TESTSRC) \ + main.c crash_test.c + +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CPPSRC = $(ALLCPPSRC) + +# List ASM source files here. +ASMSRC = $(ALLASMSRC) + +# List ASM with preprocessor source files here. +ASMXSRC = $(ALLXASMSRC) crash_test_asm.S + +# Inclusion directories. +INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC) + +# Define C warning options here. +CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes + +# Define C++ warning options here. +CPPWARN = -Wall -Wextra -Wundef + +# +# Project, target, sources and paths +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = -DFAULT_INFO_HOOK=_fault_info_hook + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user section +############################################################################## + +############################################################################## +# Common rules +# + +RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk +include $(RULESPATH)/arm-none-eabi.mk +include $(RULESPATH)/rules.mk + +# +# Common rules +############################################################################## + +############################################################################## +# Custom rules +# + +# +# Custom rules +############################################################################## diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/chconf.h b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/chconf.h new file mode 100644 index 0000000..7dc4f84 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/chconf.h @@ -0,0 +1,714 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 10000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM TRUE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS TRUE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY TRUE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/halconf.h b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/halconf.h new file mode 100644 index 0000000..e6437cd --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/halconf.h @@ -0,0 +1,525 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/mcuconf.h b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/mcuconf.h new file mode 100644 index 0000000..9b16e42 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/cfg/mcuconf.h @@ -0,0 +1,342 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test.c b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test.c new file mode 100644 index 0000000..bf11436 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test.c @@ -0,0 +1,169 @@ +/* Copyright (C) 2018 Adam Green (https://github.com/adamgreen) + 2019 Diego Ismirlian (dismirlian(at)google's mail) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + This code is heavily based on the work of Adam Green (https://github.com/adamgreen) +*/ + + +#include +#include + +// Assembly language routines defined in tests.S +void testMspMultipleOf8(void); +void testMspNotMultipleOf8(void); +void testPspMultipleOf8(void); +void testInitFPURegisters(void); +void testBreakpoints(void); + +static void enable8ByteStackAlignment(void); +static void crashWithFPUDisabled(void); +static void crashWithFPUAutoStackingDisabled(void); +static void crashWithFPUAutoStackEnabled(void); +static void crashWithFPULazyAutoStacking(void); + +#define CRASH_CATCHER_READ_FAULT() (*(volatile unsigned int*)0x55555550) +#define CRASH_CATCHER_WRITE_FAULT() (*(volatile unsigned int*)0x55555550 = 0x0) +#define CRASH_CATCHER_INVALID_INSTRUCTION() { __asm volatile (".word 0xDE00"); } + +/* Macro used to insert hardcoded breakpoint into user's code. */ +#define CRASH_CATCHER_BREAKPOINT() { __asm volatile ("bkpt #0"); } + +int crash(int option) { + + enable8ByteStackAlignment(); + + switch (option) { + case 1: + testMspMultipleOf8(); + break; + case 2: + testMspNotMultipleOf8(); + break; + case 3: + testPspMultipleOf8(); + break; + case 4: + CRASH_CATCHER_READ_FAULT(); + break; + case 5: + CRASH_CATCHER_WRITE_FAULT(); + break; + case 6: + crashWithFPUDisabled(); + break; + case 7: + crashWithFPUAutoStackingDisabled(); + break; + case 8: + crashWithFPUAutoStackEnabled(); + break; + case 9: + crashWithFPULazyAutoStacking(); + break; + case 10: + testBreakpoints(); + break; + default: + break; + } + + return 0; +} + +static void enable8ByteStackAlignment() +{ + SCB->CCR |= SCB_CCR_STKALIGN_Msk; +} + +#if CORTEX_HAS_FPU +static void disableFPU(void) +{ + static const uint32_t FPCA = 1 << 2; + SCB->CPACR &= ~(0xF << 20); + __set_CONTROL(__get_CONTROL() & ~FPCA); +} + +static void enableFPU(void) +{ + SCB->CPACR |= (0xF << 20); +} + +static void crashWithFPUDisabled(void) +{ + disableFPU(); + __disable_irq(); + testInitFPURegisters(); + CRASH_CATCHER_READ_FAULT(); +} + +static const uint32_t ASPEN = 1 << 31; +static const uint32_t LSPEN = 1 << 30; + +static void crashWithFPUAutoStackingDisabled(void) +{ + disableFPU(); + FPU->FPCCR &= ~(ASPEN | LSPEN); + enableFPU(); + __disable_irq(); + testInitFPURegisters(); + CRASH_CATCHER_READ_FAULT(); +} + +static void crashWithFPUAutoStackEnabled(void) +{ + disableFPU(); + FPU->FPCCR |= ASPEN; + FPU->FPCCR &= ~LSPEN; + enableFPU(); + __disable_irq(); + testInitFPURegisters(); + CRASH_CATCHER_READ_FAULT(); +} + +static void crashWithFPULazyAutoStacking(void) +{ + disableFPU(); + FPU->FPCCR |= (ASPEN | LSPEN); + enableFPU(); + __disable_irq(); + testInitFPURegisters(); + CRASH_CATCHER_READ_FAULT(); +} + +#else + +static void crashWithFPUDisabled(void) +{ + return; +} + +static void crashWithFPUAutoStackingDisabled(void) +{ + return; +} + +static void crashWithFPUAutoStackEnabled(void) +{ + return; +} + +static void crashWithFPULazyAutoStacking(void) +{ + return; +} + +#endif // !defined(CORTEX_M4) diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test_asm.S b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test_asm.S new file mode 100644 index 0000000..57a2f8a --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/crash_test_asm.S @@ -0,0 +1,273 @@ +/* Copyright (C) 2018 Adam Green (https://github.com/adamgreen) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Implementation of code to generate various crash scenarios for testing. */ + .text + .syntax unified + + .global testMspMultipleOf8 + .type testMspMultipleOf8, %function + .thumb_func + /* extern "C" void testMspMultipleOf8(void); + Uses MSP and has it pointing to an even multiple of 8. + */ +testMspMultipleOf8: + // Make SP, an even multiple of 8. + mov r0, sp + movs r1, #4 + bics r0, r1 + mov sp, r0 + // Load 0xFFFFFFFF into LR + movs r1, #1 + rsbs r0, r1, #0 + mov lr, r0 + // Load known values into R0-R12 + movs r0, #0 + // r1 was already set correctly above when initializing LR. + movs r2, #2 + movs r3, #3 + movs r4, #4 + movs r5, #5 + movs r6, #6 + movs r7, #7 + mov r8, r7 + mov r9, r7 + mov r10, r7 + mov r11, r7 + mov r12, r7 + add r8, r1 + add r9, r2 + add r10, r3 + add r11, r4 + add r12, r5 + // Generate a hard fault by executing an undefined instruction. + .word 0xDE00 + // CrashCatcher_Entry() shouldn't return but if it does, just infinite loop here. + b . + // Let assembler know that we have hit the end of the function. + .pool + .size testMspMultipleOf8, .-testMspMultipleOf8 + + + .global testMspNotMultipleOf8 + .type testMspNotMultipleOf8, %function + .thumb_func + /* extern "C" void testMspNotMultipleOf8(void); + Uses MSP and has it not pointing to an even multiple of 8. + */ +testMspNotMultipleOf8: + // Make SP, not an even multiple of 8. + mov r0, sp + subs r0, #8 + movs r1, #4 + orrs r0, r1 + mov sp, r0 + // Load 0xFFFFFFFF into LR + movs r1, #1 + rsbs r0, r1, #0 + mov lr, r0 + // Load known values into R0-R12 + movs r0, #0 + // r1 was already set correctly above when initializing LR. + movs r2, #2 + movs r3, #3 + movs r4, #4 + movs r5, #5 + movs r6, #6 + movs r7, #7 + mov r8, r7 + mov r9, r7 + mov r10, r7 + mov r11, r7 + mov r12, r7 + add r8, r1 + add r9, r2 + add r10, r3 + add r11, r4 + add r12, r5 + // Generate a hard fault by executing an undefined instruction. + .word 0xDE00 + // CrashCatcher_Entry() shouldn't return but if it does, just infinite loop here. + b . + // Let assembler know that we have hit the end of the function. + .pool + .size testMspNotMultipleOf8, .-testMspNotMultipleOf8 + + + .global testPspMultipleOf8 + .type testPspMultipleOf8, %function + .thumb_func + /* extern "C" void testPspMultipleOf8(void); + Uses MSP and has it pointing to an even multiple of 8. + */ +testPspMultipleOf8: + // Make PSP, an even multiple of 8. + mov r0, sp + movs r1, #4 + bics r0, r1 + msr psp, r0 + // Switch to use of PSP. + movs r0, #3 + msr control,r0 + // Flush instructions so that control mods take effect. + isb + // Load 0xFFFFFFFF into LR + movs r1, #1 + rsbs r0, r1, #0 + mov lr, r0 + // Load known values into R0-R12 + movs r0, #0 + // r1 was already set correctly above when initializing LR. + movs r2, #2 + movs r3, #3 + movs r4, #4 + movs r5, #5 + movs r6, #6 + movs r7, #7 + mov r8, r7 + mov r9, r7 + mov r10, r7 + mov r11, r7 + mov r12, r7 + add r8, r1 + add r9, r2 + add r10, r3 + add r11, r4 + add r12, r5 + // Generate a hard fault by executing an undefined instruction. + .word 0xDE00 + // CrashCatcher_Entry() shouldn't return but if it does, just infinite loop here. + b . + // Let assembler know that we have hit the end of the function. + .pool + .size testPspMultipleOf8, .-testPspMultipleOf8 + + + .global testBreakpoints + .type testBreakpoints, %function + .thumb_func + /* extern "C" void testBreakpoints(void); + Set registers to known values, breakpoint, allow continuation, and breakpoint again to see if anything changed. + */ +testBreakpoints: + // Save away non-volatile registers that will be modified for testing. + mov r0, r8 + mov r1, r9 + mov r2, r10 + mov r3, r11 + push {r0-r7} + + // Load incrementing values into R0-R12 + movs r0, #0 + movs r1, #1 + movs r2, #2 + movs r3, #3 + movs r4, #4 + movs r5, #5 + movs r6, #6 + movs r7, #7 + mov r8, r7 + mov r9, r7 + mov r10, r7 + mov r11, r7 + mov r12, r7 + add r8, r1 + add r9, r2 + add r10, r3 + add r11, r4 + add r12, r5 + + // Issue one hard coded breakpoint. + bkpt #0 + + // Issue another hard coded breakpoint and see if dumps contain same values for all registers other than PC. + bkpt #255 + + // Restore non-volatile registers and return to caller. + pop {r0-r7} + mov r8, r0 + mov r9, r1 + mov r10, r2 + mov r11, r3 + bx lr + + // Let assembler know that we have hit the end of the function. + .pool + .size testBreakpoints, .-testBreakpoints + + +#if defined(TARGET_M4) + + .global testInitFPURegisters + .type testInitFPURegisters, %function + .thumb_func + /* extern "C" void testInitFPURegisters(void); + Initialize FPU registers to known values. + */ +testInitFPURegisters: + vmov.f32 s0, #-1.0 + vmov.f32 s1, #1.0 + vmov.f32 s2, #2.0 + vmov.f32 s3, #3.0 + vmov.f32 s4, #4.0 + vmov.f32 s5, #5.0 + vmov.f32 s6, #6.0 + vmov.f32 s7, #7.0 + vmov.f32 s8, #8.0 + vmov.f32 s9, #9.0 + vmov.f32 s10, #10.0 + vmov.f32 s11, #11.0 + vmov.f32 s12, #12.0 + vmov.f32 s13, #13.0 + vmov.f32 s14, #14.0 + vmov.f32 s15, #15.0 + vmov.f32 s16, #16.0 + vmov.f32 s17, #17.0 + vmov.f32 s18, #18.0 + vmov.f32 s19, #19.0 + vmov.f32 s20, #20.0 + vmov.f32 s21, #21.0 + vmov.f32 s22, #22.0 + vmov.f32 s23, #23.0 + vmov.f32 s24, #24.0 + vmov.f32 s25, #25.0 + vmov.f32 s26, #26.0 + vmov.f32 s27, #27.0 + vmov.f32 s28, #28.0 + vmov.f32 s29, #29.0 + vmov.f32 s30, #30.0 + vmov.f32 s31, #31.0 + ldr r0, =0xBAADFEED + vmsr fpscr, r0 + bx lr + .pool + .size testInitFPURegisters, .-testInitFPURegisters + +#else + + .global testInitFPURegisters + .type testInitFPURegisters, %function + .thumb_func + /* extern "C" void testInitFPURegisters(void); + Initialize FPU registers to known values. + */ +testInitFPURegisters: + bx lr + .pool + .size testInitFPURegisters, .-testInitFPURegisters + +#endif + + + .end diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Flash and Run).launch b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Flash and Run).launch new file mode 100644 index 0000000..3552b93 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Flash and Run).launch @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Just Run).launch b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Just Run).launch new file mode 100644 index 0000000..b692aa6 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/debug/RT-STM32F407-DISCOVERY (OpenOCD, Just Run).launch @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/main.c b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/main.c new file mode 100644 index 0000000..f5f6584 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/main.c @@ -0,0 +1,69 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "ch.h" +#include "hal.h" +#include "fault_handlers.h" + +int crash(int option); + +void _fault_info_hook(const struct fault_info *info) { + (void)info; + /* _print_message(info->decoded_info_string); */ +} + +int main(void) { + + /* + * System initializations. + * - HAL initialization, this also initializes the configured device drivers + * and performs the board-specific initializations. + * - Kernel initialization, the main() function becomes a thread and the + * RTOS is active. + */ + halInit(); + chSysInit(); + + /* + 1) MSP Rounded to multiple of 8 bytes. + 2) MSP Not Rounded to multiple of 8 bytes. + 3) PSP in use. + 4) Precise fault. + 5) Imprecise fault. + 6) Fault with FPU disabled. + 7) Fault with FPU auto-stacking disabled. + 8) Fault with FPU auto-stacking enabled. + 9) Fault with FPU lazy auto-stacking. + 10) Issue two breakpoints and return. + */ + crash(4); + + /* + * Activates the serial driver 2 using the driver default configuration. + * PA2(TX) and PA3(RX) are routed to USART2. + */ + sdStart(&SD2, NULL); + palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7)); + palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7)); + + /* + * Normal main() thread activity, in this demo it does nothing except + * sleeping in a loop and check the button state. + */ + while (true) { + chThdSleepMilliseconds(500); + } +} diff --git a/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/readme.txt b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/readme.txt new file mode 100644 index 0000000..1e088b7 --- /dev/null +++ b/demos/STM32/RT-STM32F407-DISCOVERY-fault_handlers/readme.txt @@ -0,0 +1,25 @@ +***************************************************************************** +** ChibiOS/RT port for ARM-Cortex-M4 STM32F407. ** +***************************************************************************** + +** TARGET ** + +The demo runs on an ST STM32F4-Discovery board. + +** The Demo ** + + +** Build Procedure ** + +The demo has been tested by using the free Codesourcery GCC-based toolchain +and YAGARTO. just modify the TRGT line in the makefile in order to use +different GCC toolchains. + +** Notes ** + +Some files used by the demo are not part of ChibiOS/RT but are copyright of +ST Microelectronics and are licensed under a different license. +Also note that not all the files present in the ST library are distributed +with ChibiOS/RT, you can find the whole library on the ST web site: + + http://www.st.com diff --git a/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c new file mode 100644 index 0000000..37b7fc7 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c @@ -0,0 +1,215 @@ +/* + ChibiOS - Copyright (C) 2019 Diego Ismirlian (dismirlian(at)google's mail) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "fault_handlers.h" +#include +#include + +#ifndef FAULT_NO_PRINT +#include +#include + +#define fault_printf(f, ...) \ + chprintf((BaseSequentialStream *)(&ms), \ + f "\n", ##__VA_ARGS__) + +static MemoryStream ms; +#else +#define fault_printf(f, ...) do {} while(0) +#endif + +static struct fault_info fault_info; + +static void _mem_fault(void) { + fault_printf("== Mem faults follow =="); + + if (SCB->CFSR & SCB_CFSR_MSTKERR_Msk) { + fault_printf("Stacking error"); + fault_info.decoded_fault_registers.memfault.stacking_error = true; + } + if (SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) { + fault_printf("Unstacking error"); + fault_info.decoded_fault_registers.memfault.unstacking_error = true; + } + if (SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) { + fault_printf("Data Access Violation"); + fault_info.decoded_fault_registers.memfault.data_access_violation = true; + } + if (SCB->CFSR & SCB_CFSR_MMARVALID_Msk) { + fault_printf("Address: 0x%08x", (uint32_t)SCB->MMFAR); + fault_info.decoded_fault_registers.memfault.data_access_violation_address = (uint32_t)SCB->MMFAR; + } else { + fault_printf("Address: unknown"); + fault_info.decoded_fault_registers.memfault.data_access_violation_address = 0xffffffff; + } + if (SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) { + fault_printf("Instruction Access Violation"); + fault_info.decoded_fault_registers.memfault.instruction_access_violation = true; + } +} + +static void _bus_fault(void) { + fault_printf("== Bus faults follow =="); + + if (SCB->CFSR & SCB_CFSR_STKERR_Msk) { + fault_printf("Stacking error"); + fault_info.decoded_fault_registers.busfault.stacking_error = true; + } + if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) { + fault_printf("Unstacking error"); + fault_info.decoded_fault_registers.busfault.unstacking_error = true; + } + if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) { + fault_printf("Precise data bus error"); + fault_info.decoded_fault_registers.busfault.precise_data_bus_error = true; + } + if (SCB->CFSR & SCB_CFSR_BFARVALID_Msk) { + fault_printf("Address: 0x%08x", (uint32_t)SCB->BFAR); + fault_info.decoded_fault_registers.busfault.precise_data_bus_error_address = (uint32_t)SCB->BFAR; + } else { + fault_printf("Address: unknown"); + fault_info.decoded_fault_registers.busfault.precise_data_bus_error_address = 0xffffffff; + } + if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) { + fault_printf("Imprecise data bus error"); + fault_info.decoded_fault_registers.busfault.imprecise_data_bus_error = true; + } + if (SCB->CFSR & SCB_CFSR_IBUSERR_Msk) { + fault_printf("Instruction bus error"); + fault_info.decoded_fault_registers.busfault.instruction_bus_error = true; + } +} + +static void _usage_fault(void) { + fault_printf("== Usage faults follow =="); + + if (SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) { + fault_printf("Division by zero"); + fault_info.decoded_fault_registers.usagefault.division_by_zero = true; + } + if (SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) { + fault_printf("Unaligned memory access"); + fault_info.decoded_fault_registers.usagefault.unaligned_memory_access = true; + } + if (SCB->CFSR & SCB_CFSR_NOCP_Msk) { + fault_printf("No coprocessor instructions"); + fault_info.decoded_fault_registers.usagefault.no_coprocessor_instructions = true; + } + if (SCB->CFSR & SCB_CFSR_INVPC_Msk) { + fault_printf("Invalid load of PC"); + fault_info.decoded_fault_registers.usagefault.invalid_load_of_pc = true; + } + if (SCB->CFSR & SCB_CFSR_INVSTATE_Msk) { + fault_printf("Invalid state"); + fault_info.decoded_fault_registers.usagefault.invalid_state = true; + } + if (SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) { + fault_printf("Undefined instruction"); + fault_info.decoded_fault_registers.usagefault.undefined_instruction = true; + } +} + +static void _init_fault_info(void) { +#ifndef FAULT_NO_PRINT + msObjectInit(&ms, + (uint8_t *)fault_info.decoded_info_string, + sizeof(fault_info.decoded_info_string) - 1, 0); +#endif +} + +static void _save_fault_info(void) { + memset(&fault_info.decoded_fault_registers, 0, sizeof(fault_info.decoded_fault_registers)); +#ifndef FAULT_NO_PRINT + memset(&fault_info.decoded_info_string, 0, sizeof(fault_info.decoded_info_string)); +#endif + + if (ch.rlist.current) { + fault_printf("Thread: 0x%08x, %s", + ch.rlist.current, ch.rlist.current->name); + + fault_info.decoded_fault_registers.general.current_thread_address = (uint32_t)ch.rlist.current; + fault_info.decoded_fault_registers.general.current_thread_name = ch.rlist.current->name; + } else { + fault_printf("Thread: unknown"); + } + + if (SCB->HFSR & SCB_HFSR_VECTTBL_Msk) { + fault_printf("Bus fault on vector table read"); + fault_info.decoded_fault_registers.general.bus_fault_on_ivt_read = true; + } + + if (SCB->HFSR & SCB_HFSR_FORCED_Msk) { + fault_info.decoded_fault_registers.general.escalation = true; + _mem_fault(); + _bus_fault(); + _usage_fault(); + } + if (!(SCB->HFSR & + (SCB_HFSR_VECTTBL_Msk | SCB_HFSR_FORCED_Msk))) { + fault_printf("No fault info"); + } +} + +#if defined(FAULT_INFO_HOOK) +void FAULT_INFO_HOOK(const struct fault_info *info); +#endif + +void _hardfault_info(void) { + _init_fault_info(); + fault_printf("HardFault Handler"); + _save_fault_info(); + +#if defined(FAULT_INFO_HOOK) + FAULT_INFO_HOOK(&fault_info); +#endif +} + +void _hardfault_epilogue(void) __attribute__((used, naked)); +void _hardfault_epilogue(void) { + + /* This is part of the HardFault handler + * + * You may inspect fault_info.decoded_fault_registers and + * fault_info.decoded_info_string to get a description of the fault that + * occurred. + * + * Also, the debugger should show an artificial call stack that led to the + * fault. This stack is reconstructed in assembly code, until GDB includes + * a way of automatically unwind an exception stack. + * + */ + __asm volatile( + "bkpt #0 \n" + "b _hardfault_exit \n" + ); +} + +void _unhandled_exception(void) { + /* This is an unhandled exception + * + * Once the breakpoint is hit, the debugger should show the ISR number + * in the vector_number variable. Don't trust the debugger's stack unwind; + * the _unhandled_exception ISR is shared among all undefined vectors. + */ + + volatile uint32_t vector_number = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk; + (void)vector_number; + + __asm volatile("bkpt #0"); + + /* we are here if there is no debugger attached */ + chSysHalt("unhandled exception"); +} diff --git a/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.mk b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.mk new file mode 100644 index 0000000..8e04203 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.mk @@ -0,0 +1,4 @@ +ALLINC += $(CHIBIOS_CONTRIB)/os/various/fault_handlers \ + $(CHIBIOS_CONTRIB)/os/common/ports/ARMCMx/compilers/GCC/utils/ +ALLCSRC += $(CHIBIOS_CONTRIB)/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c +ALLXASMSRC += $(CHIBIOS_CONTRIB)/os/common/ports/ARMCMx/compilers/GCC/utils/hardfault_handler_v7m.S diff --git a/os/common/ports/ARMCMx/compilers/GCC/utils/hardfault_handler_v7m.S b/os/common/ports/ARMCMx/compilers/GCC/utils/hardfault_handler_v7m.S new file mode 100644 index 0000000..9b4b96f --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/utils/hardfault_handler_v7m.S @@ -0,0 +1,113 @@ +/* + ChibiOS - Copyright (C) 2019 Diego Ismirlian (dismirlian(at)google's mail) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + .syntax unified + .cpu cortex-m4 + + .section .data._fault_stack + .align 3 +_fault_stack: + .skip 256 +_fault_stack_end: + + .thumb + + .section .text.HardFault_Handler + .thumb_func + .globl HardFault_Handler +HardFault_Handler: + /* disable further interrupts */ + cpsid i + + /* preserve the ISR sp for later */ + mov r1, sp + + /* set the sp to a separate stack, in case of sp corruption */ + ldr sp, .L1 + + /* preserve the ISR lr and sp for later */ + push {r1, lr} + + /* print info */ + bl _hardfault_info + + /* restore the sp and the lr */ + pop {r1, lr} + mov sp, r1 + + /* Try to rebuild the stack for the debugger. + * The idea is that the debugger will unwind the stack, and + * show a call to the HardFault_Handler from the offending + * instruction */ + + /* check which stack was in use */ + tst lr, #4 //check bit 2 of EXC_RETURN + ite eq + mrseq r0, msp + mrsne r0, psp //r0 points to the stack that was in use + + /* try to rebuild the stack for the debugger */ + mov sp, r0 //sp points to the end of the IRQ stack + /* check if FPU registers were stacked */ + tst lr, #16 //check bit 4 of EXC_RETURN + ite eq + addeq sp, #104 //jump over the IRQ+FPU stack + addne sp, #32 //jump over the IRQ stack + + /* compensate padding */ + ldr r1, [sp, #28] //r1 = stacked xPSR + tst r1, #512 //check bit 9 of the stacked xPSR + ite eq + addeq sp, #0 //add 0 to sp if there was no padding + addne sp, #4 //add 4 to sp if there was padding + /* here, sp finally points to the stack before the IRQ was triggered */ + + /* set lr to the stacked PC address, so the debugger can show where the + fault was produced (may not be accurate, depending on the fault) */ + ldr lr, [r0, #24] + + /* restore used registers */ + ldr r0, [r0, #0] + ldr r1, [r0, #4] + + b _hardfault_epilogue + + .align 2 +.L1: .word _fault_stack_end + + + .section .text._hardfault_exit + .thumb_func + .globl _hardfault_exit +_hardfault_exit: + /* we are here if there is no debugger attached */ + + /* restore the sp to the separate stack */ + ldr sp, .L3 + + /* call chSysHalt */ + ldr r0, =.L2 + bl chSysHalt + + b . + + .align 2 +.L3: .word _fault_stack_end + + .align 2 +.L2: .asciz "hard fault" + + .align 2 diff --git a/os/common/ports/ARMCMx/compilers/GCC/utils/port_fault_handlers.h b/os/common/ports/ARMCMx/compilers/GCC/utils/port_fault_handlers.h new file mode 100644 index 0000000..ca98459 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/utils/port_fault_handlers.h @@ -0,0 +1,52 @@ +/* + ChibiOS - Copyright (C) 2019 Diego Ismirlian (dismirlian(at)google's mail) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef FAULT_HANDLERS_v7m_H_ +#define FAULT_HANDLERS_v7m_H_ + +struct decoded_fault_registers { + struct general { + bool bus_fault_on_ivt_read; + bool escalation; + uint32_t current_thread_address; + const char *current_thread_name; + } general; + struct memfault { + bool stacking_error; + bool unstacking_error; + bool data_access_violation; + uint32_t data_access_violation_address; + bool instruction_access_violation; + } memfault; + struct busfault { + bool stacking_error; + bool unstacking_error; + bool precise_data_bus_error; + uint32_t precise_data_bus_error_address; + bool imprecise_data_bus_error; + bool instruction_bus_error; + } busfault; + struct usagefault { + bool division_by_zero; + bool unaligned_memory_access; + bool no_coprocessor_instructions; + bool invalid_load_of_pc; + bool invalid_state; + bool undefined_instruction; + } usagefault; +}; + +#endif /* FAULT_HANDLERS_v7m_H_ */ diff --git a/os/various/fault_handlers/fault_handlers.h b/os/various/fault_handlers/fault_handlers.h new file mode 100644 index 0000000..1fb210b --- /dev/null +++ b/os/various/fault_handlers/fault_handlers.h @@ -0,0 +1,22 @@ +#ifndef FAULT_HANDLERS_H_ +#define FAULT_HANDLERS_H_ + +#include +#include "port_fault_handlers.h" + +/* + * Notes: + * + * 1) #define FAULT_NO_PRINT to remove chprintf, etc + * 2) #define FAULT_INFO_HOOK(fault_info) to receive a struct fault_info when + * a fault is produced. + */ + +struct fault_info { + struct decoded_fault_registers decoded_fault_registers; +#ifndef FAULT_NO_PRINT + char decoded_info_string[300]; +#endif +}; + +#endif /* FAULT_HANDLERS_H_ */ -- cgit v1.2.3 From 1ca49e0b903954c1fd463d29e51faa22436fa33f Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Wed, 2 Oct 2019 15:18:08 -0300 Subject: Fault handlers: v7m: simplify --- os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c index 37b7fc7..587fce3 100644 --- a/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c +++ b/os/common/ports/ARMCMx/compilers/GCC/utils/fault_handlers_v7m.c @@ -131,10 +131,7 @@ static void _init_fault_info(void) { } static void _save_fault_info(void) { - memset(&fault_info.decoded_fault_registers, 0, sizeof(fault_info.decoded_fault_registers)); -#ifndef FAULT_NO_PRINT - memset(&fault_info.decoded_info_string, 0, sizeof(fault_info.decoded_info_string)); -#endif + memset(&fault_info, 0, sizeof(fault_info)); if (ch.rlist.current) { fault_printf("Thread: 0x%08x, %s", -- cgit v1.2.3 From fa3880546cc5fa933caa4333f1dbc397a93420b6 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 17:48:46 -0300 Subject: USBH: check remaining bytes before dereferencing buffer To avoid accessing unimplemented memory. We rely on the lazy evaluation of the C language. --- os/hal/src/usbh/hal_usbh_desciter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/os/hal/src/usbh/hal_usbh_desciter.c b/os/hal/src/usbh/hal_usbh_desciter.c index cfce62b..0ccf4e4 100644 --- a/os/hal/src/usbh/hal_usbh_desciter.c +++ b/os/hal/src/usbh/hal_usbh_desciter.c @@ -25,7 +25,7 @@ void cfg_iter_init(generic_iterator_t *icfg, const uint8_t *buff, uint16_t rem) { icfg->valid = 0; - if ((buff[0] < 2) || (rem < 2) || (rem < buff[0]) + if ((rem < 2) || (buff[0] < 2) || (rem < buff[0]) || (buff[0] < USBH_DT_CONFIG_SIZE) || (buff[1] != USBH_DT_CONFIG)) return; @@ -45,14 +45,14 @@ void if_iter_next(if_iterator_t *iif) { iif->valid = 0; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; for (;;) { rem -= curr[0]; curr += curr[0]; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; if (curr[1] == USBH_DT_INTERFACE_ASSOCIATION) { @@ -92,14 +92,14 @@ void ep_iter_next(generic_iterator_t *iep) { iep->valid = 0; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; for (;;) { rem -= curr[0]; curr += curr[0]; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION) @@ -131,13 +131,13 @@ void cs_iter_next(generic_iterator_t *ics) { ics->valid = 0; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; rem -= curr[0]; curr += curr[0]; - if ((curr[0] < 2) || (rem < 2) || (rem < curr[0])) + if ((rem < 2) || (curr[0] < 2) || (rem < curr[0])) return; if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION) -- cgit v1.2.3 From 392d6af30057db0b36ae02e5ca940691c382fd23 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 18:33:46 -0300 Subject: USBH: rework debug framework --- os/hal/include/hal_usbh.h | 40 +- os/hal/include/usbh/debug.h | 49 +- os/hal/include/usbh/debug_helpers.h | 163 +++++++ os/hal/include/usbh/dev/uvc.h | 4 +- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 215 ++++----- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h | 1 + os/hal/src/hal_usbh.c | 194 ++++---- os/hal/src/usbh/hal_usbh_aoa.c | 93 ++-- os/hal/src/usbh/hal_usbh_debug.c | 664 ++++++--------------------- os/hal/src/usbh/hal_usbh_ftdi.c | 91 ++-- os/hal/src/usbh/hal_usbh_hid.c | 59 +-- os/hal/src/usbh/hal_usbh_hub.c | 60 +-- os/hal/src/usbh/hal_usbh_msd.c | 143 +++--- os/hal/src/usbh/hal_usbh_uvc.c | 170 +++---- 14 files changed, 815 insertions(+), 1131 deletions(-) create mode 100644 os/hal/include/usbh/debug_helpers.h diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index aa49205..6e83a44 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -242,6 +242,31 @@ struct usbh_port { _usbh_port_ll_data }; + +#if USBH_DEBUG_ENABLE +struct usbh_dq { + int rem; + int sz; + uint8_t *first; + uint8_t *next; + uint8_t *start; + uint8_t *end; +}; + +typedef struct usbh_dq usbh_dq_t; + +struct usbh_debug_helper { + uint8_t buff[USBH_DEBUG_BUFFER]; + THD_WORKING_AREA(thd_wa, 512); + usbh_dq_t dq; + systime_t first; + systime_t last; + bool ena; + bool on; + thread_reference_t tr; +}; +#endif + struct USBHDriver { usbh_status_t status; uint8_t address_bitmap[(USBH_MAX_ADDRESSES + 7) / 8]; @@ -255,15 +280,16 @@ struct USBHDriver { /* Low level part */ _usbhdriver_ll_data -#if USBH_DEBUG_ENABLE +#if USBH_DEBUG_ENABLE && USBH_DEBUG_MULTI_HOST /* debug */ - uint8_t dbg_buff[USBH_DEBUG_BUFFER]; - THD_WORKING_AREA(waDebug, 512); - input_queue_t iq; + struct usbh_debug_helper debug; #endif }; - +#if USBH_DEBUG_ENABLE && !USBH_DEBUG_MULTI_HOST +/* debug */ +extern struct usbh_debug_helper usbh_debug; +#endif /*===========================================================================*/ /* External declarations. */ @@ -289,10 +315,10 @@ extern "C" { /* Device-related */ #if USBH_DEBUG_ENABLE && USBH_DEBUG_ENABLE_INFO void usbhDevicePrintInfo(usbh_device_t *dev); - void usbhDevicePrintConfiguration(const uint8_t *descriptor, uint16_t rem); + void usbhDevicePrintConfiguration(const usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); #else # define usbhDevicePrintInfo(dev) do {} while(0) -# define usbhDevicePrintConfiguration(descriptor, rem) do {} while(0) +# define usbhDevicePrintConfiguration(dev, descriptor, rem) do {} while(0) #endif bool usbhDeviceReadString(usbh_device_t *dev, char *dest, uint8_t size, uint8_t index, uint16_t langID); diff --git a/os/hal/include/usbh/debug.h b/os/hal/include/usbh/debug.h index 41319b9..f90a11a 100644 --- a/os/hal/include/usbh/debug.h +++ b/os/hal/include/usbh/debug.h @@ -24,18 +24,53 @@ #if HAL_USE_USBH #if USBH_DEBUG_ENABLE +#if USBH_DEBUG_MULTI_HOST + /* output callback */ + void USBH_DEBUG_OUTPUT_CALLBACK(USBHDriver *host, const uint8_t *buff, size_t len); + + /* printing functions */ + void usbDbgPrintf(USBHDriver *host, const char *fmt, ...); + void usbDbgPuts(USBHDriver *host, const char *s); + void usbDbgInit(USBHDriver *host); +#else + /* output callback */ + void USBH_DEBUG_OUTPUT_CALLBACK(const uint8_t *buff, size_t len); + + /* printing functions */ void usbDbgPrintf(const char *fmt, ...); void usbDbgPuts(const char *s); - void usbDbgInit(USBHDriver *host); + void usbDbgInit(void); +#endif + void usbDbgReset(void); - void usbDbgSystemHalted(void); #else -#define usbDbgPrintf(fmt, ...) do {} while(0) -#define usbDbgPuts(s) do {} while(0) -#define usbDbgInit(host) do {} while(0) -#define usbDbgReset() do {} while(0) -#define usbDbgSystemHalted() do {} while(0) + +#if USBH_DEBUG_MULTI_HOST +# define usbDbgPrintf(host, fmt, ...) do {} while(0) +# define usbDbgPuts(host, s) do {} while(0) +# define usbDbgInit(host) do {} while(0) +#else +# define usbDbgPrintf(fmt, ...) do {} while(0) +# define usbDbgPuts(s) do {} while(0) +# define usbDbgInit() do {} while(0) +#endif +# define usbDbgReset() do {} while(0) +#endif + +#if USBH_DEBUG_MULTI_HOST +#define _usbh_dbg(host, s) usbDbgPuts(host, s) +#define _usbh_dbgf(host, f, ...) usbDbgPrintf(host, f, ##__VA_ARGS__) +#define _usbh_ldbg(host, lvl, n, s) do {if (lvl >= n) usbDbgPuts(host, s); } while(0) +#define _usbh_ldbgf(host, lvl, n, f, ...) do {if (lvl >= n) usbDbgPrintf(host, f, ##__VA_ARGS__); } while(0) +#else + +#define _usbh_dbg(host, s) usbDbgPuts(s) +#define _usbh_dbgf(host, f, ...) usbDbgPrintf(f, ##__VA_ARGS__) +#define _usbh_ldbg(host, lvl, n, s) do {if (lvl >= n) usbDbgPuts(s); } while(0) +#define _usbh_ldbgf(host, lvl, n, f, ...) do {if (lvl >= n) usbDbgPrintf(f, ##__VA_ARGS__); } while(0) + #endif + #endif diff --git a/os/hal/include/usbh/debug_helpers.h b/os/hal/include/usbh/debug_helpers.h new file mode 100644 index 0000000..b09bd0a --- /dev/null +++ b/os/hal/include/usbh/debug_helpers.h @@ -0,0 +1,163 @@ +#ifndef USBH_INTERNAL_H_ +#error "Internal use only" +#endif + +#ifndef _USBH_DEBUG_HELPER_ENABLE_TRACE +#error "_USBH_DEBUG_HELPER_ENABLE_TRACE must be set" +#endif +#ifndef _USBH_DEBUG_HELPER_ENABLE_INFO +#error "_USBH_DEBUG_HELPER_ENABLE_INFO must be set" +#endif +#ifndef _USBH_DEBUG_HELPER_ENABLE_WARNINGS +#error "_USBH_DEBUG_HELPER_ENABLE_WARNINGS must be set" +#endif +#ifndef _USBH_DEBUG_HELPER_ENABLE_ERRORS +#error "_USBH_DEBUG_HELPER_ENABLE_ERRORS must be set" +#endif + +#define _usbh_dbg_host(s) _usbh_dbg(host, s) +#define _usbh_dbg_port(s) _usbh_dbg(port->device.host, s) +#define _usbh_dbg_dev(s) _usbh_dbg(dev->host, s) +#define _usbh_dbg_ep(lvl, s) _usbh_ldbg(ep->device->host, ep->trace_level, lvl, s) +#define _usbh_dbg_urb(lvl, s) _usbh_ldbg(urb->ep->device->host, urb->ep->trace_level, lvl, s) + +#define _usbh_dbgf_host(f, ...) _usbh_dbgf(host, f, ##__VA_ARGS__) +#define _usbh_dbgf_port(f, ...) _usbh_dbgf(port->device.host, f, ##__VA_ARGS__) +#define _usbh_dbgf_dev(f, ...) _usbh_dbgf(dev->host, f, ##__VA_ARGS__) +#define _usbh_dbgf_ep(f, lvl, ...) _usbh_ldbgf(ep->device->host, ep->trace_level, lvl, "\t%s: " f, ep->name, ##__VA_ARGS__) +#define _usbh_dbgf_urb(f, lvl, ...) _usbh_ldbgf(urb->ep->device->host, urb->ep->trace_level, lvl, "\t%s: " f, urb->ep->name, ##__VA_ARGS__) + +#if defined(_USBH_DEBUG_HELPER_CLASS_DRIVER) +#define _usbh_dbg_classdrv(drv, s) _usbh_dbg(drv->dev->host, s) +#define _usbh_dbgf_classdrv(drv, f, ...) _usbh_dbgf(drv->dev->host, f, ##__VA_ARGS__) +#endif + +#define _usbh_dbg_dummy do {} while(0) + +#if _USBH_DEBUG_HELPER_ENABLE_TRACE +#define udbg(s) _usbh_dbg_host(s) +#define uportdbg(s) _usbh_dbg_port(s) +#define udevdbg(s) _usbh_dbg_dev(s) +#define uepdbg(s) _usbh_dbg_ep(4, s) +#define uurbdbg(s) _usbh_dbg_urb(4, s) +#define udbgf(f, ...) _usbh_dbgf_host(f, ##__VA_ARGS__) +#define uportdbgf(f, ...) _usbh_dbgf_port(f, ##__VA_ARGS__) +#define udevdbgf(f, ...) _usbh_dbgf_dev(f, ##__VA_ARGS__) +#define uepdbgf(f, ...) _usbh_dbgf_ep(f, 4, ##__VA_ARGS__) +#define uurbdbgf(f, ...) _usbh_dbgf_urb(f, 4, ##__VA_ARGS__) +#else +#define udbg(s) _usbh_dbg_dummy +#define uportdbg(s) _usbh_dbg_dummy +#define udevdbg(s) _usbh_dbg_dummy +#define uurbdbg(s) _usbh_dbg_dummy +#define uepdbg(s) _usbh_dbg_dummy +#define udbgf(f, ...) _usbh_dbg_dummy +#define uportdbgf(f, ...) _usbh_dbg_dummy +#define udevdbgf(f, ...) _usbh_dbg_dummy +#define uepdbgf(f, ...) _usbh_dbg_dummy +#define uurbdbgf(f, ...) _usbh_dbg_dummy +#endif + +#if _USBH_DEBUG_HELPER_ENABLE_INFO +#define uinfo(s) _usbh_dbg_host(s) +#define uportinfo(s) _usbh_dbg_port(s) +#define udevinfo(s) _usbh_dbg_dev(s) +#define uepinfo(s) _usbh_dbg_ep(3, s) +#define uurbinfo(s) _usbh_dbg_urb(3, s) +#define uinfof(f, ...) _usbh_dbgf_host(f, ##__VA_ARGS__) +#define uportinfof(f, ...) _usbh_dbgf_port(f, ##__VA_ARGS__) +#define udevinfof(f, ...) _usbh_dbgf_dev(f, ##__VA_ARGS__) +#define uepinfof(f, ...) _usbh_dbgf_ep(f, 3, ##__VA_ARGS__) +#define uurbinfof(f, ...) _usbh_dbgf_urb(f, 3, ##__VA_ARGS__) +#else +#define uinfo(s) _usbh_dbg_dummy +#define udevinfo(s) _usbh_dbg_dummy +#define uportinfo(s) _usbh_dbg_dummy +#define uepinfo(s) _usbh_dbg_dummy +#define uurbinfo(s) _usbh_dbg_dummy +#define uinfof(f, ...) _usbh_dbg_dummy +#define uportinfof(f, ...) _usbh_dbg_dummy +#define udevinfof(f, ...) _usbh_dbg_dummy +#define uepinfof(f, ...) _usbh_dbg_dummy +#define uurbinfof(f, ...) _usbh_dbg_dummy +#endif + +#if _USBH_DEBUG_HELPER_ENABLE_WARNINGS +#define uwarn(s) _usbh_dbg_host(s) +#define uportwarn(s) _usbh_dbg_port(s) +#define udevwarn(s) _usbh_dbg_dev(s) +#define uepwarn(s) _usbh_dbg_ep(3, s) +#define uurbwarn(s) _usbh_dbg_urb(3, s) +#define uwarnf(f, ...) _usbh_dbgf_host(f, ##__VA_ARGS__) +#define uportwarnf(f, ...) _usbh_dbgf_port(f, ##__VA_ARGS__) +#define udevwarnf(f, ...) _usbh_dbgf_dev(f, ##__VA_ARGS__) +#define uepwarnf(f, ...) _usbh_dbgf_ep(f, 3, ##__VA_ARGS__) +#define uurbwarnf(f, ...) _usbh_dbgf_urb(f, 3, ##__VA_ARGS__) +#else +#define uwarn(s) _usbh_dbg_dummy +#define udevwarn(s) _usbh_dbg_dummy +#define uportwarn(s) _usbh_dbg_dummy +#define uepwarn(s) _usbh_dbg_dummy +#define uurbwarn(s) _usbh_dbg_dummy +#define uwarnf(f, ...) _usbh_dbg_dummy +#define uportwarnf(f, ...) _usbh_dbg_dummy +#define udevwarnf(f, ...) _usbh_dbg_dummy +#define uepwarnf(f, ...) _usbh_dbg_dummy +#define uurbwarnf(f, ...) _usbh_dbg_dummy +#endif + + +#if _USBH_DEBUG_HELPER_ENABLE_ERRORS +#define uerr(s) _usbh_dbg_host(s) +#define uporterr(s) _usbh_dbg_port(s) +#define udeverr(s) _usbh_dbg_dev(s) +#define ueperr(s) _usbh_dbg_ep(3, s) +#define uurberr(s) _usbh_dbg_urb(3, s) +#define uerrf(f, ...) _usbh_dbgf_host(f, ##__VA_ARGS__) +#define uporterrf(f, ...) _usbh_dbgf_port(f, ##__VA_ARGS__) +#define udeverrf(f, ...) _usbh_dbgf_dev(f, ##__VA_ARGS__) +#define ueperrf(f, ...) _usbh_dbgf_ep(f, 3, ##__VA_ARGS__) +#define uurberrf(f, ...) _usbh_dbgf_urb(f, 3, ##__VA_ARGS__) +#else +#define uerr(s) _usbh_dbg_dummy +#define udeverr(s) _usbh_dbg_dummy +#define uporterr(s) _usbh_dbg_dummy +#define ueperr(s) _usbh_dbg_dummy +#define uurberr(s) _usbh_dbg_dummy +#define uerrf(f, ...) _usbh_dbg_dummy +#define uporterrf(f, ...) _usbh_dbg_dummy +#define udeverrf(f, ...) _usbh_dbg_dummy +#define ueperrf(f, ...) _usbh_dbg_dummy +#define uurberrf(f, ...) _usbh_dbg_dummy +#endif + +#if defined(_USBH_DEBUG_HELPER_CLASS_DRIVER) +#if _USBH_DEBUG_HELPER_ENABLE_TRACE +#define uclassdrvdbg(s) _usbh_dbg_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, s) +#define uclassdrvdbgf(f, ...) _usbh_dbgf_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, f, ##__VA_ARGS__) +#else +#define uclassdrvdbg(s) _usbh_dbg_dummy +#define uclassdrvdbgf(f, ...) _usbh_dbg_dummy +#endif +#if _USBH_DEBUG_HELPER_ENABLE_INFO +#define uclassdrvinfo(s) _usbh_dbg_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, s) +#define uclassdrvinfof(f, ...) _usbh_dbgf_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, f, ##__VA_ARGS__) +#else +#define uclassdrvinfo(s) _usbh_dbg_dummy +#define uclassdrvinfof(f, ...) _usbh_dbg_dummy +#endif +#if _USBH_DEBUG_HELPER_ENABLE_WARNINGS +#define uclassdrvwarn(s) _usbh_dbg_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, s) +#define uclassdrvwarnf(f, ...) _usbh_dbgf_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, f, ##__VA_ARGS__) +#else +#define uclassdrvwarn(s) _usbh_dbg_dummy +#define uclassdrvwarnf(f, ...) _usbh_dbg_dummy +#endif +#if _USBH_DEBUG_HELPER_ENABLE_ERRORS +#define uclassdrverr(s) _usbh_dbg_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, s) +#define uclassdrverrf(f, ...) _usbh_dbgf_classdrv(_USBH_DEBUG_HELPER_CLASS_DRIVER, f, ##__VA_ARGS__) +#else +#define uclassdrverr(s) _usbh_dbg_dummy +#define uclassdrverrf(f, ...) _usbh_dbg_dummy +#endif +#endif diff --git a/os/hal/include/usbh/dev/uvc.h b/os/hal/include/usbh/dev/uvc.h index 713d16c..7116c91 100644 --- a/os/hal/include/usbh/dev/uvc.h +++ b/os/hal/include/usbh/dev/uvc.h @@ -408,9 +408,9 @@ extern "C" { const uint8_t *framedesc, uint32_t dwFrameInterval); #if USBH_DEBUG_ENABLE && USBHUVC_DEBUG_ENABLE_INFO - void usbhuvcPrintProbeCommit(const usbh_uvc_ctrl_vs_probecommit_data_t *pc); + void usbhuvcPrintProbeCommit(USBHUVCDriver *uvcdp, const usbh_uvc_ctrl_vs_probecommit_data_t *pc); #else -# define usbhuvcPrintProbeCommit(pc) do {} while(0) +# define usbhuvcPrintProbeCommit(uvcdp, pc) do {} while(0) #endif bool usbhuvcProbe(USBHUVCDriver *uvcdp); bool usbhuvcCommit(USBHUVCDriver *uvcdp); diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index 787a831..2066b60 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -67,38 +67,11 @@ #endif #endif - -#if USBH_LLD_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBH_LLD_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBH_LLD_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBH_LLD_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBH_LLD_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBH_LLD_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBH_LLD_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBH_LLD_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" static void _transfer_completedI(usbh_ep_t *ep, usbh_urb_t *urb, usbh_urbstatus_t status); static void _try_commit_np(USBHDriver *host); @@ -161,7 +134,10 @@ static void _halt_channel(USBHDriver *host, stm32_hc_management_t *hcm, usbh_lld (void)host; if (hcm->halt_reason != USBH_LLD_HALTREASON_NONE) { - uwarnf("\t%s: Repeated halt (original=%d, new=%d)", hcm->ep->name, hcm->halt_reason, reason); +#if USBH_DEBUG_ENABLE && USBH_LLD_DEBUG_ENABLE_WARNINGS + usbh_ep_t *const ep = hcm->ep; + uepwarnf("Repeated halt (original=%d, new=%d)", hcm->halt_reason, reason); +#endif return; } @@ -178,17 +154,20 @@ static void _halt_channel(USBHDriver *host, stm32_hc_management_t *hcm, usbh_lld } static void _release_channel(USBHDriver *host, stm32_hc_management_t *hcm) { -// static const char *reason[] = {"XFRC", "XFRC", "NAK", "STALL", "ERROR", "ABORT"}; -// udbgf("\t%s: release (%s)", hcm->ep->name, reason[hcm->halt_reason]); + usbh_ep_t *const ep = hcm->ep; +#if USBH_DEBUG_ENABLE && USBH_LLD_DEBUG_ENABLE_TRACE + static const char *reason[] = {"XFRC", "XFRC", "NAK", "STALL", "ERROR", "ABORT"}; + uepdbgf("release (%s)", reason[hcm->halt_reason]); +#endif hcm->hc->HCINTMSK = 0; host->otg->HAINTMSK &= ~hcm->haintmsk; hcm->halt_reason = USBH_LLD_HALTREASON_NONE; - if (usbhEPIsPeriodic(hcm->ep)) { + if (usbhEPIsPeriodic(ep)) { list_add(&hcm->node, &host->ch_free[0]); } else { list_add(&hcm->node, &host->ch_free[1]); } - hcm->ep->xfer.hcm = 0; + ep->xfer.hcm = 0; hcm->ep = 0; } @@ -207,12 +186,12 @@ static bool _activate_ep(USBHDriver *host, usbh_ep_t *ep) { } if (list_empty(list)) { - uwarnf("\t%s: No free %s channels", ep->name, usbhEPIsPeriodic(ep) ? "P" : "NP"); + uepwarnf("No free %s channels", usbhEPIsPeriodic(ep) ? "P" : "NP"); return FALSE; } if (spc <= STM32_USBH_MIN_QSPACE) { - uwarnf("\t%s: No space in %s Queue (spc=%d)", ep->name, usbhEPIsPeriodic(ep) ? "P" : "NP", spc); + uepwarnf("No space in %s Queue (spc=%d)", usbhEPIsPeriodic(ep) ? "P" : "NP", spc); return FALSE; } @@ -332,15 +311,15 @@ static bool _activate_ep(USBHDriver *host, usbh_ep_t *ep) { if (--spc > STM32_USBH_MIN_QSPACE) { hc->HCCHAR |= HCCHAR_CHENA; } else { - uwarnf("\t%s: Could not queue back-to-back packets", ep->name); + uepwarnf("Could not queue back-to-back packets"); } } if (urb->queued == FALSE) { urb->queued = TRUE; - udbgf("\t%s: Start (%dB)", ep->name, xfer_len); + uepdbgf("Start (%dB)", xfer_len); } else { - udbgf("\t%s: Restart (%dB)", ep->name, xfer_len); + uepdbgf("Restart (%dB)", xfer_len); } ep->xfer.len = xfer_len; @@ -387,7 +366,7 @@ static bool _update_urb(usbh_ep_t *ep, uint32_t hctsiz, usbh_urb_t *urb, bool co osalDbgAssert(urb->actualLength + len <= urb->requestedLength, "what happened?"); #else if (urb->actualLength + len > urb->requestedLength) { - uerrf("\t%s: Trimming actualLength %u -> %u", ep->name, urb->actualLength + len, urb->requestedLength); + ueperrf("Trimming actualLength %u -> %u", urb->actualLength + len, urb->requestedLength); urb->actualLength = urb->requestedLength; return TRUE; } @@ -449,9 +428,9 @@ static void _purge_queue(USBHDriver *host, struct list_head *list) { list_for_each_entry_safe(ep, usbh_ep_t, tmp, list, node) { usbh_urb_t *const urb = _active_urb(ep); stm32_hc_management_t *const hcm = ep->xfer.hcm; - uwarnf("\t%s: Abort URB, USBH_URBSTATUS_DISCONNECTED", ep->name); + uepwarnf("Abort URB, USBH_URBSTATUS_DISCONNECTED"); if (hcm) { - uwarnf("\t%s: URB had channel %d assigned, halt_reason = %d", ep->name, hcm - host->channels, hcm->halt_reason); + uepwarnf("URB had channel %d assigned, halt_reason = %d", hcm - host->channels, hcm->halt_reason); _release_channel(host, hcm); _update_urb(ep, hcm->hc->HCTSIZ, urb, FALSE); } @@ -514,7 +493,7 @@ static uint32_t _write_packet(struct list_head *list, uint32_t space_available) volatile uint32_t *dest = ep->xfer.hcm->fifo; uint32_t *src = (uint32_t *)ep->xfer.buf; - udbgf("\t%s: write %d words (%dB), partial=%d", ep->name, words, written, ep->xfer.partial); + uepdbgf("write %d words (%dB), partial=%d", words, written, ep->xfer.partial); while (words--) { *dest = *src++; } @@ -589,19 +568,19 @@ void usbh_lld_ep_object_init(usbh_ep_t *ep) { } void usbh_lld_ep_open(usbh_ep_t *ep) { - uinfof("\t%s: Open EP", ep->name); + uepinfof("Open EP"); ep->status = USBH_EPSTATUS_OPEN; } void usbh_lld_ep_close(usbh_ep_t *ep) { usbh_urb_t *urb; - uinfof("\t%s: Closing EP...", ep->name); + uepinfof("Closing EP..."); while (!list_empty(&ep->urb_list)) { urb = list_first_entry(&ep->urb_list, usbh_urb_t, node); - uinfof("\t%s: Abort URB, USBH_URBSTATUS_DISCONNECTED", ep->name); + uepinfof("Abort URB, USBH_URBSTATUS_DISCONNECTED"); _usbh_urb_abort_and_waitS(urb, USBH_URBSTATUS_DISCONNECTED); } - uinfof("\t%s: Closed", ep->name); + uepinfof("Closed"); ep->status = USBH_EPSTATUS_CLOSED; } @@ -615,7 +594,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) { USBHDriver *const host = ep->device->host; if (!(host->otg->HPRT & HPRT_PENA)) { - uwarnf("\t%s: Can't submit URB, port disabled", ep->name); + uepwarnf("Can't submit URB, port disabled"); _usbh_urb_completeI(urb, USBH_URBSTATUS_DISCONNECTED); return; } @@ -651,20 +630,20 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { if (hcm->halt_reason == USBH_LLD_HALTREASON_NONE) { /* The channel is not being halted */ - uinfof("\t%s: usbh_lld_urb_abort: channel is not being halted", hcm->ep->name); + uepinfof("usbh_lld_urb_abort: channel is not being halted"); urb->status = status; _halt_channel(ep->device->host, hcm, USBH_LLD_HALTREASON_ABORT); } else { /* The channel is being halted, so we can't re-halt it. The CHH interrupt will * be in charge of completing the transfer, but the URB will not have the specified status. */ - uinfof("\t%s: usbh_lld_urb_abort: channel is being halted", hcm->ep->name); + uepinfof("usbh_lld_urb_abort: channel is being halted"); } return FALSE; } /* This URB is inactive, we can cancel it now */ - uinfof("\t%s: usbh_lld_urb_abort: URB is not active", ep->name); + uepinfof("usbh_lld_urb_abort: URB is not active"); _transfer_completedI(ep, urb, status); return TRUE; @@ -679,94 +658,103 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { // si si si si si si no no ep->type != ISO && !ep->in static inline void _ack_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { (void)host; - osalDbgAssert(hcm->ep->type != USBH_EPTYPE_ISO, "ACK should not happen in ISO endpoints"); - hcm->ep->xfer.error_count = 0; + usbh_ep_t *const ep = hcm->ep; + osalDbgAssert(ep->type != USBH_EPTYPE_ISO, "ACK should not happen in ISO endpoints"); + ep->xfer.error_count = 0; hc->HCINTMSK &= ~HCINTMSK_ACKM; - udbgf("\t%s: ACK", hcm->ep->name); + uepdbgf("ACK"); } //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) // si no si no si no no no ep->type != ISO && ep->in static inline void _dterr_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { (void)host; - osalDbgAssert(hcm->ep->in && (hcm->ep->type != USBH_EPTYPE_ISO), "DTERR should not happen in OUT or ISO endpoints"); + usbh_ep_t *const ep = hcm->ep; + osalDbgAssert(ep->in && (ep->type != USBH_EPTYPE_ISO), "DTERR should not happen in OUT or ISO endpoints"); #if 0 hc->HCINTMSK &= ~(HCINTMSK_DTERRM | HCINTMSK_ACKM); - hcm->ep->xfer.error_count = 0; + ep->xfer.error_count = 0; _halt_channel(host, hcm, USBH_LLD_HALTREASON_ERROR); #else /* restart directly, no need to halt it in this case */ - hcm->ep->xfer.error_count = 0; + ep->xfer.error_count = 0; hc->HCINTMSK &= ~HCINTMSK_ACKM; hc->HCCHAR |= HCCHAR_CHENA; #endif - uerrf("\t%s: DTERR", hcm->ep->name); + ueperrf("DTERR"); } //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) // si no si no si no si no ep->in static inline void _bberr_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { - osalDbgAssert(hcm->ep->in, "BBERR should not happen in OUT endpoints"); + usbh_ep_t *const ep = hcm->ep; + osalDbgAssert(ep->in, "BBERR should not happen in OUT endpoints"); hc->HCINTMSK &= ~HCINTMSK_BBERRM; - hcm->ep->xfer.error_count = 3; + ep->xfer.error_count = 3; _halt_channel(host, hcm, USBH_LLD_HALTREASON_ERROR); - uerrf("\t%s: BBERR", hcm->ep->name); + ueperrf("BBERR"); } ///CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) // si si si si si si si no ep->type != ISO || ep->in static inline void _trerr_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { - osalDbgAssert(hcm->ep->in || (hcm->ep->type != USBH_EPTYPE_ISO), "TRERR should not happen in ISO OUT endpoints"); + usbh_ep_t *const ep = hcm->ep; + osalDbgAssert(ep->in || (ep->type != USBH_EPTYPE_ISO), "TRERR should not happen in ISO OUT endpoints"); hc->HCINTMSK &= ~HCINTMSK_TRERRM; - ++hcm->ep->xfer.error_count; + ++ep->xfer.error_count; _halt_channel(host, hcm, USBH_LLD_HALTREASON_ERROR); - uerrf("\t%s: TRERR", hcm->ep->name); + ueperrf("TRERR"); } //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) // no no si si no no si si ep->type = PERIODIC static inline void _frmor_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { - osalDbgAssert(usbhEPIsPeriodic(hcm->ep), "FRMOR should not happen in non-periodic endpoints"); + usbh_ep_t *const ep = hcm->ep; + osalDbgAssert(usbhEPIsPeriodic(ep), "FRMOR should not happen in non-periodic endpoints"); hc->HCINTMSK &= ~HCINTMSK_FRMORM; - hcm->ep->xfer.error_count = 3; + ep->xfer.error_count = 3; _halt_channel(host, hcm, USBH_LLD_HALTREASON_ERROR); - uerrf("\t%s: FRMOR", hcm->ep->name); + ueperrf("FRMOR"); } //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) // si si si si si si no no ep->type != ISO static inline void _nak_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { + usbh_ep_t *const ep = hcm->ep; osalDbgAssert(hcm->ep->type != USBH_EPTYPE_ISO, "NAK should not happen in ISO endpoints"); - if (!hcm->ep->in || (hcm->ep->type == USBH_EPTYPE_INT)) { + if (!ep->in || (ep->type == USBH_EPTYPE_INT)) { hc->HCINTMSK &= ~HCINTMSK_NAKM; _halt_channel(host, hcm, USBH_LLD_HALTREASON_NAK); } else { /* restart directly, no need to halt it in this case */ - hcm->ep->xfer.error_count = 0; + ep->xfer.error_count = 0; hc->HCINTMSK &= ~HCINTMSK_ACKM; hc->HCCHAR |= HCCHAR_CHENA; } - udbgf("\t%s: NAK", hcm->ep->name); + uepdbgf("NAK"); } //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) -// si sólo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP) +// si solo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP) static inline void _stall_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_otg_host_chn_t *hc) { osalDbgAssert(hcm->ep->type != USBH_EPTYPE_ISO, "STALL should not happen in ISO endpoints"); hc->HCINTMSK &= ~HCINTMSK_STALLM; _halt_channel(host, hcm, USBH_LLD_HALTREASON_STALL); - uwarnf("\t%s: STALL", hcm->ep->name); +#if USBH_DEBUG_ENABLE && USBH_LLD_DEBUG_ENABLE_WARNINGS + usbh_ep_t *const ep = hcm->ep; + uepwarnf("STALL"); +#endif } static void _complete_bulk_int(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_t *ep, usbh_urb_t *urb, uint32_t hctsiz) { _release_channel(host, hcm); _save_dt_mask(ep, hctsiz); if (_update_urb(ep, hctsiz, urb, TRUE)) { - udbgf("\t%s: done", ep->name); + uepdbgf("done"); _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } else { osalDbgCheck(urb->requestedLength > 0x7FFFF); - uwarnf("\t%s: incomplete", ep->name); + uepwarnf("incomplete"); _move_to_pending_queue(ep); } if (usbhEPIsPeriodic(ep)) { @@ -782,18 +770,18 @@ static void _complete_control(USBHDriver *host, stm32_hc_management_t *hcm, usbh _release_channel(host, hcm); if (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_DATA) { if (_update_urb(ep, hctsiz, urb, TRUE)) { - udbgf("\t%s: DATA done", ep->name); + uepdbgf("DATA done"); ep->xfer.u.ctrl_phase = USBH_LLD_CTRLPHASE_STATUS; ep->in = !ep->in; } else { osalDbgCheck(urb->requestedLength > 0x7FFFF); - uwarnf("\t%s: DATA incomplete", ep->name); + uepwarnf("DATA incomplete"); _save_dt_mask(ep, hctsiz); } _move_to_pending_queue(ep); } else { osalDbgCheck(ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_STATUS); - udbgf("\t%s: STATUS done", ep->name); + uepdbgf("STATUS done"); _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } _try_commit_np(host); @@ -802,13 +790,13 @@ static void _complete_control(USBHDriver *host, stm32_hc_management_t *hcm, usbh static void _complete_control_setup(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_t *ep, usbh_urb_t *urb) { _release_channel(host, hcm); if (urb->requestedLength) { - udbgf("\t%s: SETUP done -> DATA", ep->name); + uepdbgf("SETUP done -> DATA"); ep->xfer.u.ctrl_phase = USBH_LLD_CTRLPHASE_DATA; ep->in = *((uint8_t *)urb->setup_buff) & 0x80 ? TRUE : FALSE; ep->dt_mask = HCTSIZ_DPID_DATA1; ep->xfer.error_count = 0; } else { - udbgf("\t%s: SETUP done -> STATUS", ep->name); + uepdbgf("SETUP done -> STATUS"); ep->in = TRUE; ep->xfer.u.ctrl_phase = USBH_LLD_CTRLPHASE_STATUS; } @@ -817,7 +805,7 @@ static void _complete_control_setup(USBHDriver *host, stm32_hc_management_t *hcm } static void _complete_iso(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_t *ep, usbh_urb_t *urb, uint32_t hctsiz) { - udbgf("\t%s: done", hcm->ep->name); + uepdbgf("done"); _release_channel(host, hcm); _update_urb(ep, hctsiz, urb, TRUE); _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); @@ -915,7 +903,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ case USBH_LLD_HALTREASON_STALL: if (ep->type == USBH_EPTYPE_CTRL) { if (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_SETUP) { - uerrf("\t%s: Faulty device: STALLed SETUP phase", ep->name); + ueperrf("Faulty device: STALLed SETUP phase"); } } else { ep->status = USBH_EPSTATUS_HALTED; @@ -927,13 +915,13 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ if ((ep->type == USBH_EPTYPE_ISO) || done || (ep->xfer.error_count >= 3)) { _transfer_completedI(ep, urb, USBH_URBSTATUS_ERROR); } else { - uerrf("\t%s: err=%d, done=%d, retry", ep->name, ep->xfer.error_count, done); + ueperrf("err=%d, done=%d, retry", ep->xfer.error_count, done); _move_to_pending_queue(ep); } break; case USBH_LLD_HALTREASON_ABORT: - uwarnf("\t%s: Abort", ep->name); + uepwarnf("Abort"); _transfer_completedI(ep, urb, urb->status); break; @@ -1094,8 +1082,7 @@ static inline void _rxflvl_int(USBHDriver *host) { hcm->hc->HCCHAR |= HCCHAR_CHENA; } - udbgf("\t%s: RXFLVL rx=%dB, rem=%dB (%dpkts)", - ep->name, + uepdbgf("RXFLVL rx=%dB, rem=%dB (%dpkts)", (grxstsp & GRXSTSP_BCNT_MASK) >> 4, (hctsiz & HCTSIZ_XFRSIZ_MASK), (hctsiz & HCTSIZ_PKTCNT_MASK) >> 19); @@ -1131,7 +1118,7 @@ static inline void _rxflvl_int(USBHDriver *host) { uint32_t pkt = (hctsiz & HCTSIZ_PKTCNT_MASK) >> 19; uint32_t siz = (hctsiz & HCTSIZ_XFRSIZ_MASK); if (pkt * ep->wMaxPacketSize != siz) { - uerrf("\t%s: whatttt???", ep->name); + ueperrf("whatttt???"); } } #endif @@ -1479,13 +1466,13 @@ void usbh_lld_init(void) { #endif } -static void _usbh_start(USBHDriver *usbh) { - stm32_otg_t *const otgp = usbh->otg; +static void _usbh_start(USBHDriver *host) { + stm32_otg_t *const otgp = host->otg; /* Clock activation.*/ #if STM32_USBH_USE_OTG1 #if STM32_USBH_USE_OTG2 - if (&USBHD1 == usbh) + if (&USBHD1 == host) #endif { /* OTG FS clock enable and reset.*/ @@ -1501,7 +1488,7 @@ static void _usbh_start(USBHDriver *usbh) { #if STM32_USBH_USE_OTG2 #if STM32_USBH_USE_OTG1 - if (&USBHD2 == usbh) + if (&USBHD2 == host) #endif { /* OTG HS clock enable and reset.*/ @@ -1518,7 +1505,7 @@ static void _usbh_start(USBHDriver *usbh) { otgp->GUSBCFG = GUSBCFG_PHYSEL | GUSBCFG_TRDT(5); - otg_core_reset(usbh); + otg_core_reset(host); otgp->GCCFG = GCCFG_PWRDWN; @@ -1553,28 +1540,28 @@ static void _usbh_start(USBHDriver *usbh) { otgp->HPRT |= HPRT_PPWR; - otg_txfifo_flush(usbh, 0x10); - otg_rxfifo_flush(usbh); + otg_txfifo_flush(host, 0x10); + otg_rxfifo_flush(host); otgp->GINTSTS = 0xffffffff; otgp->GINTMSK = GINTMSK_DISCM | GINTMSK_HPRTM | GINTMSK_MMISM; - usbh->rootport.lld_status = USBH_PORTSTATUS_POWER; - usbh->rootport.lld_c_status = 0; + host->rootport.lld_status = USBH_PORTSTATUS_POWER; + host->rootport.lld_c_status = 0; /* Global interrupts enable.*/ otgp->GAHBCFG |= GAHBCFG_GINTMSK; } -void usbh_lld_start(USBHDriver *usbh) { - if (usbh->status != USBH_STATUS_STOPPED) return; - _usbh_start(usbh); +void usbh_lld_start(USBHDriver *host) { + if (host->status != USBH_STATUS_STOPPED) return; + _usbh_start(host); } /*===========================================================================*/ /* Root Hub request handler. */ /*===========================================================================*/ -usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestType, uint8_t bRequest, +usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *host, uint8_t bmRequestType, uint8_t bRequest, uint16_t wvalue, uint16_t windex, uint16_t wlength, uint8_t *buf) { uint16_t typereq = (bmRequestType << 8) | bRequest; @@ -1606,23 +1593,23 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case USBH_PORT_FEAT_C_CONNECTION: - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; break; case USBH_PORT_FEAT_C_RESET: - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_RESET; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_RESET; break; case USBH_PORT_FEAT_C_ENABLE: - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_ENABLE; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_ENABLE; break; case USBH_PORT_FEAT_C_SUSPEND: - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_SUSPEND; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_SUSPEND; break; case USBH_PORT_FEAT_C_OVERCURRENT: - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; break; default: @@ -1645,7 +1632,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy osalDbgAssert(windex == 1, "invalid windex"); osalDbgCheck(wlength >= 4); osalSysLock(); - *(uint32_t *)buf = usbh->rootport.lld_status | (usbh->rootport.lld_c_status << 16); + *(uint32_t *)buf = host->rootport.lld_status | (host->rootport.lld_c_status << 16); osalSysUnlock(); break; @@ -1665,7 +1652,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy case USBH_PORT_FEAT_RESET: { osalSysLock(); - stm32_otg_t *const otg = usbh->otg; + stm32_otg_t *const otg = host->otg; uint32_t hprt; otg->PCGCCTL = 0; hprt = otg->HPRT; @@ -1675,14 +1662,14 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy uerr("Detected enabled port; resetting OTG core"); otg->GAHBCFG = 0; osalThreadSleepS(OSAL_MS2I(20)); - _usbh_start(usbh); /* this effectively resets the core */ + _usbh_start(host); /* this effectively resets the core */ osalThreadSleepS(OSAL_MS2I(100)); /* during this delay, the core generates connect ISR */ uinfo("OTG reset ended"); if (otg->HPRT & HPRT_PCSTS) { /* if the device is still connected, don't report a C_CONNECTION flag, which would cause * the upper layer to abort enumeration */ uinfo("Clear connection change flag"); - usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + host->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; } } /* note: writing PENA = 1 actually disables the port */ @@ -1692,7 +1679,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy osalThreadSleepS(OSAL_MS2I(15)); otg->HPRT = hprt; osalThreadSleepS(OSAL_MS2I(10)); - usbh->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET; + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET; osalSysUnlock(); } break; @@ -1714,8 +1701,8 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy return USBH_URBSTATUS_OK; } -uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh) { - return usbh->rootport.lld_c_status ? (1 << 1) : 0; +uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *host) { + return host->rootport.lld_c_status ? (1 << 1) : 0; } #endif diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h index bb92ede..7e0c1b6 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h @@ -83,6 +83,7 @@ typedef struct stm32_hc_management { uint32_t hcintmsk; \ uint32_t hcchar; \ uint32_t dt_mask; /* data-toggle mask */ \ + int32_t trace_level; /* enable tracing */ \ /* current transfer */ \ struct { \ stm32_hc_management_t *hcm; /* assigned channel */ \ diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index feaf956..2b9ae7c 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -23,36 +23,15 @@ #include "usbh/dev/hub.h" #include -#if USBH_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBH_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBH_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBH_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBH_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBH_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBH_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBH_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" + +#if USBH_DEBUG_ENABLE && !USBH_DEBUG_MULTI_HOST +/* debug */ +struct usbh_debug_helper usbh_debug; #endif static void _classdriver_process_device(usbh_device_t *dev); @@ -104,7 +83,11 @@ void usbhObjectInit(USBHDriver *usbh) { } void usbhStart(USBHDriver *usbh) { +#if USBH_DEBUG_MULTI_HOST usbDbgInit(usbh); +#else + usbDbgInit(); +#endif osalSysLock(); osalDbgAssert((usbh->status == USBH_STATUS_STOPPED) || (usbh->status == USBH_STATUS_STARTED), @@ -264,7 +247,7 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status) { _check_urb(urb); if (_usbh_urb_abortI(urb, status) == FALSE) { - uwarn("URB wasn't aborted immediately, suspend"); + uurbwarn("URB wasn't aborted immediately, suspend"); osalThreadSuspendS(&urb->abortingThread); osalDbgAssert(urb->abortingThread == 0, "maybe we should uncomment the line below"); //urb->abortingThread = 0; @@ -272,7 +255,7 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status) { /* This call is necessary because _usbh_urb_abortI may require a reschedule */ osalOsRescheduleS(); } - uwarn("URB aborted"); + uurbwarn("URB aborted"); } /* usbhURBCancelI may require a reschedule if called from a S-locked state */ @@ -607,26 +590,26 @@ static bool _device_set_configuration(usbh_device_t *dev, uint8_t configuration) static bool _device_configure(usbh_device_t *dev, uint8_t bConfiguration) { uint8_t i; - uinfof("Reading basic configuration descriptor %d", bConfiguration); + udevinfof("Reading basic configuration descriptor %d", bConfiguration); for (i = 0; i < 3; i++) { if (!_device_read_basic_cfgdesc(dev, bConfiguration)) break; } if (i == 3) { - uerrf("Could not read basic configuration descriptor %d; " + udeverrf("Could not read basic configuration descriptor %d; " "won't configure device", bConfiguration); return HAL_FAILED; } - uinfof("Selecting configuration %d", bConfiguration); + udevinfof("Selecting configuration %d", bConfiguration); for (i = 0; i < 3; i++) { if (!_device_set_configuration(dev, dev->basicConfigDesc.bConfigurationValue)) { /* TODO: check if correctly configured using GET_CONFIGURATION */ dev->status = USBH_DEVSTATUS_CONFIGURED; dev->bConfiguration = bConfiguration; - uinfo("Device configured."); + udevinfo("Device configured."); return HAL_SUCCESS; } } @@ -636,16 +619,16 @@ static bool _device_configure(usbh_device_t *dev, uint8_t bConfiguration) { static bool _device_enumerate(usbh_device_t *dev) { - uinfo("Enumerate."); - uinfo("Get first 8 bytes of device descriptor"); + udevinfo("Enumerate."); + udevinfo("Get first 8 bytes of device descriptor"); /* get first 8 bytes of device descriptor */ if (usbhStdReqGetDeviceDescriptor(dev, 8, (uint8_t *)&dev->devDesc)) { - uerr("Error"); + udeverr("Error"); return HAL_FAILED; } - uinfof("Configure bMaxPacketSize0 = %d", dev->devDesc.bMaxPacketSize0); + udevinfof("Configure bMaxPacketSize0 = %d", dev->devDesc.bMaxPacketSize0); /* configure EP0 wMaxPacketSize */ usbhEPClose(&dev->ctrl); _ep0_object_init(dev, dev->devDesc.bMaxPacketSize0); @@ -653,14 +636,14 @@ static bool _device_enumerate(usbh_device_t *dev) { uint8_t addr = _find_address(dev->host); if (addr == 0) { - uerr("No free addresses found"); + udeverr("No free addresses found"); return HAL_FAILED; } /* set device address */ - uinfof("Set device address: %d", addr); + udevinfof("Set device address: %d", addr); if (_device_setaddress(dev, addr)) { - uerr("Error"); + udeverr("Error"); _free_address(dev->host, addr); return HAL_FAILED; } @@ -670,23 +653,23 @@ static bool _device_enumerate(usbh_device_t *dev) { _ep0_object_init(dev, dev->devDesc.bMaxPacketSize0); usbhEPOpen(&dev->ctrl); - uinfof("Wait stabilization..."); + udevinfof("Wait stabilization..."); osalThreadSleepMilliseconds(HAL_USBH_DEVICE_ADDRESS_STABILIZATION); /* address is set */ dev->status = USBH_DEVSTATUS_ADDRESS; - uinfof("Get full device desc"); + udevinfof("Get full device desc"); /* get full device descriptor */ if (usbhStdReqGetDeviceDescriptor(dev, sizeof(dev->devDesc), (uint8_t *)&dev->devDesc)) { - uerr("Error"); + udeverr("Error"); _device_setaddress(dev, 0); _free_address(dev->host, addr); return HAL_FAILED; } - uinfof("Enumeration finished."); + udevinfof("Enumeration finished."); return HAL_SUCCESS; } @@ -695,93 +678,96 @@ void usbhDevicePrintInfo(usbh_device_t *dev) { USBH_DEFINE_BUFFER(char str[64]); usbh_device_descriptor_t *const desc = &dev->devDesc; - uinfo("----- Device info -----"); - uinfo("Device descriptor:"); - uinfof("\tUSBSpec=%04x, #configurations=%d, langID0=%04x", + udevinfo("----- Device info -----"); + udevinfo("Device descriptor:"); + udevinfof("\tUSBSpec=%04x, #configurations=%d, langID0=%04x", desc->bcdUSB, desc->bNumConfigurations, dev->langID0); - uinfof("\tClass=%02x, Subclass=%02x, Protocol=%02x", + udevinfof("\tClass=%02x, Subclass=%02x, Protocol=%02x", desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol); - uinfof("\tVID=%04x, PID=%04x, Release=%04x", + udevinfof("\tVID=%04x, PID=%04x, Release=%04x", desc->idVendor, desc->idProduct, desc->bcdDevice); if (dev->langID0) { usbhDeviceReadString(dev, str, sizeof(str), desc->iManufacturer, dev->langID0); - uinfof("\tManufacturer: %s", str); + udevinfof("\tManufacturer: %s", str); usbhDeviceReadString(dev, str, sizeof(str), desc->iProduct, dev->langID0); - uinfof("\tProduct: %s", str); + udevinfof("\tProduct: %s", str); usbhDeviceReadString(dev, str, sizeof(str), desc->iSerialNumber, dev->langID0); - uinfof("\tSerial Number: %s", str); + udevinfof("\tSerial Number: %s", str); } if (dev->status == USBH_DEVSTATUS_CONFIGURED) { - uinfo("Configuration descriptor (partial):"); + udevinfo("Configuration descriptor (partial):"); usbh_config_descriptor_t *const cfg = &dev->basicConfigDesc; - uinfof("\tbConfigurationValue=%d, Length=%d, #interfaces=%d", + udevinfof("\tbConfigurationValue=%d, Length=%d, #interfaces=%d", cfg->bConfigurationValue, cfg->wTotalLength, cfg->bNumInterfaces); - uinfof("\tCurrent=%dmA", cfg->bMaxPower * 2); - uinfof("\tSelfPowered=%d, RemoteWakeup=%d", + udevinfof("\tCurrent=%dmA", cfg->bMaxPower * 2); + udevinfof("\tSelfPowered=%d, RemoteWakeup=%d", cfg->bmAttributes & 0x40 ? 1 : 0, cfg->bmAttributes & 0x20 ? 1 : 0); if (dev->langID0) { usbhDeviceReadString(dev, str, sizeof(str), cfg->iConfiguration, dev->langID0); - uinfof("\tName: %s", str); + udevinfof("\tName: %s", str); } } - uinfo("----- End Device info -----"); + udevinfo("----- End Device info -----"); } -void usbhDevicePrintConfiguration(const uint8_t *descriptor, uint16_t rem) { +void usbhDevicePrintConfiguration(const usbh_device_t *dev, + const uint8_t *descriptor, uint16_t rem) { + (void)dev; + generic_iterator_t iep, icfg, ics; if_iterator_t iif; - uinfo("----- Configuration info -----"); - uinfo("Configuration descriptor:"); + udevinfo("----- Configuration info -----"); + udevinfo("Configuration descriptor:"); cfg_iter_init(&icfg, descriptor, rem); const usbh_config_descriptor_t *const cfgdesc = cfg_get(&icfg); - uinfof("Configuration %d, #IFs=%d", cfgdesc->bConfigurationValue, cfgdesc->bNumInterfaces); + udevinfof("Configuration %d, #IFs=%d", cfgdesc->bConfigurationValue, cfgdesc->bNumInterfaces); for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); - uinfof(" Interface %d, alt=%d, #EPs=%d, " + udevinfof(" Interface %d, alt=%d, #EPs=%d, " "Class=%02x, Subclass=%02x, Protocol=%02x", ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting, ifdesc->bNumEndpoints, ifdesc->bInterfaceClass, ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol); for (cs_iter_init(&ics, (generic_iterator_t *)&iif); ics.valid; cs_iter_next(&ics)) { - uinfof(" Class-Specific descriptor, Length=%d, Type=%02x", + udevinfof(" Class-Specific descriptor, Length=%d, Type=%02x", ics.curr[0], ics.curr[1]); } for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); - uinfof(" Endpoint descriptor, Address=%02x, Type=%d, MaxPacket=%d, Interval=%d", + udevinfof(" Endpoint descriptor, Address=%02x, Type=%d, MaxPacket=%d, Interval=%d", epdesc->bEndpointAddress, epdesc->bmAttributes & 3, epdesc->wMaxPacketSize, epdesc->bInterval); for (cs_iter_init(&ics, &iep); ics.valid; cs_iter_next(&ics)) { - uinfof(" Class-Specific descriptor, Length=%d, Type=%02x", + udevinfof(" Class-Specific descriptor, Length=%d, Type=%02x", ics.curr[0], ics.curr[1]); } } } - uinfo("----- End Configuration info -----"); + udevinfo("----- End Configuration info -----"); } #endif @@ -873,25 +859,25 @@ static void _port_process_status_change(usbh_port_t *port) { if (port->c_status & USBH_PORTSTATUS_C_RESET) { port->c_status &= ~USBH_PORTSTATUS_C_RESET; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_RESET); - udbgf("Port %d: reset=%d", port->number, port->status & USBH_PORTSTATUS_RESET ? 1 : 0); + uportdbgf("Port %d: reset=%d", port->number, port->status & USBH_PORTSTATUS_RESET ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_ENABLE) { port->c_status &= ~USBH_PORTSTATUS_C_ENABLE; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_ENABLE); - udbgf("Port %d: enable=%d", port->number, port->status & USBH_PORTSTATUS_ENABLE ? 1 : 0); + uportdbgf("Port %d: enable=%d", port->number, port->status & USBH_PORTSTATUS_ENABLE ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_OVERCURRENT) { port->c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_OVERCURRENT); - uwarnf("Port %d: overcurrent=%d", port->number, port->status & USBH_PORTSTATUS_OVERCURRENT ? 1 : 0); + uportwarnf("Port %d: overcurrent=%d", port->number, port->status & USBH_PORTSTATUS_OVERCURRENT ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_SUSPEND) { port->c_status &= ~USBH_PORTSTATUS_C_SUSPEND; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_SUSPEND); - uinfof("Port %d: suspend=%d", port->number, port->status & USBH_PORTSTATUS_SUSPEND ? 1 : 0); + uportinfof("Port %d: suspend=%d", port->number, port->status & USBH_PORTSTATUS_SUSPEND ? 1 : 0); } } @@ -906,7 +892,7 @@ static void _port_connected(usbh_port_t *port) { USBH_DEFINE_BUFFER(usbh_string_descriptor_t strdesc); port->device.status = USBH_DEVSTATUS_ATTACHED; - uinfof("Port %d: attached, wait debounce...", port->number); + uportinfof("Port %d: attached, wait debounce...", port->number); /* wait for attach de-bounce */ osalThreadSleepMilliseconds(HAL_USBH_PORT_DEBOUNCE_TIME); @@ -916,23 +902,23 @@ static void _port_connected(usbh_port_t *port) { if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) { port->c_status &= ~USBH_PORTSTATUS_C_CONNECTION; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_CONNECTION); - uwarnf("Port %d: connection state changed; abort #1", port->number); + uportwarnf("Port %d: connection state changed; abort #1", port->number); goto abort; } /* make sure that the device is still connected */ if ((port->status & USBH_PORTSTATUS_CONNECTION) == 0) { - uwarnf("Port %d: device is disconnected", port->number); + uportwarnf("Port %d: device is disconnected", port->number); goto abort; } - uinfof("Port %d: connected", port->number); + uportinfof("Port %d: connected", port->number); port->device.status = USBH_DEVSTATUS_CONNECTED; retries = 3; reset: for (i = 0; i < 3; i++) { - uinfof("Port %d: Try reset...", port->number); + uportinfof("Port %d: Try reset...", port->number); /* TODO: check that port is actually disabled */ port->c_status &= ~(USBH_PORTSTATUS_C_RESET | USBH_PORTSTATUS_C_ENABLE); _port_reset(port); @@ -945,7 +931,7 @@ reset: if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) { port->c_status &= ~USBH_PORTSTATUS_C_CONNECTION; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_CONNECTION); - uwarnf("Port %d: connection state changed; abort #2", port->number); + uportwarnf("Port %d: connection state changed; abort #2", port->number); goto abort; } @@ -962,7 +948,7 @@ reset: /* check for timeout */ if (osalOsGetSystemTimeX() - start > HAL_USBH_PORT_RESET_TIMEOUT) { - uwarnf("Port %d: reset timeout", port->number); + uportwarnf("Port %d: reset timeout", port->number); break; } } @@ -972,7 +958,7 @@ reset: goto abort; reset_success: - uinfof("Port %d: Reset OK, recovery...", port->number); + uportinfof("Port %d: Reset OK, recovery...", port->number); /* reset recovery */ osalThreadSleepMilliseconds(100); @@ -994,17 +980,17 @@ reset_success: usbhEPClose(&port->device.ctrl); if (!--retries) { - uwarnf("Port %d: enumeration failed; abort", port->number); + uportwarnf("Port %d: enumeration failed; abort", port->number); goto abort; } /* retry reset & enumeration */ - uwarnf("Port %d: enumeration failed; retry reset & enumeration", port->number); + uportwarnf("Port %d: enumeration failed; retry reset & enumeration", port->number); goto reset; } /* load the default language ID */ - uinfof("Port %d: Loading langID0...", port->number); + uportinfof("Port %d: Loading langID0...", port->number); if (!usbhStdReqGetStringDescriptor(&port->device, 0, 0, USBH_DT_STRING_SIZE, (uint8_t *)&strdesc) && (strdesc.bLength >= 4) @@ -1012,12 +998,12 @@ reset_success: 4, (uint8_t *)&strdesc)) { port->device.langID0 = strdesc.wData[0]; - uinfof("Port %d: langID0=%04x", port->number, port->device.langID0); + uportinfof("Port %d: langID0=%04x", port->number, port->device.langID0); } /* check if the device has only one configuration */ if (port->device.devDesc.bNumConfigurations == 1) { - uinfof("Port %d: device has only one configuration", port->number); + uportinfof("Port %d: device has only one configuration", port->number); _device_configure(&port->device, 0); } @@ -1025,7 +1011,7 @@ reset_success: return; abort: - uerrf("Port %d: abort", port->number); + uporterrf("Port %d: abort", port->number); port->device.status = USBH_DEVSTATUS_DISCONNECTED; } @@ -1033,14 +1019,14 @@ void _usbh_port_disconnected(usbh_port_t *port) { if (port->device.status == USBH_DEVSTATUS_DISCONNECTED) return; - uinfof("Port %d: disconnected", port->number); + uportinfof("Port %d: disconnected", port->number); /* unload drivers */ while (port->device.drivers) { usbh_baseclassdriver_t *drv = port->device.drivers; /* unload */ - uinfof("Port %d: unload driver %s", port->number, drv->info->name); + uportinfof("Port %d: unload driver %s", port->number, drv->info->name); drv->info->vmt->unload(drv); /* unlink */ @@ -1277,7 +1263,7 @@ static bool _classdriver_load(usbh_device_t *dev, uint8_t *descbuff, uint16_t re for (i = 0; i < sizeof_array(usbh_classdrivers_lookup); i++) { const usbh_classdriverinfo_t *const info = usbh_classdrivers_lookup[i]; - uinfof("Try load driver %s", info->name); + udevinfof("Try load driver %s", info->name); drv = info->vmt->load(dev, descbuff, rem); if (drv != NULL) @@ -1297,7 +1283,7 @@ success: } static void _classdriver_process_device(usbh_device_t *dev) { - uinfo("New device found."); + udevinfo("New device found."); const usbh_device_descriptor_t *const devdesc = &dev->devDesc; usbhDevicePrintInfo(dev); @@ -1308,20 +1294,20 @@ static void _classdriver_process_device(usbh_device_t *dev) { * will have multiple configurations. */ if (dev->status != USBH_DEVSTATUS_CONFIGURED) { - uwarn("Multiple configurations not supported, selecting configuration #0"); + udevwarn("Multiple configurations not supported, selecting configuration #0"); if (_device_configure(dev, 0) != HAL_SUCCESS) { - uerr("Couldn't configure device; abort."); + udeverr("Couldn't configure device; abort."); return; } } _device_read_full_cfgdesc(dev, dev->bConfiguration); if (dev->fullConfigurationDescriptor == NULL) { - uerr("Couldn't read full configuration descriptor; abort."); + udeverr("Couldn't read full configuration descriptor; abort."); return; } - usbhDevicePrintConfiguration(dev->fullConfigurationDescriptor, + usbhDevicePrintConfiguration(dev, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); #if HAL_USBH_USE_IAD @@ -1329,7 +1315,7 @@ static void _classdriver_process_device(usbh_device_t *dev) { && dev->devDesc.bDeviceSubClass == 0x02 && dev->devDesc.bDeviceProtocol == 0x01) { - uinfo("Load a driver for each IF collection."); + udevinfo("Load a driver for each IF collection."); generic_iterator_t icfg; if_iterator_t iif; @@ -1338,7 +1324,7 @@ static void _classdriver_process_device(usbh_device_t *dev) { cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); if (!icfg.valid) { - uerr("Invalid configuration descriptor."); + udeverr("Invalid configuration descriptor."); goto exit; } @@ -1348,7 +1334,7 @@ static void _classdriver_process_device(usbh_device_t *dev) { if (_classdriver_load(dev, (uint8_t *)iif.iad, (uint8_t *)iif.curr - (uint8_t *)iif.iad + iif.rem) != HAL_SUCCESS) { - uwarnf("No drivers found for IF collection #%d:%d", + udevwarnf("No drivers found for IF collection #%d:%d", iif.iad->bFirstInterface, iif.iad->bFirstInterface + iif.iad->bInterfaceCount - 1); } @@ -1358,11 +1344,11 @@ static void _classdriver_process_device(usbh_device_t *dev) { } else #endif if (_classdriver_load(dev, (uint8_t *)devdesc, USBH_DT_DEVICE_SIZE) != HAL_SUCCESS) { - uinfo("No drivers found for device."); + udevinfo("No drivers found for device."); if (devdesc->bDeviceClass == 0) { /* each interface defines its own device class/subclass/protocol */ - uinfo("Try load a driver for each IF."); + udevinfo("Try load a driver for each IF."); generic_iterator_t icfg; if_iterator_t iif; @@ -1371,7 +1357,7 @@ static void _classdriver_process_device(usbh_device_t *dev) { cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); if (!icfg.valid) { - uerr("Invalid configuration descriptor."); + udeverr("Invalid configuration descriptor."); goto exit; } @@ -1380,12 +1366,12 @@ static void _classdriver_process_device(usbh_device_t *dev) { if (ifdesc->bInterfaceNumber != last_if) { last_if = ifdesc->bInterfaceNumber; if (_classdriver_load(dev, (uint8_t *)ifdesc, iif.rem) != HAL_SUCCESS) { - uwarnf("No drivers found for IF #%d", ifdesc->bInterfaceNumber); + udevwarnf("No drivers found for IF #%d", ifdesc->bInterfaceNumber); } } } } else { - uwarn("Unable to load driver."); + udevwarn("Unable to load driver."); } } diff --git a/os/hal/src/usbh/hal_usbh_aoa.c b/os/hal/src/usbh/hal_usbh_aoa.c index 0686179..77ac4e7 100644 --- a/os/hal/src/usbh/hal_usbh_aoa.c +++ b/os/hal/src/usbh/hal_usbh_aoa.c @@ -29,39 +29,12 @@ //#pragma GCC optimize("Og") - -#if USBHAOA_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHAOA_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBHAOA_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHAOA_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif - +#define _USBH_DEBUG_HELPER_CLASS_DRIVER container_of(aoacp, USBHAOADriver, channel) +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHAOA_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHAOA_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHAOA_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHAOA_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" /*===========================================================================*/ /* Constants */ @@ -162,11 +135,11 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc }; if (descriptor[1] != USBH_DT_DEVICE) { - uinfo("AOA: Won't try to detect Android device at interface level"); + udevinfo("AOA: Won't try to detect Android device at interface level"); return NULL; } - uinfo("AOA: Unrecognized VID"); + udevinfo("AOA: Unrecognized VID"); #if defined(HAL_USBHAOA_FILTER_CALLBACK) if (!HAL_USBHAOA_FILTER_CALLBACK(dev, descriptor, rem, &config)) { @@ -174,12 +147,12 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc } #endif - uinfo("AOA: Try if it's an Android device"); + udevinfo("AOA: Try if it's an Android device"); if (_get_protocol(dev, &protocol) != HAL_SUCCESS) { - uinfo("AOA: not an Android device"); + udevinfo("AOA: not an Android device"); return NULL; } - uinfof("AOA: Possible Android device found (protocol=%d)", protocol); + udevinfof("AOA: Possible Android device found (protocol=%d)", protocol); if (config.channel.manufacturer != NULL) { if ((_send_string(dev, USBHAOA_ACCESSORY_STRING_MANUFACTURER, config.channel.manufacturer) != HAL_SUCCESS) @@ -188,22 +161,22 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc || (_send_string(dev, USBHAOA_ACCESSORY_STRING_VERSION, config.channel.version) != HAL_SUCCESS) || (_send_string(dev, USBHAOA_ACCESSORY_STRING_URI, config.channel.uri) != HAL_SUCCESS) || (_send_string(dev, USBHAOA_ACCESSORY_STRING_SERIAL, config.channel.serial) != HAL_SUCCESS)) { - uerr("AOA: Can't send string; abort start"); + udeverr("AOA: Can't send string; abort start"); return NULL; } } if (protocol > 1) { if (_set_audio_mode(dev, (uint16_t)(config.audio.mode)) != HAL_SUCCESS) { - uerr("AOA: Can't set audio mode; abort channel start"); + udeverr("AOA: Can't set audio mode; abort channel start"); return NULL; } } if (_accessory_start(dev) != HAL_SUCCESS) { - uerr("AOA: Can't start accessory; abort channel start"); + udeverr("AOA: Can't start accessory; abort channel start"); } else { - uinfo("AOA: Accessory started"); + udevinfo("AOA: Accessory started"); } return NULL; @@ -227,18 +200,18 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc case AOA_GOOGLE_PID_ACCESSORY_AUDIO_ABD: break; default: - uerr("AOA: Unrecognized PID"); + udeverr("AOA: Unrecognized PID"); return NULL; } const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; if ((_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, 0xFF, 0xFF, 0x00) != HAL_SUCCESS) || (ifdesc->bNumEndpoints < 2)) { - uerr("AOA: This IF is not the Accessory IF"); + udeverr("AOA: This IF is not the Accessory IF"); return NULL; } - uinfof("AOA: Found Accessory Interface #%d", ifdesc->bInterfaceNumber); + udevinfof("AOA: Found Accessory Interface #%d", ifdesc->bInterfaceNumber); for (i = 0; i < HAL_USBHAOA_MAX_INSTANCES; i++) { if (USBHAOAD[i].dev == NULL) { @@ -247,7 +220,7 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc } } - uwarn("AOA: Can't alloc driver"); + udevwarn("AOA: Can't alloc driver"); /* can't alloc */ return NULL; @@ -269,30 +242,30 @@ alloc_ok: for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("AOA: BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("AOA: BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&aoap->channel.epin, dev, epdesc); usbhEPSetName(&aoap->channel.epin, "AOA[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("AOA: BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("AOA: BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&aoap->channel.epout, dev, epdesc); usbhEPSetName(&aoap->channel.epout, "AOA[BOUT]"); } else { - uinfof("AOA: unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", + udevinfof("AOA: unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((aoap->channel.epin.status != USBH_EPSTATUS_CLOSED) || (aoap->channel.epout.status != USBH_EPSTATUS_CLOSED)) { - uwarn("AOA: Couldn't find endpoints"); + udevwarn("AOA: Couldn't find endpoints"); aoap->state = USBHAOA_STATE_STOP; return NULL; } aoap->state = USBHAOA_STATE_READY; aoap->channel.state = USBHAOA_CHANNEL_STATE_ACTIVE; - uwarn("AOA: Ready"); + udevwarn("AOA: Ready"); return (usbh_baseclassdriver_t *)aoap; } @@ -311,7 +284,7 @@ static void _aoa_unload(usbh_baseclassdriver_t *drv) { /* ------------------------------------ */ static void _submitOutI(USBHAOAChannel *aoacp, uint32_t len) { - udbgf("AOA: Submit OUT %d", len); + uclassdrvdbgf("AOA: Submit OUT %d", len); aoacp->oq_urb.requestedLength = len; usbhURBObjectResetI(&aoacp->oq_urb); usbhURBSubmitI(&aoacp->oq_urb); @@ -327,12 +300,12 @@ static void _out_cb(usbh_urb_t *urb) { chnAddFlagsI(aoacp, CHN_OUTPUT_EMPTY | CHN_TRANSMISSION_END); return; case USBH_URBSTATUS_DISCONNECTED: - uwarn("AOA: URB OUT disconnected"); + uclassdrvwarn("AOA: URB OUT disconnected"); chThdDequeueAllI(&aoacp->oq_waiting, Q_RESET); chnAddFlagsI(aoacp, CHN_OUTPUT_EMPTY); return; default: - uerrf("AOA: URB OUT status unexpected = %d", urb->status); + uclassdrverrf("AOA: URB OUT status unexpected = %d", urb->status); break; } usbhURBObjectResetI(&aoacp->oq_urb); @@ -406,7 +379,7 @@ static msg_t _put(USBHAOAChannel *aoacp, uint8_t b) { } static void _submitInI(USBHAOAChannel *aoacp) { - udbg("AOA: Submit IN"); + uclassdrvdbg("AOA: Submit IN"); usbhURBObjectResetI(&aoacp->iq_urb); usbhURBSubmitI(&aoacp->iq_urb); } @@ -416,9 +389,9 @@ static void _in_cb(usbh_urb_t *urb) { switch (urb->status) { case USBH_URBSTATUS_OK: if (urb->actualLength == 0) { - udbgf("AOA: URB IN no data"); + uurbdbgf("AOA: URB IN no data"); } else { - udbgf("AOA: URB IN data len=%d", urb->actualLength); + uurbdbgf("AOA: URB IN data len=%d", urb->actualLength); aoacp->iq_ptr = aoacp->iq_buff; aoacp->iq_counter = urb->actualLength; chThdDequeueNextI(&aoacp->iq_waiting, Q_OK); @@ -426,14 +399,14 @@ static void _in_cb(usbh_urb_t *urb) { } break; case USBH_URBSTATUS_DISCONNECTED: - uwarn("AOA: URB IN disconnected"); + uurbwarn("AOA: URB IN disconnected"); chThdDequeueAllI(&aoacp->iq_waiting, Q_RESET); chnAddFlagsI(aoacp, CHN_DISCONNECTED); aoacp->state = USBHAOA_CHANNEL_STATE_ACTIVE; container_of(aoacp, USBHAOADriver, channel)->state = USBHAOA_STATE_ACTIVE; break; default: - uerrf("AOA: URB IN status unexpected = %d", urb->status); + uurberrf("AOA: URB IN status unexpected = %d", urb->status); _submitInI(aoacp); break; } @@ -532,7 +505,7 @@ static const struct AOADriverVMT async_channel_vmt = { static void _stop_channelS(USBHAOAChannel *aoacp) { if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) return; - uwarn("AOA: Stop channel"); + uclassdrvwarn("AOA: Stop channel"); chVTResetI(&aoacp->vt); usbhEPCloseS(&aoacp->epin); usbhEPCloseS(&aoacp->epout); diff --git a/os/hal/src/usbh/hal_usbh_debug.c b/os/hal/src/usbh/hal_usbh_debug.c index 57df535..225489d 100644 --- a/os/hal/src/usbh/hal_usbh_debug.c +++ b/os/hal/src/usbh/hal_usbh_debug.c @@ -21,573 +21,199 @@ #include "ch.h" #include "usbh/debug.h" -#include -#if 0 -#include "debug.h" -#else #include "chprintf.h" -#define dbg_lock() -#define dbg_unlock() -#endif - -#define MAX_FILLER 11 -#define FLOAT_PRECISION 9 -#define MPRINTF_USE_FLOAT 0 - -static char *long_to_string_with_divisor(char *p, long num, unsigned radix, long divisor) -{ - int i; - char *q; - long l, ll; +#include - l = num; - if (divisor == 0) { - ll = num; - } else { - ll = divisor; +#define TEMP_BUFF_LEN 255 + +/* ************************ */ +/* Circular queue structure */ +/* ************************ */ +static int dq_append_string(usbh_dq_t *q, const uint8_t *s, int len) { + if (len <= 0) return 0; + if (len > TEMP_BUFF_LEN) len = TEMP_BUFF_LEN; + if (q->rem < len + 1) return -1; + q->rem -= len + 1; + + uint8_t *d = q->next; + *d++ = len; + if (d == q->end) d = q->start; + while (len--) { + *d++ = *s++; + if (d == q->end) d = q->start; } - - q = p + MAX_FILLER; - do { - i = (int)(l % radix); - i += '0'; - if (i > '9') { - i += 'A' - '0' - 10; - } - *--q = i; - l /= radix; - } while ((ll /= radix) != 0); - - i = (int)(p + MAX_FILLER - q); - do { - *p++ = *q++; - } while (--i); - - return p; -} - -static char *ltoa(char *p, long num, unsigned radix) { - - return long_to_string_with_divisor(p, num, radix, 0); + q->next = d; + return 0; } -#if MPRINTF_USE_FLOAT -static const long _pow10[FLOAT_PRECISION] = {10, 100, 1000, 10000, 100000, 1000000, - 10000000, 100000000, 1000000000}; -static const double m10[FLOAT_PRECISION] = {5.0/100, 5.0/1000, 5.0/10000, 5.0/100000, 5.0/1000000, - 5.0/10000000, 5.0/100000000, 5.0/1000000000, 5.0/10000000000}; - -static char *ftoa(char *p, double num, unsigned long precision, bool dot) { - long l; - char *q; - double r; - - - if (precision == 0) { - l = (long)(num + 0.5); - return long_to_string_with_divisor(p, l, 10, 0); - } else { - if (precision > FLOAT_PRECISION) precision = FLOAT_PRECISION; - r = m10[precision - 1]; - precision = _pow10[precision - 1]; - - l = (long)num; - p = long_to_string_with_divisor(p, l, 10, 0); - if (dot) *p++ = '.'; - l = (long)((num - l + r) * precision); - q = long_to_string_with_divisor(p, l, 10, precision / 10) - 1; - - while (q > p) { - if (*q != '0') { - break; - } - --q; +static void dq_remove_oldest_string(usbh_dq_t *q) { + int len = *q->first; + if (len) { + ++len; + q->rem += len; + q->first += len; + if (q->first >= q->end) { + q->first -= q->sz; + } + if (q->rem == q->sz) { + *q->first = 0; } - return ++q; } - - - - } -#endif -static inline void _wr(input_queue_t *iqp, char c) { - *iqp->q_wrptr++ = c; - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; +static int dq_read_oldest_string(usbh_dq_t *q, uint8_t *d) { + uint8_t *s = q->first; + int len; + int sz; + len = sz = *s++; + while (len--) { + *d++ = *s++; + if (d == q->end) d = q->start; + } + *d = 0; + return sz; } -static inline void _put(char c) { - input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; - if (sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter <= 1) - return; - iqp->q_counter++; - _wr(iqp, c); +static void dq_init(usbh_dq_t *q, uint8_t *buff, int len) { + q->start = q->first = q->next = buff; + q->end = q->start + len; + q->sz = q->rem = len; + *buff = 0; } -int _dbg_printf(const char *fmt, va_list ap) { - char *p, *s, c, filler; - int i, precision, width; - int n = 0; - bool is_long, left_align, sign; - long l; -#if MPRINTF_USE_FLOAT - double f; - char tmpbuf[2*MAX_FILLER + 1]; -#else - char tmpbuf[MAX_FILLER + 1]; -#endif - - for (;;) { - - //agarrar nuevo caracter de formato - c = *fmt++; - //chequeo eos - if (c == 0) return n; +static uint8_t buff[TEMP_BUFF_LEN + 1]; - //copio los caracteres comunes - if (c != '%') { - _put(c); - n++; - continue; - } - - //encontré un '%' - p = tmpbuf; - s = tmpbuf; - - //left align - left_align = FALSE; - if (*fmt == '-') { - fmt++; - left_align = TRUE; - } - - sign = FALSE; - if (*fmt == '+') { - fmt++; - sign = TRUE; - } - - //filler - filler = ' '; - if (*fmt == '0') { - fmt++; - filler = '0'; - } - - //width - width = 0; - while (TRUE) { - c = *fmt++; - if (c >= '0' && c <= '9') - c -= '0'; - else if (c == '*') - c = va_arg(ap, int); - else - break; - width = width * 10 + c; - } - - //precision - precision = 0; - if (c == '.') { - - if (*fmt == 'n') { - fmt++; - - } - while (TRUE) { - c = *fmt++; - if (c >= '0' && c <= '9') - c -= '0'; - else if (c == '*') - c = va_arg(ap, int); - else - break; - precision = precision * 10 + c; - } - } - - //long modifier - if (c == 'l' || c == 'L') { - is_long = TRUE; - if (*fmt) - c = *fmt++; - } - else - is_long = (c >= 'A') && (c <= 'Z'); - - /* Command decoding.*/ - switch (c) { - //char - case 'c': - filler = ' '; - *p++ = va_arg(ap, int); - break; - - //string - case 's': - filler = ' '; - if ((s = va_arg(ap, char *)) == 0) - s = (char *)"(null)"; - if (precision == 0) - precision = 32767; - - //strlen con límite hasta precision - for (p = s; *p && (--precision >= 0); p++) - ; - break; - - - - case 'D': - case 'd': - case 'I': - case 'i': - if (is_long) - l = va_arg(ap, long); - else - l = va_arg(ap, int); - if (l < 0) { - *p++ = '-'; - l = -l; - sign = TRUE; - } else if (sign) { - *p++ = '+'; - } - p = ltoa(p, l, 10); - break; - -#if MPRINTF_USE_FLOAT - case 'f': - f = va_arg(ap, double); - if (f < 0) { - *p++ = '-'; - f = -f; - sign = TRUE; - } else if (sign) { - *p++ = '+'; - } - if (prec == FALSE) precision = 6; - p = ftoa(p, f, precision, dot); - break; -#endif - - - case 'X': - case 'x': - c = 16; - goto unsigned_common; - case 'U': - case 'u': - c = 10; - goto unsigned_common; - case 'O': - case 'o': - c = 8; - -unsigned_common: - if (is_long) - l = va_arg(ap, unsigned long); - else - l = va_arg(ap, unsigned int); - p = ltoa(p, l, c); - break; - - //copiar - default: - *p++ = c; - break; - } - - //longitud - i = (int)(p - s); - - //calculo cuántos caracteres de filler debo poner - if ((width -= i) < 0) - width = 0; - - if (left_align == FALSE) - width = -width; - - if (width < 0) { - //alineado a la derecha - - //poner el signo adelante - if (sign && filler == '0') { - _put(*s++); - n++; - i--; - } - - //fill a la izquierda - do { - _put(filler); - n++; - } while (++width != 0); - } - - //copiar los caracteres - while (--i >= 0) { - _put(*s++); - n++; - } +static inline syssts_t _dbg_prologue(struct usbh_debug_helper *debug, + uint32_t hfnum, uint16_t hfir, const char *s, int *len) { + syssts_t sts = chSysGetStatusAndLockX(); - //fill a la derecha - while (width) { - _put(filler); - n++; - width--; - } + debug->last = osalOsGetSystemTimeX(); + if (debug->ena) { + debug->first = debug->last; } - //return n; // can raise 'code is unreachable' warning + if (((hfnum & 0x3fff) == 0x3fff) && (hfir == (hfnum >> 16))) { + *len = chsnprintf((char *)buff, sizeof(buff), "+%08d ", debug->last - debug->first); + debug->ena = FALSE; + } else { + uint32_t f = hfnum & 0xffff; + uint32_t p = 1000 - ((hfnum >> 16) / (hfir / 1000)); + *len = chsnprintf((char *)buff, sizeof(buff), "%05d.%03d %s", f, p, s); + debug->ena = TRUE; + } + return sts; } -static systime_t first, last; -static bool ena; -static uint32_t hdr[2]; +static inline void dbg_epilogue(struct usbh_debug_helper *debug, + syssts_t sts, int len) { -static void _build_hdr(void) { - uint32_t hfnum = USBH_DEBUG_USBHD.otg->HFNUM; - uint16_t hfir = USBH_DEBUG_USBHD.otg->HFIR; - last = osalOsGetSystemTimeX(); - if (ena) { - first = last; + while (dq_append_string(&debug->dq, buff, len) < 0) { + dq_remove_oldest_string(&debug->dq); } - if (((hfnum & 0x3fff) == 0x3fff) && (hfir == (hfnum >> 16))) { - hdr[0] = 0xfeff; - hdr[1] = last - first; - ena = FALSE; - } else { - hdr[0] = 0xffff | (hfir << 16); - hdr[1] = hfnum; - ena = TRUE; + if (debug->on) { + chThdResumeI(&debug->tr, MSG_OK); } -} -static void _print_hdr(void) -{ - _put(hdr[0] & 0xff); - _put((hdr[0] >> 8) & 0xff); - _put((hdr[0] >> 16) & 0xff); - _put((hdr[0] >> 24) & 0xff); - _put(hdr[1] & 0xff); - _put((hdr[1] >> 8) & 0xff); - _put((hdr[1] >> 16) & 0xff); - _put((hdr[1] >> 24) & 0xff); -} - -void usbDbgPrintf(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - syssts_t sts = chSysGetStatusAndLockX(); - input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; - int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter; - if (rem >= 9) { - _build_hdr(); - _print_hdr(); - _dbg_printf(fmt, ap); - iqp->q_counter++; - _wr(iqp, 0); - chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); - } chSysRestoreStatusX(sts); - if (!port_is_isr_context() && chSchIsPreemptionRequired()) { - chSchRescheduleS(); - } - va_end(ap); } +#if USBH_DEBUG_MULTI_HOST +void usbDbgPrintf(USBHDriver *host, const char *fmt, ...) { + if (!host) return; + struct usbh_debug_helper *const debug = &host->debug; + uint32_t hfnum = host->otg->HFNUM; + uint16_t hfir = host->otg->HFIR; +#else +void usbDbgPrintf(const char *fmt, ...) { + struct usbh_debug_helper *const debug = &usbh_debug; + uint32_t hfnum = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFNUM; + uint16_t hfir = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFIR; +#endif + int len; -void usbDbgPuts(const char *s) -{ - _build_hdr(); - uint8_t *p = (uint8_t *)hdr; - uint8_t *top = p + 8; + syssts_t sts = _dbg_prologue(debug, hfnum, hfir, "", &len); - syssts_t sts = chSysGetStatusAndLockX(); - input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; - int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter; - if (rem >= 9) { - while (rem) { - _wr(iqp, *p); - if (++p == top) break; - } - rem -= 9; - while (rem && *s) { - _wr(iqp, *s); - rem--; - s++; - } - _wr(iqp, 0); - iqp->q_counter = sizeof(USBH_DEBUG_USBHD.dbg_buff) - rem; - chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); - } - chSysRestoreStatusX(sts); - if (!port_is_isr_context() && chSchIsPreemptionRequired()) { - chSchRescheduleS(); - } -} - -void usbDbgReset(void) { - const char *msg = "\r\n\r\n==== DEBUG OUTPUT RESET ====\r\n"; + va_list ap; + va_start(ap, fmt); + len += chvsnprintf((char *)buff + len, sizeof(buff) - len, fmt, ap); + va_end(ap); - syssts_t sts = chSysGetStatusAndLockX(); - iqResetI(&USBH_DEBUG_USBHD.iq); - oqResetI(&USBH_DEBUG_SD.oqueue); - while (*msg) { - *USBH_DEBUG_SD.oqueue.q_wrptr++ = *msg++; - USBH_DEBUG_SD.oqueue.q_counter--; - } - chSysRestoreStatusX(sts); - if (!port_is_isr_context() && chSchIsPreemptionRequired()) { - chSchRescheduleS(); - } + dbg_epilogue(debug, sts, len); } -static int _get(void) { - if (!USBH_DEBUG_USBHD.iq.q_counter) return -1; - USBH_DEBUG_USBHD.iq.q_counter--; - uint8_t b = *USBH_DEBUG_USBHD.iq.q_rdptr++; - if (USBH_DEBUG_USBHD.iq.q_rdptr >= USBH_DEBUG_USBHD.iq.q_top) { - USBH_DEBUG_USBHD.iq.q_rdptr = USBH_DEBUG_USBHD.iq.q_buffer; - } - return b; +#if USBH_DEBUG_MULTI_HOST +void usbDbgPuts(USBHDriver *host, const char *s) { + if (!host) return; + struct usbh_debug_helper *const debug = &host->debug; + uint32_t hfnum = host->otg->HFNUM; + uint16_t hfir = host->otg->HFIR; +#else +void usbDbgPuts(const char *s) { + struct usbh_debug_helper *const debug = &usbh_debug; + uint32_t hfnum = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFNUM; + uint16_t hfir = USBH_DEBUG_SINGLE_HOST_SELECTION.otg->HFIR; +#endif + int len; + syssts_t sts = _dbg_prologue(debug, hfnum, hfir, s, &len); + dbg_epilogue(debug, sts, len); } -void usbDbgSystemHalted(void) { - while (true) { - if (!((bool)((USBH_DEBUG_SD.oqueue.q_wrptr == USBH_DEBUG_SD.oqueue.q_rdptr) && (USBH_DEBUG_SD.oqueue.q_counter != 0U)))) - break; - USBH_DEBUG_SD.oqueue.q_counter++; - while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); - USBH_DEBUG_SD.usart->DR = *USBH_DEBUG_SD.oqueue.q_rdptr++; - if (USBH_DEBUG_SD.oqueue.q_rdptr >= USBH_DEBUG_SD.oqueue.q_top) { - USBH_DEBUG_SD.oqueue.q_rdptr = USBH_DEBUG_SD.oqueue.q_buffer; - } - } - - int c; - int state = 0; - for (;;) { - c = _get(); if (c < 0) break; - - if (state == 0) { - if (c == 0xff) state = 1; - } else if (state == 1) { - if (c == 0xff) state = 2; - else (state = 0); - } else { - c = _get(); if (c < 0) return; - c = _get(); if (c < 0) return; - c = _get(); if (c < 0) return; - c = _get(); if (c < 0) return; - c = _get(); if (c < 0) return; - - while (true) { - c = _get(); if (c < 0) return; - if (!c) { - while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); - USBH_DEBUG_SD.usart->DR = '\r'; - while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); - USBH_DEBUG_SD.usart->DR = '\n'; - state = 0; - break; - } - while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); - USBH_DEBUG_SD.usart->DR = c; - } - } - } +#if USBH_DEBUG_MULTI_HOST +void usbDbgEnable(USBHDriver *host, bool enable) { + struct usbh_debug_helper *const debug = &host->debug; +#else +void usbDbgEnable(bool enable) { + struct usbh_debug_helper *const debug = &usbh_debug; +#endif + debug->on = enable; } static void usb_debug_thread(void *arg) { - USBHDriver *host = (USBHDriver *)arg; - uint8_t state = 0; +#if USBH_DEBUG_MULTI_HOST + USBHDriver *const host = (USBHDriver *)arg; + struct usbh_debug_helper *const debug = &host->debug; +#else + (void)arg; + struct usbh_debug_helper *const debug = &usbh_debug; +#endif + + uint8_t rdbuff[TEMP_BUFF_LEN + 1]; chRegSetThreadName("USBH_DBG"); while (true) { - msg_t c = iqGet(&host->iq); - if (c < 0) goto reset; - - if (state == 0) { - if (c == 0xff) state = 1; - } else if (state == 1) { - if (c == 0xff) state = 2; - else if (c == 0xfe) state = 3; - else (state = 0); - } else if (state == 2) { - uint16_t hfir; - uint32_t hfnum; - - hfir = c; - c = iqGet(&host->iq); if (c < 0) goto reset; - hfir |= c << 8; - - c = iqGet(&host->iq); if (c < 0) goto reset; - hfnum = c; - c = iqGet(&host->iq); if (c < 0) goto reset; - hfnum |= c << 8; - c = iqGet(&host->iq); if (c < 0) goto reset; - hfnum |= c << 16; - c = iqGet(&host->iq); if (c < 0) goto reset; - hfnum |= c << 24; - - uint32_t f = hfnum & 0xffff; - uint32_t p = 1000 - ((hfnum >> 16) / (hfir / 1000)); - dbg_lock(); - chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "%05d.%03d ", f, p); - state = 4; - } else if (state == 3) { - uint32_t t; - - c = iqGet(&host->iq); if (c < 0) goto reset; - c = iqGet(&host->iq); if (c < 0) goto reset; - - t = c; - c = iqGet(&host->iq); if (c < 0) goto reset; - t |= c << 8; - c = iqGet(&host->iq); if (c < 0) goto reset; - t |= c << 16; - c = iqGet(&host->iq); if (c < 0) goto reset; - t |= c << 24; - - dbg_lock(); - chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "+%08d ", t); - state = 4; + chSysLock(); + int len = dq_read_oldest_string(&debug->dq, rdbuff); + if (!len) { + chThdSuspendS(&debug->tr); + chSysUnlock(); } else { - while (true) { - if (!c) { - sdPut(&USBH_DEBUG_SD, '\r'); - sdPut(&USBH_DEBUG_SD, '\n'); - goto reset; - } - sdPut(&USBH_DEBUG_SD, (uint8_t)c); - c = iqGet(&host->iq); if (c < 0) goto reset; - } - } - - continue; -reset: - if (state == 4) { - dbg_unlock(); + dq_remove_oldest_string(&debug->dq); + chSysUnlock(); +#if USBH_DEBUG_MULTI_HOST + USBH_DEBUG_OUTPUT_CALLBACK(host, rdbuff, len); +#else + USBH_DEBUG_OUTPUT_CALLBACK(rdbuff, len); +#endif } - state = 0; } } +#if USBH_DEBUG_MULTI_HOST void usbDbgInit(USBHDriver *host) { - if (host != &USBH_DEBUG_USBHD) - return; - iqObjectInit(&USBH_DEBUG_USBHD.iq, USBH_DEBUG_USBHD.dbg_buff, sizeof(USBH_DEBUG_USBHD.dbg_buff), 0, 0); - chThdCreateStatic(USBH_DEBUG_USBHD.waDebug, sizeof(USBH_DEBUG_USBHD.waDebug), NORMALPRIO, usb_debug_thread, &USBH_DEBUG_USBHD); + struct usbh_debug_helper *const debug = &host->debug; + void *param = host; +#else +void usbDbgInit(void) { + struct usbh_debug_helper *const debug = &usbh_debug; + void *param = NULL; +#endif + dq_init(&debug->dq, debug->buff, sizeof(debug->buff)); + debug->on = true; + chThdCreateStatic(debug->thd_wa, sizeof(debug->thd_wa), + NORMALPRIO, usb_debug_thread, param); } #endif diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index b4b03df..1b06405 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -27,37 +27,13 @@ #include "usbh/dev/ftdi.h" #include "usbh/internal.h" -#if USBHFTDI_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHFTDI_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif +#define _USBH_DEBUG_HELPER_CLASS_DRIVER ftdipp->ftdip +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHFTDI_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHFTDI_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHFTDI_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHFTDI_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" -#if USBHFTDI_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHFTDI_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif static void _ftdip_object_init(USBHFTDIPortDriver *ftdipp); @@ -105,7 +81,7 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des case 0xE2E6: break; default: - uerr("FTDI: Unrecognized PID"); + udeverr("FTDI: Unrecognized PID"); return NULL; } @@ -114,7 +90,7 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des return NULL; if (((const usbh_interface_descriptor_t *)descriptor)->bInterfaceNumber != 0) { - uwarn("FTDI: Will allocate driver along with IF #0"); + udevwarn("FTDI: Will allocate driver along with IF #0"); } /* alloc driver */ @@ -125,7 +101,7 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des } } - uwarn("FTDI: Can't alloc driver"); + udevwarn("FTDI: Can't alloc driver"); /* can't alloc */ return NULL; @@ -135,24 +111,24 @@ alloc_ok: ftdip->ports = 0; switch (dev->devDesc.bcdDevice) { case 0x200: //AM - uinfo("FTDI: Type A chip"); + udevinfo("FTDI: Type A chip"); ftdip->type = USBHFTDI_TYPE_A; break; case 0x400: //BM case 0x500: //2232C case 0x600: //R case 0x1000: //230X - uinfo("FTDI: Type B chip"); + udevinfo("FTDI: Type B chip"); ftdip->type = USBHFTDI_TYPE_B; break; case 0x700: //2232H; case 0x800: //4232H; case 0x900: //232H; - uinfo("FTDI: Type H chip"); + udevinfo("FTDI: Type H chip"); ftdip->type = USBHFTDI_TYPE_H; break; default: - uerr("FTDI: Unrecognized chip type"); + udeverr("FTDI: Unrecognized chip type"); return NULL; } usbhEPSetName(&dev->ctrl, "FTD[CTRL]"); @@ -163,11 +139,11 @@ alloc_ok: cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); - uinfof("FTDI: Interface #%d", ifdesc->bInterfaceNumber); + udevinfof("FTDI: Interface #%d", ifdesc->bInterfaceNumber); USBHFTDIPortDriver *const prt = _find_port(); if (prt == NULL) { - uwarn("\tCan't alloc port for this interface"); + udevwarn("\tCan't alloc port for this interface"); break; } @@ -178,23 +154,23 @@ alloc_ok: for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epin, dev, epdesc); usbhEPSetName(&prt->epin, "FTD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&prt->epout, dev, epdesc); usbhEPSetName(&prt->epout, "FTD[BOUT]"); } else { - uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", + udevinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } if ((prt->epin.status != USBH_EPSTATUS_CLOSED) || (prt->epout.status != USBH_EPSTATUS_CLOSED)) { - uwarn("\tCouldn't find endpoints; can't alloc port for this interface"); + udevwarn("\tCouldn't find endpoints; can't alloc port for this interface"); continue; } @@ -336,13 +312,14 @@ static usbh_urbstatus_t _ftdi_port_control(USBHFTDIPortDriver *ftdipp, return usbhControlRequestExtended(ftdipp->ftdip->dev, &req, buff, NULL, OSAL_MS2I(1000)); } -static uint32_t _get_divisor(uint32_t baud, usbhftdi_type_t type) { +static uint32_t _get_divisor(const USBHFTDIPortDriver *ftdipp, uint32_t baud) { + usbhftdi_type_t type = ftdipp->ftdip->type; static const uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; if (type == USBHFTDI_TYPE_A) { uint32_t divisor3 = ((48000000UL / 2) + baud / 2) / baud; - uinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor3); + uclassdrvinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor3); if ((divisor3 & 0x7) == 7) divisor3++; /* round x.7/8 up to x+1 */ @@ -359,13 +336,13 @@ static uint32_t _get_divisor(uint32_t baud, usbhftdi_type_t type) { } else { if (type == USBHFTDI_TYPE_B) { divisor = ((48000000UL / 2) + baud / 2) / baud; - uinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor); + uclassdrvinfof("FTDI: desired=%dbps, real=%dbps", baud, (48000000UL / 2) / divisor); } else { /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ if (baud < 1200) baud = 1200; divisor = (120000000UL * 8 + baud * 5) / (baud * 10); - uinfof("FTDI: desired=%dbps, real=%dbps", baud, (120000000UL * 8) / divisor / 10); + uclassdrvinfof("FTDI: desired=%dbps, real=%dbps", baud, (120000000UL * 8) / divisor / 10); } divisor = (divisor >> 3) | (divfrac[divisor & 0x7] << 14); @@ -382,7 +359,7 @@ static uint32_t _get_divisor(uint32_t baud, usbhftdi_type_t type) { } static usbh_urbstatus_t _set_baudrate(USBHFTDIPortDriver *ftdipp, uint32_t baudrate) { - uint32_t divisor = _get_divisor(baudrate, ftdipp->ftdip->type); + uint32_t divisor = _get_divisor(ftdipp, baudrate); uint16_t wValue = (uint16_t)divisor; uint16_t wIndex = (uint16_t)(divisor >> 16); if (ftdipp->ftdip->dev->basicConfigDesc.bNumInterfaces > 1) @@ -400,7 +377,7 @@ static usbh_urbstatus_t _set_baudrate(USBHFTDIPortDriver *ftdipp, uint32_t baudr static void _submitOutI(USBHFTDIPortDriver *ftdipp, uint32_t len) { - udbgf("FTDI: Submit OUT %d", len); + uclassdrvdbgf("FTDI: Submit OUT %d", len); ftdipp->oq_urb.requestedLength = len; usbhURBObjectResetI(&ftdipp->oq_urb); usbhURBSubmitI(&ftdipp->oq_urb); @@ -415,11 +392,11 @@ static void _out_cb(usbh_urb_t *urb) { chThdDequeueNextI(&ftdipp->oq_waiting, Q_OK); return; case USBH_URBSTATUS_DISCONNECTED: - uwarn("FTDI: URB OUT disconnected"); + uurbwarn("FTDI: URB OUT disconnected"); chThdDequeueAllI(&ftdipp->oq_waiting, Q_RESET); return; default: - uerrf("FTDI: URB OUT status unexpected = %d", urb->status); + uurberrf("FTDI: URB OUT status unexpected = %d", urb->status); break; } usbhURBObjectResetI(&ftdipp->oq_urb); @@ -493,7 +470,7 @@ static msg_t _put(USBHFTDIPortDriver *ftdipp, uint8_t b) { } static void _submitInI(USBHFTDIPortDriver *ftdipp) { - udbg("FTDI: Submit IN"); + uclassdrvdbg("FTDI: Submit IN"); usbhURBObjectResetI(&ftdipp->iq_urb); usbhURBSubmitI(&ftdipp->iq_urb); } @@ -503,9 +480,9 @@ static void _in_cb(usbh_urb_t *urb) { switch (urb->status) { case USBH_URBSTATUS_OK: if (urb->actualLength < 2) { - uwarnf("FTDI: URB IN actualLength = %d, < 2", urb->actualLength); + uurbwarnf("FTDI: URB IN actualLength = %d, < 2", urb->actualLength); } else if (urb->actualLength > 2) { - udbgf("FTDI: URB IN data len=%d, status=%02x %02x", + uurbdbgf("FTDI: URB IN data len=%d, status=%02x %02x", urb->actualLength - 2, ((uint8_t *)urb->buff)[0], ((uint8_t *)urb->buff)[1]); @@ -514,18 +491,18 @@ static void _in_cb(usbh_urb_t *urb) { chThdDequeueNextI(&ftdipp->iq_waiting, Q_OK); return; } else { - udbgf("FTDI: URB IN no data, status=%02x %02x", + uurbdbgf("FTDI: URB IN no data, status=%02x %02x", ((uint8_t *)urb->buff)[0], ((uint8_t *)urb->buff)[1]); // return; } break; case USBH_URBSTATUS_DISCONNECTED: - uwarn("FTDI: URB IN disconnected"); + uurbwarn("FTDI: URB IN disconnected"); chThdDequeueAllI(&ftdipp->iq_waiting, Q_RESET); return; default: - uerrf("FTDI: URB IN status unexpected = %d", urb->status); + uurberrf("FTDI: URB IN status unexpected = %d", urb->status); break; } _submitInI(ftdipp); diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index a34325b..f381b90 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -27,39 +27,12 @@ #include "usbh/dev/hid.h" #include "usbh/internal.h" -#if USBHHID_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHHID_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBHHID_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHHID_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif - - +#define _USBH_DEBUG_HELPER_CLASS_DRIVER hidp +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHHID_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHHID_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHHID_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHHID_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" #define USBH_HID_REQ_GET_REPORT 0x01 #define USBH_HID_REQ_GET_IDLE 0x02 @@ -113,7 +86,7 @@ static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *desc } } - uwarn("Can't alloc HID driver"); + udevwarn("Can't alloc HID driver"); /* can't alloc */ return NULL; @@ -136,7 +109,7 @@ alloc_ok: for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) { - uinfof("INT IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("INT IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&hidp->epin, dev, epdesc); usbhEPSetName(&hidp->epin, "HID[IIN ]"); #if HAL_USBHHID_USE_INTERRUPT_OUT @@ -147,7 +120,7 @@ alloc_ok: usbhEPSetName(&hidp->epout, "HID[IOUT]"); #endif } else { - uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", + udevinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } @@ -157,19 +130,19 @@ alloc_ok: if (ifdesc->bInterfaceSubClass != 0x01) { hidp->type = USBHHID_DEVTYPE_GENERIC; - uinfof("HID: bInterfaceSubClass=%02x, generic HID", ifdesc->bInterfaceSubClass); + udevinfof("HID: bInterfaceSubClass=%02x, generic HID", ifdesc->bInterfaceSubClass); if (ifdesc->bInterfaceSubClass != 0x00) { - uinfof("HID: bInterfaceSubClass=%02x is an invalid bInterfaceSubClass value", + udevinfof("HID: bInterfaceSubClass=%02x is an invalid bInterfaceSubClass value", ifdesc->bInterfaceSubClass); } } else if (ifdesc->bInterfaceProtocol == 0x01) { hidp->type = USBHHID_DEVTYPE_BOOT_KEYBOARD; - uinfo("HID: BOOT protocol keyboard found"); + udevinfo("HID: BOOT protocol keyboard found"); } else if (ifdesc->bInterfaceProtocol == 0x02) { hidp->type = USBHHID_DEVTYPE_BOOT_MOUSE; - uinfo("HID: BOOT protocol mouse found"); + udevinfo("HID: BOOT protocol mouse found"); } else { - uerrf("HID: bInterfaceProtocol=%02x is an invalid boot protocol, abort", + udeverrf("HID: bInterfaceProtocol=%02x is an invalid boot protocol, abort", ifdesc->bInterfaceProtocol); goto deinit; } @@ -200,14 +173,14 @@ static void _in_cb(usbh_urb_t *urb) { } break; case USBH_URBSTATUS_DISCONNECTED: - uwarn("HID: URB IN disconnected"); + uurbwarn("HID: URB IN disconnected"); return; case USBH_URBSTATUS_TIMEOUT: //no data break; default: - uerrf("HID: URB IN status unexpected = %d", urb->status); + uurberrf("HID: URB IN status unexpected = %d", urb->status); break; } usbhURBObjectResetI(&hidp->in_urb); diff --git a/os/hal/src/usbh/hal_usbh_hub.c b/os/hal/src/usbh/hal_usbh_hub.c index 900c6f8..b8937fa 100644 --- a/os/hal/src/usbh/hal_usbh_hub.c +++ b/os/hal/src/usbh/hal_usbh_hub.c @@ -27,38 +27,12 @@ #include "usbh/dev/hub.h" #include "usbh/internal.h" -#if USBHHUB_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHHUB_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBHHUB_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHHUB_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif - +#define _USBH_DEBUG_HELPER_CLASS_DRIVER hubp +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHHUB_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHHUB_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHHUB_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHHUB_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES]; static usbh_port_t USBHPorts[HAL_USBHHUB_MAX_PORTS]; @@ -106,13 +80,13 @@ static void _urb_complete(usbh_urb_t *urb) { switch (urb->status) { case USBH_URBSTATUS_TIMEOUT: /* the device NAKed */ - udbg("HUB: no info"); + uurbdbg("HUB: no info"); //hubdp->statuschange = 0; break; case USBH_URBSTATUS_OK: { uint8_t len = hubdp->hubDesc.bNbrPorts / 8 + 1; if (urb->actualLength != len) { - uwarnf("Expected %d status change bytes but got %d", len, urb->actualLength); + uurbwarnf("Expected %d status change bytes but got %d", len, urb->actualLength); } if (urb->actualLength < len) @@ -126,13 +100,13 @@ static void _urb_complete(usbh_urb_t *urb) { while (len--) *sc++ |= *r++; - uinfof("HUB: change, %08x", hubdp->statuschange); + uurbinfof("HUB: change, %08x", hubdp->statuschange); } break; case USBH_URBSTATUS_DISCONNECTED: - uwarn("HUB: URB disconnected, aborting poll"); + uurbwarn("HUB: URB disconnected, aborting poll"); return; default: - uerrf("HUB: URB status unexpected = %d", urb->status); + uurberrf("HUB: URB status unexpected = %d", urb->status); break; } @@ -181,7 +155,7 @@ static usbh_baseclassdriver_t *_hub_load(usbh_device_t *dev, } } - uwarn("Can't alloc HUB driver"); + udevwarn("Can't alloc HUB driver"); /* can't alloc */ return NULL; @@ -195,7 +169,7 @@ alloc_ok: usbhEPSetName(&dev->ctrl, "HUB[CTRL]"); /* read Hub descriptor */ - uinfo("Read Hub descriptor"); + udevinfo("Read Hub descriptor"); if (usbhhubControlRequest(dev->host, hubdp, USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE, USBH_REQ_GET_DESCRIPTOR, @@ -207,7 +181,7 @@ alloc_ok: const usbh_hub_descriptor_t *const hubdesc = &hubdp->hubDesc; - uinfof("Hub descriptor loaded; %d ports, wHubCharacteristics=%04x, bPwrOn2PwrGood=%d, bHubContrCurrent=%d", + udevinfof("Hub descriptor loaded; %d ports, wHubCharacteristics=%04x, bPwrOn2PwrGood=%d, bHubContrCurrent=%d", hubdesc->bNbrPorts, hubdesc->wHubCharacteristics, hubdesc->bPwrOn2PwrGood, @@ -217,7 +191,7 @@ alloc_ok: uint8_t ports = hubdesc->bNbrPorts; for (i = 0; (ports > 0) && (i < HAL_USBHHUB_MAX_PORTS); i++) { if (USBHPorts[i].hub == NULL) { - uinfof("Alloc port %d", ports); + udevinfof("Alloc port %d", ports); _usbhub_port_object_init(&USBHPorts[i], dev->host, hubdp, ports); USBHPorts[i].next = hubdp->ports; hubdp->ports = &USBHPorts[i]; @@ -226,7 +200,7 @@ alloc_ok: } if (ports) { - uwarn("Could not alloc all ports"); + udevwarn("Could not alloc all ports"); } /* link hub to the host's list */ @@ -235,7 +209,7 @@ alloc_ok: /* enable power to ports */ usbh_port_t *port = hubdp->ports; while (port) { - uinfof("Enable power for port %d", port->number); + udevinfof("Enable power for port %d", port->number); usbhhubSetFeaturePort(port, USBH_PORT_FEAT_POWER); port = port->next; } diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index 230bf9a..a5fbc9f 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -27,37 +27,12 @@ #include "usbh/dev/msd.h" #include "usbh/internal.h" -#if USBHMSD_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHMSD_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBHMSD_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHMSD_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif +#define _USBH_DEBUG_HELPER_CLASS_DRIVER msdp +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHMSD_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHMSD_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHMSD_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHMSD_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" static void _lun_object_deinit(USBHMassStorageLUNDriver *lunp); @@ -122,7 +97,7 @@ static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *desc } } - uwarn("Can't alloc MSD driver"); + udevwarn("Can't alloc MSD driver"); /* can't alloc */ return NULL; @@ -146,16 +121,16 @@ alloc_ok: for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) { const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep); if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epin, dev, epdesc); usbhEPSetName(&msdp->epin, "MSD[BIN ]"); } else if (((epdesc->bEndpointAddress & 0x80) == 0) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) { - uinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); + udevinfof("BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress); usbhEPObjectInit(&msdp->epout, dev, epdesc); usbhEPSetName(&msdp->epout, "MSD[BOUT]"); } else { - uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", + udevinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } } @@ -164,23 +139,23 @@ alloc_ok: } /* read the number of LUNs */ - uinfo("Reading Max LUN:"); + udevinfo("Reading Max LUN:"); USBH_DEFINE_BUFFER(uint8_t buff[4]); stat = usbhControlRequest(dev, USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), MSD_GET_MAX_LUN, 0, msdp->ifnum, 1, buff); if (stat == USBH_URBSTATUS_OK) { msdp->max_lun = buff[0] + 1; - uinfof("\tmax_lun = %d", msdp->max_lun); + udevinfof("\tmax_lun = %d", msdp->max_lun); if (msdp->max_lun > HAL_USBHMSD_MAX_LUNS) { msdp->max_lun = HAL_USBHMSD_MAX_LUNS; - uwarnf("\tUsing max_lun = %d", msdp->max_lun); + udevwarnf("\tUsing max_lun = %d", msdp->max_lun); } } else if (stat == USBH_URBSTATUS_STALL) { - uwarn("\tStall, max_lun = 1"); + udevwarn("\tStall, max_lun = 1"); msdp->max_lun = 1; } else { - uerr("\tError"); + udeverr("\tError"); goto deinit; } @@ -293,28 +268,30 @@ static bool _msd_bot_reset(USBHMassStorageDriver *msdp) { static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp, void *data) { + USBHMassStorageDriver *const msdp = lunp->msdp; + uint32_t data_actual_len, actual_len; usbh_urbstatus_t status; USBH_DEFINE_BUFFER(msd_csw_t csw); - tran->cbw->bCBWLUN = (uint8_t)(lunp - &lunp->msdp->luns[0]); + tran->cbw->bCBWLUN = (uint8_t)(lunp - &msdp->luns[0]); tran->cbw->dCBWSignature = MSD_CBW_SIGNATURE; - tran->cbw->dCBWTag = ++lunp->msdp->tag; + tran->cbw->dCBWTag = ++msdp->tag; tran->data_processed = 0; /* control phase */ - status = usbhBulkTransfer(&lunp->msdp->epout, tran->cbw, + status = usbhBulkTransfer(&msdp->epout, tran->cbw, sizeof(*tran->cbw), &actual_len, OSAL_MS2I(1000)); if (status == USBH_URBSTATUS_CANCELLED) { - uerr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED"); + uclassdrverr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if ((status != USBH_URBSTATUS_OK) || (actual_len != sizeof(*tran->cbw))) { - uerrf("\tMSD: Control phase: status = %d (!= OK), actual_len = %d (expected to send %d)", + uclassdrverrf("\tMSD: Control phase: status = %d (!= OK), actual_len = %d (expected to send %d)", status, actual_len, sizeof(*tran->cbw)); - _msd_bot_reset(lunp->msdp); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } @@ -322,7 +299,7 @@ static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassSt /* data phase */ data_actual_len = 0; if (tran->cbw->dCBWDataTransferLength) { - usbh_ep_t *const ep = tran->cbw->bmCBWFlags & MSD_CBWFLAGS_D2H ? &lunp->msdp->epin : &lunp->msdp->epout; + usbh_ep_t *const ep = tran->cbw->bmCBWFlags & MSD_CBWFLAGS_D2H ? &msdp->epin : &msdp->epout; status = usbhBulkTransfer( ep, data, @@ -330,62 +307,62 @@ static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassSt &data_actual_len, OSAL_MS2I(20000)); if (status == USBH_URBSTATUS_CANCELLED) { - uerr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED"); + uclassdrverr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if (status == USBH_URBSTATUS_STALL) { - uerrf("\tMSD: Data phase: USBH_URBSTATUS_STALL, clear halt"); + uclassdrverrf("\tMSD: Data phase: USBH_URBSTATUS_STALL, clear halt"); status = (usbhEPReset(ep) == HAL_SUCCESS) ? USBH_URBSTATUS_OK : USBH_URBSTATUS_ERROR; } if (status != USBH_URBSTATUS_OK) { - uerrf("\tMSD: Data phase: status = %d (!= OK), resetting", status); - _msd_bot_reset(lunp->msdp); + uclassdrverrf("\tMSD: Data phase: status = %d (!= OK), resetting", status); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } } /* status phase */ - status = usbhBulkTransfer(&lunp->msdp->epin, &csw, + status = usbhBulkTransfer(&msdp->epin, &csw, sizeof(csw), &actual_len, OSAL_MS2I(1000)); if (status == USBH_URBSTATUS_STALL) { - uwarn("\tMSD: Status phase: USBH_URBSTATUS_STALL, clear halt and retry"); + uclassdrvwarn("\tMSD: Status phase: USBH_URBSTATUS_STALL, clear halt and retry"); - status = (usbhEPReset(&lunp->msdp->epin) == HAL_SUCCESS) ? USBH_URBSTATUS_OK : USBH_URBSTATUS_ERROR; + status = (usbhEPReset(&msdp->epin) == HAL_SUCCESS) ? USBH_URBSTATUS_OK : USBH_URBSTATUS_ERROR; if (status == USBH_URBSTATUS_OK) { - status = usbhBulkTransfer(&lunp->msdp->epin, &csw, + status = usbhBulkTransfer(&msdp->epin, &csw, sizeof(csw), &actual_len, OSAL_MS2I(1000)); } } if (status == USBH_URBSTATUS_CANCELLED) { - uerr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED"); + uclassdrverr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED"); return MSD_BOTRESULT_DISCONNECTED; } if (status != USBH_URBSTATUS_OK) { - uerrf("\tMSD: Status phase: status = %d (!= OK), resetting", status); - _msd_bot_reset(lunp->msdp); + uclassdrverrf("\tMSD: Status phase: status = %d (!= OK), resetting", status); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } /* validate CSW */ if ((actual_len != sizeof(csw)) || (csw.dCSWSignature != MSD_CSW_SIGNATURE) - || (csw.dCSWTag != lunp->msdp->tag) + || (csw.dCSWTag != msdp->tag) || (csw.bCSWStatus >= CSW_STATUS_PHASE_ERROR)) { /* CSW is not valid */ - uerrf("\tMSD: Status phase: Invalid CSW: len=%d, dCSWSignature=%x, dCSWTag=%x (expected %x), bCSWStatus=%d, resetting", + uclassdrverrf("\tMSD: Status phase: Invalid CSW: len=%d, dCSWSignature=%x, dCSWTag=%x (expected %x), bCSWStatus=%d, resetting", actual_len, csw.dCSWSignature, csw.dCSWTag, - lunp->msdp->tag, + msdp->tag, csw.bCSWStatus); - _msd_bot_reset(lunp->msdp); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } @@ -393,17 +370,17 @@ static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassSt if ((csw.bCSWStatus != CSW_STATUS_PHASE_ERROR) && (csw.dCSWDataResidue > tran->cbw->dCBWDataTransferLength)) { /* CSW is not meaningful */ - uerrf("\tMSD: Status phase: CSW not meaningful: bCSWStatus=%d, dCSWDataResidue=%u, dCBWDataTransferLength=%u, resetting", + uclassdrverrf("\tMSD: Status phase: CSW not meaningful: bCSWStatus=%d, dCSWDataResidue=%u, dCBWDataTransferLength=%u, resetting", csw.bCSWStatus, csw.dCSWDataResidue, tran->cbw->dCBWDataTransferLength); - _msd_bot_reset(lunp->msdp); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } if (csw.bCSWStatus == CSW_STATUS_PHASE_ERROR) { - uerr("\tMSD: Status phase: Phase error, resetting"); - _msd_bot_reset(lunp->msdp); + uclassdrverr("\tMSD: Status phase: Phase error, resetting"); + _msd_bot_reset(msdp); return MSD_BOTRESULT_ERROR; } @@ -502,6 +479,9 @@ static msd_result_t scsi_requestsense(USBHMassStorageLUNDriver *lunp, scsi_sense static msd_result_t _scsi_perform_transaction(USBHMassStorageLUNDriver *lunp, msd_transaction_t *transaction, void *data) { + USBHMassStorageDriver *const msdp = lunp->msdp; + (void)msdp; + msd_bot_result_t res; res = _msd_bot_transaction(transaction, lunp, data); if (res != MSD_BOTRESULT_OK) { @@ -511,10 +491,10 @@ static msd_result_t _scsi_perform_transaction(USBHMassStorageLUNDriver *lunp, if (transaction->csw_status == CSW_STATUS_FAILED) { if (transaction->cbw->CBWCB[0] != SCSI_CMD_REQUEST_SENSE) { /* do auto-sense (except for SCSI_CMD_REQUEST_SENSE!) */ - uwarn("\tMSD: Command failed, auto-sense"); + uclassdrvwarn("\tMSD: Command failed, auto-sense"); USBH_DEFINE_BUFFER(scsi_sense_response_t sense); if (scsi_requestsense(lunp, &sense) == MSD_RESULT_OK) { - uwarnf("\tMSD: REQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x", + uclassdrvwarnf("\tMSD: REQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x", sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]); return MSD_RESULT_OK; @@ -724,6 +704,9 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp->msdp != NULL); msd_result_t res; + USBHMassStorageDriver *const msdp = lunp->msdp; + (void)msdp; + chSemWait(&lunp->sem); osalDbgAssert((lunp->state == BLK_READY) || (lunp->state == BLK_ACTIVE), "invalid state"); if (lunp->state == BLK_READY) { @@ -734,7 +717,7 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { { USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq); - uinfo("INQUIRY..."); + uclassdrvinfo("INQUIRY..."); res = scsi_inquiry(lunp, &inq); if (res == MSD_RESULT_DISCONNECTED) { goto failed; @@ -746,9 +729,9 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { goto failed; } - uinfof("\tPDT=%02x", inq.peripheral & 0x1f); + uclassdrvinfof("\tPDT=%02x", inq.peripheral & 0x1f); if (inq.peripheral != 0) { - uerr("\tUnsupported PDT"); + uclassdrverr("\tUnsupported PDT"); goto failed; } } @@ -756,7 +739,7 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { // Test if unit ready uint8_t i; for (i = 0; i < 10; i++) { - uinfo("TEST UNIT READY..."); + uclassdrvinfo("TEST UNIT READY..."); res = scsi_testunitready(lunp); if (res == MSD_RESULT_DISCONNECTED) { goto failed; @@ -764,11 +747,11 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { //retry? goto failed; } else if (res == MSD_RESULT_FAILED) { - uinfo("\tTEST UNIT READY: Command Failed, retry"); + uclassdrvinfo("\tTEST UNIT READY: Command Failed, retry"); osalThreadSleepMilliseconds(200); continue; } - uinfo("\tReady."); + uclassdrvinfo("\tReady."); break; } if (i == 10) goto failed; @@ -776,7 +759,7 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { { USBH_DEFINE_BUFFER(scsi_readcapacity10_response_t cap); // Read capacity - uinfo("READ CAPACITY(10)..."); + uclassdrvinfo("READ CAPACITY(10)..."); res = scsi_readcapacity10(lunp, &cap); if (res == MSD_RESULT_DISCONNECTED) { goto failed; @@ -792,17 +775,17 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { lunp->info.blk_num = __REV(cap.last_block_addr) + 1; } - uinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num, + uclassdrvinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num, (uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL))); - uinfo("MSD Connected."); + uclassdrvinfo("MSD Connected."); lunp->state = BLK_READY; chSemSignal(&lunp->sem); return HAL_SUCCESS; /* Connection failed, state reset to BLK_ACTIVE.*/ failed: - uinfo("MSD Connect failed."); + uclassdrvinfo("MSD Connect failed."); lunp->state = BLK_ACTIVE; chSemSignal(&lunp->sem); return HAL_FAILED; @@ -949,6 +932,10 @@ bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp) { return FALSE; } +USBHDriver *usbhmsdLUNGetHost(const USBHMassStorageLUNDriver *lunp) { + return lunp->msdp->dev->host; +} + static void _msd_object_init(USBHMassStorageDriver *msdp) { osalDbgCheck(msdp != NULL); memset(msdp, 0, sizeof(*msdp)); diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index ca16c66..8c82554 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -31,38 +31,12 @@ #include "usbh/dev/uvc.h" #include "usbh/internal.h" -#if USBHUVC_DEBUG_ENABLE_TRACE -#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define udbgf(f, ...) do {} while(0) -#define udbg(f, ...) do {} while(0) -#endif - -#if USBHUVC_DEBUG_ENABLE_INFO -#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uinfof(f, ...) do {} while(0) -#define uinfo(f, ...) do {} while(0) -#endif - -#if USBHUVC_DEBUG_ENABLE_WARNINGS -#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uwarnf(f, ...) do {} while(0) -#define uwarn(f, ...) do {} while(0) -#endif - -#if USBHUVC_DEBUG_ENABLE_ERRORS -#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__) -#else -#define uerrf(f, ...) do {} while(0) -#define uerr(f, ...) do {} while(0) -#endif - +#define _USBH_DEBUG_HELPER_CLASS_DRIVER uvcdp +#define _USBH_DEBUG_HELPER_ENABLE_TRACE USBHUVC_DEBUG_ENABLE_TRACE +#define _USBH_DEBUG_HELPER_ENABLE_INFO USBHUVC_DEBUG_ENABLE_INFO +#define _USBH_DEBUG_HELPER_ENABLE_WARNINGS USBHUVC_DEBUG_ENABLE_WARNINGS +#define _USBH_DEBUG_HELPER_ENABLE_ERRORS USBHUVC_DEBUG_ENABLE_ERRORS +#include "usbh/debug_helpers.h" USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES]; @@ -124,7 +98,7 @@ bool usbhuvcVSRequest(USBHUVCDriver *uvcdp, static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { if (min_ep_size == 0) { - uinfo("Selecting Alternate setting 0"); + uclassdrvinfo("Selecting Alternate setting 0"); return usbhStdReqSetInterface(uvcdp->dev, if_get(&uvcdp->ivs)->bInterfaceNumber, 0); } @@ -134,7 +108,7 @@ static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { uint8_t alt = 0; uint16_t sz = 0xffff; - uinfof("Searching alternate setting with min_ep_size=%d", min_ep_size); + uclassdrvinfof("Searching alternate setting with min_ep_size=%d", min_ep_size); for (; iif.valid; if_iter_next(&iif)) { const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); @@ -143,7 +117,7 @@ static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { || (ifdesc->bInterfaceSubClass != UVC_SC_VIDEOSTREAMING)) continue; - uinfof("\tScanning alternate setting=%d", ifdesc->bAlternateSetting); + uclassdrvinfof("\tScanning alternate setting=%d", ifdesc->bAlternateSetting); if (ifdesc->bNumEndpoints == 0) continue; @@ -153,11 +127,11 @@ static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { if (((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_ISO) && ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) { - uinfof("\t Endpoint wMaxPacketSize = %d", epdesc->wMaxPacketSize); + uclassdrvinfof("\t Endpoint wMaxPacketSize = %d", epdesc->wMaxPacketSize); if (epdesc->wMaxPacketSize >= min_ep_size) { if (epdesc->wMaxPacketSize < sz) { - uinfo("\t Found new optimal alternate setting"); + uclassdrvinfo("\t Found new optimal alternate setting"); sz = epdesc->wMaxPacketSize; alt = ifdesc->bAlternateSetting; ep = epdesc; @@ -168,7 +142,7 @@ static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { } if (ep && alt) { - uinfof("\tSelecting Alternate setting %d", alt); + uclassdrvinfof("\tSelecting Alternate setting %d", alt); if (usbhStdReqSetInterface(uvcdp->dev, if_get(&uvcdp->ivs)->bInterfaceNumber, alt) == HAL_SUCCESS) { usbhEPObjectInit(&uvcdp->ep_iso, uvcdp->dev, ep); usbhEPSetName(&uvcdp->ep_iso, "UVC[ISO ]"); @@ -180,20 +154,22 @@ static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) { } #if USBH_DEBUG_ENABLE && USBHUVC_DEBUG_ENABLE_INFO -void usbhuvcPrintProbeCommit(const usbh_uvc_ctrl_vs_probecommit_data_t *pc) { +void usbhuvcPrintProbeCommit(USBHUVCDriver *uvcdp, + const usbh_uvc_ctrl_vs_probecommit_data_t *pc) { + (void)uvcdp; //uinfof("UVC: probe/commit data:"); - uinfof("\tbmHint=%04x", pc->bmHint); - uinfof("\tbFormatIndex=%d, bFrameIndex=%d, dwFrameInterval=%u", + uclassdrvinfof("\tbmHint=%04x", pc->bmHint); + uclassdrvinfof("\tbFormatIndex=%d, bFrameIndex=%d, dwFrameInterval=%u", pc->bFormatIndex, pc->bFrameIndex, pc->dwFrameInterval); - uinfof("\twKeyFrameRate=%d, wPFrameRate=%d, wCompQuality=%u, wCompWindowSize=%u", + uclassdrvinfof("\twKeyFrameRate=%d, wPFrameRate=%d, wCompQuality=%u, wCompWindowSize=%u", pc->wKeyFrameRate, pc->wPFrameRate, pc->wCompQuality, pc->wCompWindowSize); - uinfof("\twDelay=%d", pc->wDelay); - uinfof("\tdwMaxVideoFrameSize=%u", pc->dwMaxVideoFrameSize); - uinfof("\tdwMaxPayloadTransferSize=%u", pc->dwMaxPayloadTransferSize); -/* uinfof("\tdwClockFrequency=%u", pc->dwClockFrequency); - uinfof("\tbmFramingInfo=%02x", pc->bmFramingInfo); - uinfof("\tbPreferedVersion=%d, bMinVersion=%d, bMaxVersion=%d", + uclassdrvinfof("\twDelay=%d", pc->wDelay); + uclassdrvinfof("\tdwMaxVideoFrameSize=%u", pc->dwMaxVideoFrameSize); + uclassdrvinfof("\tdwMaxPayloadTransferSize=%u", pc->dwMaxPayloadTransferSize); +/* uclassdrvinfof("\tdwClockFrequency=%u", pc->dwClockFrequency); + uclassdrvinfof("\tbmFramingInfo=%02x", pc->bmFramingInfo); + uclassdrvinfof("\tbPreferedVersion=%d, bMinVersion=%d, bMaxVersion=%d", pc->bPreferedVersion, pc->bMinVersion, pc->bMaxVersion); */ } #endif @@ -214,11 +190,11 @@ static void _post(USBHUVCDriver *uvcdp, usbh_urb_t *urb, memory_pool_t *mp, uint urb->buff = ((usbhuvc_message_data_t *)new_msg)->data; } else { /* couldn't post the message, free the newly allocated buffer */ - uerr("UVC: error, mailbox overrun"); + uurberr("UVC: error, mailbox overrun"); chPoolFreeI(&uvcdp->mp_status, new_msg); } } else { - uerrf("UVC: error, %s pool overrun", mp == &uvcdp->mp_data ? "data" : "status"); + uurberrf("UVC: error, %s pool overrun", mp == &uvcdp->mp_data ? "data" : "status"); } } @@ -230,18 +206,18 @@ static void _cb_int(usbh_urb_t *urb) { if (urb->actualLength >= 2) { _post(uvcdp, urb, &uvcdp->mp_status, USBHUVC_MESSAGETYPE_STATUS); } else { - uerrf("UVC: INT IN, actualLength=%d", urb->actualLength); + uurberrf("UVC: INT IN, actualLength=%d", urb->actualLength); } break; case USBH_URBSTATUS_TIMEOUT: /* the device NAKed */ - udbg("UVC: INT IN no info"); + uurbdbg("UVC: INT IN no info"); break; case USBH_URBSTATUS_DISCONNECTED: case USBH_URBSTATUS_CANCELLED: - uwarn("UVC: INT IN status = DISCONNECTED/CANCELLED, aborting"); + uurbwarn("UVC: INT IN status = DISCONNECTED/CANCELLED, aborting"); return; default: - uerrf("UVC: INT IN error, unexpected status = %d", urb->status); + uurberrf("UVC: INT IN error, unexpected status = %d", urb->status); break; } @@ -254,20 +230,20 @@ static void _cb_iso(usbh_urb_t *urb) { if ((urb->status == USBH_URBSTATUS_DISCONNECTED) || (urb->status == USBH_URBSTATUS_CANCELLED)) { - uwarn("UVC: ISO IN status = DISCONNECTED/CANCELLED, aborting"); + uurbwarn("UVC: ISO IN status = DISCONNECTED/CANCELLED, aborting"); return; } if (urb->status != USBH_URBSTATUS_OK) { - uerrf("UVC: ISO IN error, unexpected status = %d", urb->status); + uurberrf("UVC: ISO IN error, unexpected status = %d", urb->status); } else if (urb->actualLength >= 2) { const uint8_t *const buff = (const uint8_t *)urb->buff; if (buff[0] < 2) { - uerrf("UVC: ISO IN, bHeaderLength=%d", buff[0]); + uurberrf("UVC: ISO IN, bHeaderLength=%d", buff[0]); } else if (buff[0] > urb->actualLength) { - uerrf("UVC: ISO IN, bHeaderLength=%d > actualLength=%d", buff[0], urb->actualLength); + uurberrf("UVC: ISO IN, bHeaderLength=%d > actualLength=%d", buff[0], urb->actualLength); } else { - udbgf("UVC: ISO IN len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d", + uurbdbgf("UVC: ISO IN len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d", urb->actualLength, buff[0], buff[1] & UVC_HDR_FID, @@ -279,7 +255,7 @@ static void _cb_iso(usbh_urb_t *urb) { || (buff[1] & (UVC_HDR_EOF | UVC_HDR_ERR))) { _post(uvcdp, urb, &uvcdp->mp_data, USBHUVC_MESSAGETYPE_DATA); } else { - udbgf("UVC: ISO IN skip: len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d", + uurbdbgf("UVC: ISO IN skip: len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d", urb->actualLength, buff[0], buff[1] & UVC_HDR_FID, @@ -289,7 +265,7 @@ static void _cb_iso(usbh_urb_t *urb) { } } } else if (urb->actualLength > 0) { - uerrf("UVC: ISO IN, actualLength=%d", urb->actualLength); + uurberrf("UVC: ISO IN, actualLength=%d", urb->actualLength); } usbhURBObjectResetI(urb); @@ -327,20 +303,20 @@ bool usbhuvcStreamStart(USBHUVCDriver *uvcdp, uint16_t min_ep_sz) { data_sz = (uvcdp->ep_iso.wMaxPacketSize + sizeof(usbhuvc_message_data_t) + 3) & ~3; datapackets = HAL_USBHUVC_WORK_RAM_SIZE / data_sz; if (datapackets == 0) { - uerr("Not enough work RAM"); + uclassdrverr("Not enough work RAM"); goto failed; } workramsz = datapackets * data_sz; - uinfof("Reserving %u bytes of RAM (%d data packets of %d bytes)", workramsz, datapackets, data_sz); + uclassdrvinfof("Reserving %u bytes of RAM (%d data packets of %d bytes)", workramsz, datapackets, data_sz); if (datapackets > (HAL_USBHUVC_MAX_MAILBOX_SZ - HAL_USBHUVC_STATUS_PACKETS_COUNT)) { - uwarn("Mailbox may overflow, use a larger HAL_USBHUVC_MAX_MAILBOX_SZ. UVC will under-utilize the assigned work RAM."); + uclassdrvwarn("Mailbox may overflow, use a larger HAL_USBHUVC_MAX_MAILBOX_SZ. UVC will under-utilize the assigned work RAM."); } chMBResumeX(&uvcdp->mb); uvcdp->mp_data_buffer = chHeapAlloc(NULL, workramsz); if (uvcdp->mp_data_buffer == NULL) { - uerr("Couldn't reserve RAM"); + uclassdrverr("Couldn't reserve RAM"); goto failed; } @@ -497,7 +473,7 @@ uint32_t usbhuvcEstimateRequiredEPSize(USBHUVCDriver *uvcdp, const uint8_t *form mul = div = 1; } break; default: - uwarn("Unsupported format"); + uclassdrvwarn("Unsupported format"); return 0xffffffff; } @@ -528,7 +504,7 @@ static usbh_baseclassdriver_t *_uvc_load(usbh_device_t *dev, const uint8_t *desc } } - uwarn("Can't alloc UVC driver"); + udevwarn("Can't alloc UVC driver"); /* can't alloc */ return NULL; @@ -553,12 +529,12 @@ alloc_ok: const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); if (ifdesc->bInterfaceClass != UVC_CC_VIDEO) { - uwarnf("Skipping Interface %d (class != UVC_CC_VIDEO)", + udevwarnf("Skipping Interface %d (class != UVC_CC_VIDEO)", ifdesc->bInterfaceNumber); continue; } - uinfof("Interface %d, Alt=%d, Class=UVC_CC_VIDEO, Subclass=%02x", + udevinfof("Interface %d, Alt=%d, Class=UVC_CC_VIDEO, Subclass=%02x", ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting, ifdesc->bInterfaceSubClass); @@ -570,24 +546,24 @@ alloc_ok: } for (cs_iter_init(&ics, (generic_iterator_t *)&iif); ics.valid; cs_iter_next(&ics)) { if (ics.curr[1] != UVC_CS_INTERFACE) { - uwarnf("Unknown descriptor=%02X", ics.curr[1]); + udevwarnf("Unknown descriptor=%02X", ics.curr[1]); continue; } switch (ics.curr[2]) { case UVC_VC_HEADER: - uinfo(" VC_HEADER"); break; + udevinfo(" VC_HEADER"); break; case UVC_VC_INPUT_TERMINAL: - uinfof(" VC_INPUT_TERMINAL, ID=%d", ics.curr[3]); break; + udevinfof(" VC_INPUT_TERMINAL, ID=%d", ics.curr[3]); break; case UVC_VC_OUTPUT_TERMINAL: - uinfof(" VC_OUTPUT_TERMINAL, ID=%d", ics.curr[3]); break; + udevinfof(" VC_OUTPUT_TERMINAL, ID=%d", ics.curr[3]); break; case UVC_VC_SELECTOR_UNIT: - uinfof(" VC_SELECTOR_UNIT, ID=%d", ics.curr[3]); break; + udevinfof(" VC_SELECTOR_UNIT, ID=%d", ics.curr[3]); break; case UVC_VC_PROCESSING_UNIT: - uinfof(" VC_PROCESSING_UNIT, ID=%d", ics.curr[3]); break; + udevinfof(" VC_PROCESSING_UNIT, ID=%d", ics.curr[3]); break; case UVC_VC_EXTENSION_UNIT: - uinfof(" VC_EXTENSION_UNIT, ID=%d", ics.curr[3]); break; + udevinfof(" VC_EXTENSION_UNIT, ID=%d", ics.curr[3]); break; default: - uwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]); + udevwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]); break; } } @@ -598,47 +574,47 @@ alloc_ok: } for (cs_iter_init(&ics, (generic_iterator_t *)&iif); ics.valid; cs_iter_next(&ics)) { if (ics.curr[1] != UVC_CS_INTERFACE) { - uwarnf("Unknown descriptor=%02X", ics.curr[1]); + udevwarnf("Unknown descriptor=%02X", ics.curr[1]); continue; } switch (ics.curr[2]) { case UVC_VS_INPUT_HEADER: - uinfo(" VS_INPUT_HEADER"); break; + udevinfo(" VS_INPUT_HEADER"); break; case UVC_VS_OUTPUT_HEADER: - uinfo(" VS_OUTPUT_HEADER"); break; + udevinfo(" VS_OUTPUT_HEADER"); break; case UVC_VS_STILL_IMAGE_FRAME: - uinfo(" VS_STILL_IMAGE_FRAME"); break; + udevinfo(" VS_STILL_IMAGE_FRAME"); break; case UVC_VS_FORMAT_UNCOMPRESSED: - uinfof(" VS_FORMAT_UNCOMPRESSED, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_UNCOMPRESSED, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FORMAT_MPEG2TS: - uinfof(" VS_FORMAT_MPEG2TS, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_MPEG2TS, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FORMAT_DV: - uinfof(" VS_FORMAT_DV, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_DV, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FORMAT_MJPEG: - uinfof(" VS_FORMAT_MJPEG, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_MJPEG, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FORMAT_FRAME_BASED: - uinfof(" VS_FORMAT_FRAME_BASED, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_FRAME_BASED, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FORMAT_STREAM_BASED: - uinfof(" VS_FORMAT_STREAM_BASED, bFormatIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FORMAT_STREAM_BASED, bFormatIndex=%d", ics.curr[3]); break; case UVC_VS_FRAME_UNCOMPRESSED: - uinfof(" VS_FRAME_UNCOMPRESSED, bFrameIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FRAME_UNCOMPRESSED, bFrameIndex=%d", ics.curr[3]); break; case UVC_VS_FRAME_MJPEG: - uinfof(" VS_FRAME_MJPEG, bFrameIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FRAME_MJPEG, bFrameIndex=%d", ics.curr[3]); break; case UVC_VS_FRAME_FRAME_BASED: - uinfof(" VS_FRAME_FRAME_BASED, bFrameIndex=%d", ics.curr[3]); break; + udevinfof(" VS_FRAME_FRAME_BASED, bFrameIndex=%d", ics.curr[3]); break; case UVC_VS_COLOR_FORMAT: - uinfo(" VS_COLOR_FORMAT"); break; + udevinfo(" VS_COLOR_FORMAT"); break; default: - uwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]); + udevwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]); break; } } break; default: - uwarnf("Unknown video bInterfaceSubClass=%02x", ifdesc->bInterfaceSubClass); + udevwarnf("Unknown video bInterfaceSubClass=%02x", ifdesc->bInterfaceSubClass); break; } @@ -649,7 +625,7 @@ alloc_ok: && ((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_INT) && ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) { /* found VC interrupt endpoint */ - uinfof(" VC Interrupt endpoint; %02x, bInterval=%d", + udevinfof(" VC Interrupt endpoint; %02x, bInterval=%d", epdesc->bEndpointAddress, epdesc->bInterval); usbhEPObjectInit(&uvcdp->ep_int, dev, epdesc); usbhEPSetName(&uvcdp->ep_int, "UVC[INT ]"); @@ -657,16 +633,16 @@ alloc_ok: && ((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_ISO) && ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) { /* found VS isochronous endpoint */ - uinfof(" VS Isochronous endpoint; %02x, bInterval=%d, bmAttributes=%02x", + udevinfof(" VS Isochronous endpoint; %02x, bInterval=%d, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bInterval, epdesc->bmAttributes); } else { /* unknown EP */ - uwarnf(" , bEndpointAddress=%02x, bmAttributes=%02x", + udevwarnf(" , bEndpointAddress=%02x, bmAttributes=%02x", epdesc->bEndpointAddress, epdesc->bmAttributes); } for (cs_iter_init(&ics, &iep); ics.valid; cs_iter_next(&ics)) { - uinfof(" CS_ENDPOINT bLength=%d, bDescriptorType=%02X", + udevinfof(" CS_ENDPOINT bLength=%d, bDescriptorType=%02X", ics.curr[0], ics.curr[1]); } } -- cgit v1.2.3 From 7a57cfe93d3123b6927c6eb886cd60ba60d1605f Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 18:34:31 -0300 Subject: USBH: Fix compilation with HAL_USBH_USE_HUB = false --- os/hal/hal.mk | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/os/hal/hal.mk b/os/hal/hal.mk index cd8420b..ae27ea5 100644 --- a/os/hal/hal.mk +++ b/os/hal/hal.mk @@ -28,10 +28,8 @@ endif ifneq ($(findstring HAL_USE_USBH TRUE,$(HALCONF)),) HALSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/src/hal_usbh.c \ ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_debug.c \ - ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_desciter.c -endif -ifneq ($(findstring HAL_USBH_USE_HUB TRUE,$(HALCONF)),) -HALSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_hub.c + ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_desciter.c \ + ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_hub.c endif ifneq ($(findstring HAL_USBH_USE_MSD TRUE,$(HALCONF)),) HALSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_msd.c -- cgit v1.2.3 From 7c57d8a92488ecbcc7b29c7c9131ec41aceb6c17 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 18:36:18 -0300 Subject: USBH: UVC: improve debug message --- os/hal/src/usbh/hal_usbh_uvc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index 8c82554..3a8b488 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -181,7 +181,8 @@ static void _post(USBHUVCDriver *uvcdp, usbh_urb_t *urb, memory_pool_t *mp, uint usbhuvc_message_base_t *const new_msg = (usbhuvc_message_base_t *)chPoolAllocI(mp); if (new_msg != NULL) { /* allocated the new buffer, now try to post the message to the mailbox */ - if (chMBPostI(&uvcdp->mb, (msg_t)msg) == MSG_OK) { + msg_t r = chMBPostI(&uvcdp->mb, (msg_t)msg); + if (r == MSG_OK) { /* everything OK, complete the missing fields */ msg->type = type; msg->length = urb->actualLength; @@ -189,8 +190,12 @@ static void _post(USBHUVCDriver *uvcdp, usbh_urb_t *urb, memory_pool_t *mp, uint /* change the URB's buffer to the newly allocated one */ urb->buff = ((usbhuvc_message_data_t *)new_msg)->data; } else { + if (r == MSG_RESET) { + uurbwarn("UVC: error, mailbox reset"); + } else { + uurberr("UVC: error, mailbox overrun"); + } /* couldn't post the message, free the newly allocated buffer */ - uurberr("UVC: error, mailbox overrun"); chPoolFreeI(&uvcdp->mp_status, new_msg); } } else { -- cgit v1.2.3 From 938daa12d66b50ddf4f3d4c6cf9bbd244d3840c0 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 18:37:25 -0300 Subject: USBH: MSD: revert report OK on CSW status failure --- os/hal/src/usbh/hal_usbh_msd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index a5fbc9f..081cccb 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -496,8 +496,6 @@ static msd_result_t _scsi_perform_transaction(USBHMassStorageLUNDriver *lunp, if (scsi_requestsense(lunp, &sense) == MSD_RESULT_OK) { uclassdrvwarnf("\tMSD: REQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x", sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]); - - return MSD_RESULT_OK; } } return MSD_RESULT_FAILED; -- cgit v1.2.3 From 0c260638da6dde3896a2fd6c4e3b39ee1a1b12e9 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 18:55:03 -0300 Subject: USBH: Update testhal project to new debugging framework --- .../USB_HOST/.settings/org.eclipse.cdt.core.prefs | 2 +- testhal/STM32/STM32F4xx/USB_HOST/chconf.h | 1 + .../STM32/STM32F4xx/USB_HOST/halconf_community.h | 9 +- testhal/STM32/STM32F4xx/USB_HOST/main.c | 195 ++++++++++++--------- 4 files changed, 115 insertions(+), 92 deletions(-) diff --git a/testhal/STM32/STM32F4xx/USB_HOST/.settings/org.eclipse.cdt.core.prefs b/testhal/STM32/STM32F4xx/USB_HOST/.settings/org.eclipse.cdt.core.prefs index 8ae48ef..bf2ed73 100644 --- a/testhal/STM32/STM32F4xx/USB_HOST/.settings/org.eclipse.cdt.core.prefs +++ b/testhal/STM32/STM32F4xx/USB_HOST/.settings/org.eclipse.cdt.core.prefs @@ -1,6 +1,6 @@ eclipse.preferences.version=1 environment/project/0.1003150841/PATH/delimiter=; environment/project/0.1003150841/PATH/operation=replace -environment/project/0.1003150841/PATH/value=${PATH};D\:\\toolchains\\gcc-arm-none-eabi-8-2018-q4-major-win32\\bin;${PATH};D\:\\toolchains\\gcc-arm-none-eabi-4_9-2014q4-20141203-win32\\bin;D\:\\toolchains\\msys64\\usr\\bin +environment/project/0.1003150841/PATH/value=${PATH};D\:\\toolchains\\gcc-arm-none-eabi-8-2019-q3-update-win32\\bin;D\:\\toolchains\\msys64\\usr\\bin environment/project/0.1003150841/append=true environment/project/0.1003150841/appendContributed=true diff --git a/testhal/STM32/STM32F4xx/USB_HOST/chconf.h b/testhal/STM32/STM32F4xx/USB_HOST/chconf.h index 12c6673..a01a37c 100644 --- a/testhal/STM32/STM32F4xx/USB_HOST/chconf.h +++ b/testhal/STM32/STM32F4xx/USB_HOST/chconf.h @@ -712,3 +712,4 @@ #endif /* CHCONF_H */ /** @} */ + diff --git a/testhal/STM32/STM32F4xx/USB_HOST/halconf_community.h b/testhal/STM32/STM32F4xx/USB_HOST/halconf_community.h index fef417f..c76d1ef 100644 --- a/testhal/STM32/STM32F4xx/USB_HOST/halconf_community.h +++ b/testhal/STM32/STM32F4xx/USB_HOST/halconf_community.h @@ -177,7 +177,7 @@ #define HAL_USBH_PORT_DEBOUNCE_TIME 200 #define HAL_USBH_PORT_RESET_TIMEOUT 500 #define HAL_USBH_DEVICE_ADDRESS_STABILIZATION 20 -#define HAL_USBH_CONTROL_REQUEST_DEFAULT_TIMEOUT OSAL_MS2I(1000) +#define HAL_USBH_CONTROL_REQUEST_DEFAULT_TIMEOUT OSAL_MS2I(1000) /* MSD */ #define HAL_USBH_USE_MSD TRUE @@ -202,7 +202,7 @@ #define HAL_USBHAOA_MAX_INSTANCES 1 /* Uncomment this if you need a filter for AOA devices: - * #define HAL_USBHAOA_FILTER_CALLBACK _try_aoa + * #define HAL_USBHAOA_FILTER_CALLBACK _try_aoa */ #define HAL_USBHAOA_DEFAULT_MANUFACTURER "Diego MFG & Co." #define HAL_USBHAOA_DEFAULT_MODEL "Diego's device" @@ -235,9 +235,10 @@ /* debug */ #define USBH_DEBUG_ENABLE TRUE -#define USBH_DEBUG_USBHD USBHD1 -#define USBH_DEBUG_SD SD2 +#define USBH_DEBUG_MULTI_HOST FALSE +#define USBH_DEBUG_SINGLE_HOST_SELECTION USBHD1 #define USBH_DEBUG_BUFFER 25000 +#define USBH_DEBUG_OUTPUT_CALLBACK usbh_debug_output #define USBH_DEBUG_ENABLE_TRACE FALSE #define USBH_DEBUG_ENABLE_INFO TRUE diff --git a/testhal/STM32/STM32F4xx/USB_HOST/main.c b/testhal/STM32/STM32F4xx/USB_HOST/main.c index c88880b..5efdcf7 100644 --- a/testhal/STM32/STM32F4xx/USB_HOST/main.c +++ b/testhal/STM32/STM32F4xx/USB_HOST/main.c @@ -18,7 +18,7 @@ #include "hal.h" #include "ff.h" #include -#include "usbh/debug.h" /* for usbDbgPuts/usbDbgPrintf */ +#include "usbh/debug.h" /* for _usbh_dbg/_usbh_dbgf */ #define UVC_TO_MSD_PHOTOS_CAPTURE FALSE @@ -85,6 +85,8 @@ static const ShellConfig shell_cfg1 = { static void ThreadTestFTDI(void *p) { (void)p; USBHFTDIPortDriver *const ftdipp = &FTDIPD[0]; + USBHDriver *host = NULL; + (void)host; chRegSetThreadName("FTDI"); @@ -95,7 +97,8 @@ start: chThdSleepMilliseconds(100); } - usbDbgPuts("FTDI: Connected"); + host = usbhftdipGetHost(ftdipp); + _usbh_dbg(host, "FTDI: Connected"); USBHFTDIPortConfig config = { 115200, @@ -112,7 +115,7 @@ start: for(;;) { msg_t m = streamGet(ftdipp); if (m < MSG_OK) { - usbDbgPuts("FTDI: Disconnected"); + _usbh_dbg(host, "FTDI: Disconnected"); goto start; } streamPut(ftdipp, (uint8_t)m); @@ -146,10 +149,10 @@ start: for(;;) { msg_t m = streamGet(ftdipp); if (m < MSG_OK) { - usbDbgPuts("FTDI: Disconnected"); + _usbh_dbg(host, "FTDI: Disconnected"); goto start; } - sdPut(&USBH_DEBUG_SD, (uint8_t)m); + sdPut(&SD2, (uint8_t)m); if (m == 'q') break; } @@ -169,19 +172,19 @@ start: st = chVTGetSystemTimeX(); while (times--) { if (streamWrite(ftdipp, buf, 1024) < 1024) { - usbDbgPuts("FTDI: Disconnected"); + _usbh_dbg(host, "FTDI: Disconnected"); goto start; } bytes -= 1024; } if (bytes) { if (streamWrite(ftdipp, buf, bytes) < bytes) { - usbDbgPuts("FTDI: Disconnected"); + _usbh_dbg(host, "FTDI: Disconnected"); goto start; } } et = chVTGetSystemTimeX(); - usbDbgPrintf("\tRate=%uB/s", (config.speed * 100) / (et - st)); + _usbh_dbgf(host, "\tRate=%uB/s", (config.speed * 100) / (et - st)); } } @@ -189,7 +192,7 @@ start: if (0) { for (;;) { if (streamPut(ftdipp, 'A') != MSG_OK) { - usbDbgPuts("FTDI: Disconnected"); + _usbh_dbg(host, "FTDI: Disconnected"); goto start; } chThdSleepMilliseconds(100); @@ -198,7 +201,7 @@ start: usbhftdipStop(ftdipp); - usbDbgPuts("FTDI: Tests done, restarting in 3s"); + _usbh_dbg(host, "FTDI: Tests done, restarting in 3s"); chThdSleepMilliseconds(3000); goto start; @@ -218,6 +221,8 @@ static void ThreadTestAOA(void *p) { (void)p; USBHAOADriver *const aoap = &USBHAOAD[0]; USBHAOAChannel *const aoacp = &aoap->channel; + USBHDriver *host = NULL; + (void)host; chRegSetThreadName("AOA"); @@ -226,11 +231,12 @@ start: chThdSleepMilliseconds(100); } - usbDbgPuts("AOA: Connected"); + host = usbhaoaGetHost(aoap); + _usbh_dbg(host, "AOA: Connected"); if (usbhaoaGetChannelState(aoap) != USBHAOA_CHANNEL_STATE_READY) { usbhaoaChannelStart(aoap); - usbDbgPuts("AOA: Channel started"); + _usbh_dbg(host, "AOA: Channel started"); } //loopback @@ -238,7 +244,7 @@ start: for(;;) { msg_t m = streamGet(aoacp); if (m < MSG_OK) { - usbDbgPuts("AOA: Disconnected"); + _usbh_dbg(host, "AOA: Disconnected"); goto start; } streamPut(aoacp, (uint8_t)m); @@ -258,19 +264,19 @@ start: st = chVTGetSystemTimeX(); while (times--) { if (streamWrite(aoacp, buf, 1024) < 1024) { - usbDbgPuts("AOA: Disconnected"); + _usbh_dbg(host, "AOA: Disconnected"); goto start; } bytes -= 1024; } if (bytes) { if (streamWrite(aoacp, buf, bytes) < bytes) { - usbDbgPuts("AOA: Disconnected"); + _usbh_dbg(host, "AOA: Disconnected"); goto start; } } et = chVTGetSystemTimeX(); - usbDbgPrintf("\tRate=%uB/s", AOA_WRITE_SPEED_TEST_BYTES / (et - st) * 100); + _usbh_dbgf(host, "\tRate=%uB/s", AOA_WRITE_SPEED_TEST_BYTES / (et - st) * 100); } } @@ -278,7 +284,7 @@ start: if (0) { for (;;) { if (streamPut(aoacp, 'A') != MSG_OK) { - usbDbgPuts("AOA: Disconnected"); + _usbh_dbg(host, "AOA: Disconnected"); goto start; } chThdSleepMilliseconds(100); @@ -287,7 +293,7 @@ start: usbhaoaChannelStop(aoap); - usbDbgPuts("AOA: Tests done, restarting in 3s"); + _usbh_dbg(host, "AOA: Tests done, restarting in 3s"); chThdSleepMilliseconds(3000); goto start; @@ -305,7 +311,7 @@ static FATFS MSDLUN0FS; static uint8_t fbuff[10240]; static FIL file; -static FRESULT scan_files(BaseSequentialStream *chp, char *path) { +static FRESULT scan_files(USBHDriver *host, BaseSequentialStream *chp, char *path) { FRESULT res; DIR dir; UINT i; @@ -321,12 +327,12 @@ static FRESULT scan_files(BaseSequentialStream *chp, char *path) { i = strlen(path); path[i++] = '/'; strcpy(&path[i], fno.fname); - res = scan_files(chp, path); + res = scan_files(host, chp, path); if (res != FR_OK) break; path[--i] = 0; } else { - usbDbgPrintf("FS: %s/%s", path, fno.fname); + _usbh_dbgf(host, "FS: %s/%s", path, fno.fname); } } } @@ -341,11 +347,12 @@ static void ThreadTestMSD(void *p) { FATFS *fsp; DWORD clusters; FRESULT res; + USBHDriver *host = NULL; chRegSetThreadName("MSD"); #if !UVC_TO_MSD_PHOTOS_CAPTURE - BaseSequentialStream * const chp = (BaseSequentialStream *)&USBH_DEBUG_SD; + BaseSequentialStream * const chp = (BaseSequentialStream *)&SD2; systime_t st, et; uint32_t j; #endif @@ -355,14 +362,15 @@ start: chThdSleepMilliseconds(100); if (blkGetDriverState(&MSBLKD[0]) == BLK_ACTIVE) { - usbDbgPuts("BLK: Active, connect...."); + host = usbhmsdLUNGetHost(&MSBLKD[0]); + _usbh_dbg(host, "BLK: Active, connect...."); usbhmsdLUNConnect(&MSBLKD[0]); } if (blkGetDriverState(&MSBLKD[0]) != BLK_READY) { continue; } - usbDbgPuts("BLK: Ready."); + _usbh_dbg(host, "BLK: Ready."); #if !UVC_TO_MSD_PHOTOS_CAPTURE //raw read test @@ -372,7 +380,7 @@ start: #define NITERATIONS ((RAW_READ_SZ_MB * 1024UL * 1024UL) / sizeof(fbuff)) uint32_t start = 0; chThdSetPriority(HIGHPRIO); - usbDbgPrintf("BLK: Raw read test (%dMB, %dB blocks)", RAW_READ_SZ_MB, sizeof(fbuff)); + _usbh_dbgf(host, "BLK: Raw read test (%dMB, %dB blocks)", RAW_READ_SZ_MB, sizeof(fbuff)); st = chVTGetSystemTime(); for (j = 0; j < NITERATIONS; j++) { if (blkRead(&MSBLKD[0], start, fbuff, NBLOCKS) != HAL_SUCCESS) @@ -380,29 +388,29 @@ start: start += NBLOCKS; } et = chVTGetSystemTime(); - usbDbgPrintf("BLK: Raw read in %d ms, %dkB/s", + _usbh_dbgf(host, "BLK: Raw read in %d ms, %dkB/s", et - st, (RAW_READ_SZ_MB * 1024UL * 1000) / (et - st)); chThdSetPriority(NORMALPRIO); } #endif - usbDbgPuts("FS: Block driver ready, try mount..."); + _usbh_dbg(host, "FS: Block driver ready, try mount..."); res = f_mount(&MSDLUN0FS, FATFSDEV_MSD_DRIVE, 1); if (res != FR_OK) { - usbDbgPuts("FS: Can't mount. Check file system."); + _usbh_dbg(host, "FS: Can't mount. Check file system."); continue; } - usbDbgPuts("FS: Mounted."); + _usbh_dbg(host, "FS: Mounted."); res = f_getfree(FATFSDEV_MSD_DRIVE, &clusters, &fsp); if (res != FR_OK) { - usbDbgPuts("FS: f_getfree() failed"); + _usbh_dbg(host, "FS: f_getfree() failed"); continue; } - usbDbgPrintf("FS: %lu free clusters, %lu sectors per cluster, %lu bytes free", + _usbh_dbgf(host, "FS: %lu free clusters, %lu sectors per cluster, %lu bytes free", clusters, (uint32_t)MSDLUN0FS.csize, clusters * (uint32_t)MSDLUN0FS.csize * MSBLKD[0].info.blk_size); @@ -419,7 +427,7 @@ start: //write test if (1) { - usbDbgPuts("FS: Write test (create file /test.dat, 1MB)"); + _usbh_dbg(host, "FS: Write test (create file /test.dat, 1MB)"); f_open(&file, FATFSDEV_MSD_DRIVE "/test.dat", FA_CREATE_ALWAYS | FA_WRITE); src = start; st = chVTGetSystemTime(); @@ -431,7 +439,7 @@ start: src = start; } et = chVTGetSystemTime(); - usbDbgPrintf("FS: Written 1MB in %d ms, %dkB/s", + _usbh_dbgf(host, "FS: Written 1MB in %d ms, %dkB/s", et - st, (1024UL*1000) / (et - st)); f_close(&file); @@ -439,7 +447,7 @@ start: //read test if (1) { - usbDbgPuts("FS: Read test (read file /test.dat, 1MB, compare)"); + _usbh_dbg(host, "FS: Read test (read file /test.dat, 1MB, compare)"); f_open(&file, FATFSDEV_MSD_DRIVE "/test.dat", FA_READ); src = start; st = chVTGetSystemTime(); @@ -447,7 +455,7 @@ start: if (f_read(&file, fbuff, 512, &bw) != FR_OK) goto start; if (memcmp(src, fbuff, bw)) { - usbDbgPrintf("Compare error @%08x", (uint32_t)src); + _usbh_dbgf(host, "Compare error @%08x", (uint32_t)src); goto start; } src += bw; @@ -455,7 +463,7 @@ start: src = start; } et = chVTGetSystemTime(); - usbDbgPrintf("FS: Read 1MB in %d ms, %dkB/s", + _usbh_dbgf(host, "FS: Read 1MB in %d ms, %dkB/s", et - st, (1024UL*1000) / (et - st)); f_close(&file); @@ -463,14 +471,14 @@ start: //scan files test if (1) { - usbDbgPuts("FS: Scan files test"); + _usbh_dbg(host, "FS: Scan files test"); strcpy((char *)fbuff, FATFSDEV_MSD_DRIVE); - scan_files(chp, (char *)fbuff); + scan_files(host, chp, (char *)fbuff); } } #endif - usbDbgPuts("FS: Tests done, restarting in 3s"); + _usbh_dbg(host, "FS: Tests done, restarting in 3s"); chThdSleepMilliseconds(3000); goto start; @@ -488,12 +496,12 @@ static void _hid_report_callback(USBHHIDDriver *hidp, uint16_t len) { uint8_t *report = (uint8_t *)hidp->config->report_buffer; if (hidp->type == USBHHID_DEVTYPE_BOOT_MOUSE) { - usbDbgPrintf("Mouse report: buttons=%02x, Dx=%d, Dy=%d", + _usbh_dbgf(hidp->dev->host, "Mouse report: buttons=%02x, Dx=%d, Dy=%d", report[0], (int8_t)report[1], (int8_t)report[2]); } else if (hidp->type == USBHHID_DEVTYPE_BOOT_KEYBOARD) { - usbDbgPrintf("Keyboard report: modifier=%02x, keys=%02x %02x %02x %02x %02x %02x", + _usbh_dbgf(hidp->dev->host, "Keyboard report: modifier=%02x, keys=%02x %02x %02x %02x %02x %02x", report[0], report[2], report[3], @@ -502,7 +510,7 @@ static void _hid_report_callback(USBHHIDDriver *hidp, uint16_t len) { report[6], report[7]); } else { - usbDbgPrintf("Generic report, %d bytes", len); + _usbh_dbgf(hidp->dev->host, "Generic report, %d bytes", len); } } @@ -525,21 +533,22 @@ static void ThreadTestHID(void *p) { for (;;) { for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) { - if (usbhhidGetState(&USBHHIDD[i]) == USBHHID_STATE_ACTIVE) { - usbDbgPrintf("HID: Connected, HID%d", i); - usbhhidStart(&USBHHIDD[i], &hidcfg[i]); - if (usbhhidGetType(&USBHHIDD[i]) != USBHHID_DEVTYPE_GENERIC) { - usbhhidSetIdle(&USBHHIDD[i], 0, 0); + USBHHIDDriver *const hidp = &USBHHIDD[i]; + if (usbhhidGetState(hidp) == USBHHID_STATE_ACTIVE) { + _usbh_dbgf(hidp->dev->host, "HID: Connected, HID%d", i); + usbhhidStart(hidp, &hidcfg[i]); + if (usbhhidGetType(hidp) != USBHHID_DEVTYPE_GENERIC) { + usbhhidSetIdle(hidp, 0, 0); } kbd_led_states[i] = 1; - } else if (usbhhidGetState(&USBHHIDD[i]) == USBHHID_STATE_READY) { - if (usbhhidGetType(&USBHHIDD[i]) == USBHHID_DEVTYPE_BOOT_KEYBOARD) { + } else if (usbhhidGetState(hidp) == USBHHID_STATE_READY) { + if (usbhhidGetType(hidp) == USBHHID_DEVTYPE_BOOT_KEYBOARD) { USBH_DEFINE_BUFFER(uint8_t val); val = kbd_led_states[i] << 1; if (val == 0x08) { val = 1; } - usbhhidSetReport(&USBHHIDD[i], 0, USBHHID_REPORTTYPE_OUTPUT, &val, 1); + usbhhidSetReport(hidp, 0, USBHHID_REPORTTYPE_OUTPUT, &val, 1); kbd_led_states[i] = val; } } @@ -637,12 +646,12 @@ static void ThreadTestUVC(void *p) { if (usbhuvcGetState(&USBHUVCD[0]) != USBHUVC_STATE_ACTIVE) continue; - usbDbgPuts("UVC: Webcam connected"); + _usbh_dbg(uvcdp->dev->host, "UVC: Webcam connected"); /* ************************************ */ /* Find best configuration */ /* ************************************ */ - usbDbgPuts("UVC: Find best configuration"); + _usbh_dbg(uvcdp->dev->host, "UVC: Find best configuration"); generic_iterator_t ics; const usbh_uvc_format_mjpeg_t *format; @@ -658,7 +667,7 @@ static void ThreadTestUVC(void *p) { goto failed; format = (const usbh_uvc_format_mjpeg_t *)ics.curr; - usbDbgPrintf("\tSelect bFormatIndex=%d", format->bFormatIndex); + _usbh_dbgf(uvcdp->dev->host, "\tSelect bFormatIndex=%d", format->bFormatIndex); //find the most suitable frame (largest one within the bandwidth requirements) if (usbhuvcFindVSDescriptor(uvcdp, &ics, UVC_VS_FRAME_MJPEG, TRUE) != HAL_SUCCESS) @@ -668,18 +677,18 @@ static void ThreadTestUVC(void *p) { const usbh_uvc_frame_mjpeg_t *const frame = (usbh_uvc_frame_mjpeg_t *)ics.curr; uint32_t frame_sz = frame->wWidth * frame->wHeight; - usbDbgPrintf("\t\tbFrameIndex=%d", frame->bFrameIndex); - usbDbgPrintf("\t\t\twWidth=%d, wHeight=%d", frame->wWidth, frame->wHeight); - usbDbgPrintf("\t\t\tdwMinBitRate=%u, dwMaxBitRate=%u", frame->dwMinBitRate, frame->dwMaxBitRate); - usbDbgPrintf("\t\t\tdwMaxVideoFrameBufferSize=%u", frame->dwMaxVideoFrameBufferSize); - usbDbgPrintf("\t\t\tdwDefaultFrameInterval=%u", frame->dwDefaultFrameInterval); + _usbh_dbgf(uvcdp->dev->host, "\t\tbFrameIndex=%d", frame->bFrameIndex); + _usbh_dbgf(uvcdp->dev->host, "\t\t\twWidth=%d, wHeight=%d", frame->wWidth, frame->wHeight); + _usbh_dbgf(uvcdp->dev->host, "\t\t\tdwMinBitRate=%u, dwMaxBitRate=%u", frame->dwMinBitRate, frame->dwMaxBitRate); + _usbh_dbgf(uvcdp->dev->host, "\t\t\tdwMaxVideoFrameBufferSize=%u", frame->dwMaxVideoFrameBufferSize); + _usbh_dbgf(uvcdp->dev->host, "\t\t\tdwDefaultFrameInterval=%u", frame->dwDefaultFrameInterval); uint8_t j; for (j = 0; j < frame->bFrameIntervalType; j++) { uint32_t ep_sz = usbhuvcEstimateRequiredEPSize(uvcdp, (const uint8_t *)format, (const uint8_t *)frame, frame->dwFrameInterval[j]); - usbDbgPrintf("\t\t\tdwFrameInterval=%u, estimated EP size=%u", frame->dwFrameInterval[j], ep_sz); + _usbh_dbgf(uvcdp->dev->host, "\t\t\tdwFrameInterval=%u, estimated EP size=%u", frame->dwFrameInterval[j], ep_sz); if (ep_sz > 310) continue; @@ -697,7 +706,7 @@ static void ThreadTestUVC(void *p) { if (ep_sz < min_ep_sz) { /* new best bitrate */ min_ep_sz = ep_sz; - usbDbgPuts("\t\t\tNew best candidate found"); + _usbh_dbg(uvcdp->dev->host, "\t\t\tNew best candidate found"); best_frame_interval_index = j; best_frame = frame; } @@ -706,14 +715,14 @@ static void ThreadTestUVC(void *p) { failed: if (best_frame == NULL) { - usbDbgPuts("\t\t\tCouldn't find suitable format/frame"); + _usbh_dbg(uvcdp->dev->host, "\t\t\tCouldn't find suitable format/frame"); continue; } /* ************************************ */ /* NEGOTIATION */ /* ************************************ */ - usbDbgPuts("UVC: Start negotiation"); + _usbh_dbg(uvcdp->dev->host, "UVC: Start negotiation"); usbhuvcResetPC(uvcdp); usbh_uvc_ctrl_vs_probecommit_data_t *const pc = usbhuvcGetPC(uvcdp); @@ -723,42 +732,42 @@ failed: pc->bFrameIndex = best_frame->bFrameIndex; pc->dwFrameInterval = best_frame->dwFrameInterval[best_frame_interval_index]; - usbDbgPrintf("\tFirst probe, selecting bFormatIndex=%d, bFrameIndex=%d, dwFrameInterval=%u", + _usbh_dbgf(uvcdp->dev->host, "\tFirst probe, selecting bFormatIndex=%d, bFrameIndex=%d, dwFrameInterval=%u", pc->bFormatIndex, pc->bFrameIndex, pc->dwFrameInterval); - usbDbgPuts("SET_CUR (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc); + _usbh_dbg(uvcdp->dev->host, "SET_CUR (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc); if (usbhuvcProbe(uvcdp) != HAL_SUCCESS) { - usbDbgPuts("\tFirst probe failed"); + _usbh_dbg(uvcdp->dev->host, "\tFirst probe failed"); continue; } - usbDbgPuts("GET_CUR (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc); - usbDbgPuts("GET_MIN (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc_min); - usbDbgPuts("GET_MAX (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc_max); + _usbh_dbg(uvcdp->dev->host, "GET_CUR (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc); + _usbh_dbg(uvcdp->dev->host, "GET_MIN (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc_min); + _usbh_dbg(uvcdp->dev->host, "GET_MAX (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc_max); pc->bmHint = 0x0001; pc->wCompQuality = uvcdp->pc_min.wCompQuality; - usbDbgPuts("SET_CUR (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc); - usbDbgPrintf("\tSecond probe, selecting wCompQuality=%d", pc->wCompQuality); + _usbh_dbg(uvcdp->dev->host, "SET_CUR (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc); + _usbh_dbgf(uvcdp->dev->host, "\tSecond probe, selecting wCompQuality=%d", pc->wCompQuality); if (usbhuvcProbe(uvcdp) != HAL_SUCCESS) { - usbDbgPuts("\tSecond probe failed"); + _usbh_dbg(uvcdp->dev->host, "\tSecond probe failed"); continue; } - usbDbgPuts("GET_CUR (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc); - usbDbgPuts("GET_MIN (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc_min); - usbDbgPuts("GET_MAX (PROBE):"); usbhuvcPrintProbeCommit(&uvcdp->pc_max); + _usbh_dbg(uvcdp->dev->host, "GET_CUR (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc); + _usbh_dbg(uvcdp->dev->host, "GET_MIN (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc_min); + _usbh_dbg(uvcdp->dev->host, "GET_MAX (PROBE):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc_max); /* ************************************ */ /* Commit negotiated parameters */ /* ************************************ */ - usbDbgPuts("UVC: Commit negotiated parameters"); - usbDbgPuts("SET_CUR (COMMIT):"); usbhuvcPrintProbeCommit(&uvcdp->pc); + _usbh_dbg(uvcdp->dev->host, "UVC: Commit negotiated parameters"); + _usbh_dbg(uvcdp->dev->host, "SET_CUR (COMMIT):"); usbhuvcPrintProbeCommit(uvcdp, &uvcdp->pc); if (usbhuvcCommit(uvcdp) != HAL_SUCCESS) { - usbDbgPuts("\tCommit failed"); + _usbh_dbg(uvcdp->dev->host, "\tCommit failed"); continue; } - usbDbgPuts("UVC: Ready to start streaming"); + _usbh_dbg(uvcdp->dev->host, "UVC: Ready to start streaming"); uint32_t npackets = 0; uint32_t payload = 0; @@ -774,7 +783,7 @@ failed: msg_t msg, ret; ret = usbhuvcLockAndFetch(uvcdp, &msg, TIME_INFINITE); if (ret == MSG_RESET) { - usbDbgPuts("UVC: Driver is unloading"); + _usbh_dbg(uvcdp->dev->host, "UVC: Driver is unloading"); break; } else if (ret == MSG_TIMEOUT) { continue; @@ -784,7 +793,7 @@ failed: usbhuvc_message_data_t *const data = (usbhuvc_message_data_t *)msg; if (data->length < data->data[0]) { - usbDbgPrintf("UVC: Length error!"); + _usbh_dbgf(uvcdp->dev->host, "UVC: Length error!"); goto free_data; } @@ -815,20 +824,20 @@ failed: chsnprintf(fn, sizeof(fn), "/img%d.jpg", frame); if (f_open(&fp, fn, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { if (with_dht && f_write(&fp, jpeg_header_plus_dht, sizeof(jpeg_header_plus_dht), &bw) != FR_OK) { - usbDbgPuts("UVC->MSD: File write error"); + _usbh_dbg(uvcdp->dev->host, "UVC->MSD: File write error"); f_close(&fp); state = 0; } state = 2; } else { - usbDbgPuts("UVC->MSD: File open error"); + _usbh_dbg(uvcdp->dev->host, "UVC->MSD: File open error"); state = 0; } } if (state == 2) { if (f_write(&fp, message_data, message_payload, &bw) != FR_OK) { - usbDbgPuts("UVC->MSD: File write error"); + _usbh_dbg(uvcdp->dev->host, "UVC->MSD: File write error"); f_close(&fp); state = 0; } @@ -837,7 +846,7 @@ failed: check_eof: #endif if (data->data[1] & UVC_HDR_EOF) { - usbDbgPrintf("UVC: FRAME #%d, delta=%03dticks, #packets=%d, useful_payload=%dbytes, total=%dbytes", + _usbh_dbgf(uvcdp->dev->host, "UVC: FRAME #%d, delta=%03dticks, #packets=%d, useful_payload=%dbytes, total=%dbytes", frame, data->timestamp - last , npackets, payload, total); last = data->timestamp; npackets = 0; @@ -856,17 +865,17 @@ free_data: const uint8_t *const stat = status->data; switch (stat[0] & 0x0f) { case 1: - usbDbgPrintf("UVC: STATUS Control event, " + _usbh_dbgf(uvcdp->dev->host, "UVC: STATUS Control event, " "bOriginator=%d, bEvent=%d, bSelector=%d, bAttribute=%d", stat[1], stat[2], stat[3], stat[4]); break; case 2: - usbDbgPrintf("UVC: STATUS Streaming event, " + _usbh_dbgf(uvcdp->dev->host, "UVC: STATUS Streaming event, " "bOriginator=%d, bEvent=%d, bValue=%d", stat[1], stat[2], stat[3]); break; default: - usbDbgPrintf("UVC: STATUS unknown status report = %d", stat[0]); + _usbh_dbgf(uvcdp->dev->host, "UVC: STATUS unknown status report = %d", stat[0]); break; } usbhuvcFreeStatusMessage(uvcdp, status); @@ -879,6 +888,16 @@ free_data: } #endif +#if USBH_DEBUG_MULTI_HOST +void USBH_DEBUG_OUTPUT_CALLBACK(USBHDriver *host, const uint8_t *buff, size_t len) { + (void)host; +#else +void USBH_DEBUG_OUTPUT_CALLBACK(const uint8_t *buff, size_t len) { +#endif + sdWrite(&SD2, buff, len); + sdWrite(&SD2, (const uint8_t *)"\r\n", 2); +} + int main(void) { IWDG->KR = 0x5555; @@ -928,9 +947,11 @@ int main(void) { //start #if STM32_USBH_USE_OTG1 usbhStart(&USBHD1); + _usbh_dbgf(&USBHD1, "Started"); #endif #if STM32_USBH_USE_OTG2 usbhStart(&USBHD2); + _usbh_dbgf(&USBHD2, "Started"); #endif for(;;) { -- cgit v1.2.3 From 77021bb6466f731a572985cebe65d139c212d88d Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 30 Sep 2019 17:47:30 -0300 Subject: USBH: add helper macros to MSD, FTDI, AOA --- os/hal/include/usbh/dev/aoa.h | 1 + os/hal/include/usbh/dev/ftdi.h | 2 +- os/hal/include/usbh/dev/msd.h | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/os/hal/include/usbh/dev/aoa.h b/os/hal/include/usbh/dev/aoa.h index 8205dd5..1f36370 100644 --- a/os/hal/include/usbh/dev/aoa.h +++ b/os/hal/include/usbh/dev/aoa.h @@ -130,6 +130,7 @@ typedef bool (*usbhaoa_filter_callback_t)(usbh_device_t *dev, const uint8_t *des #define usbhaoaGetState(aoap) ((aoap)->state) #define usbhaoaGetChannelState(aoap) ((aoap)->channel.state) +#define usbhaoaGetHost(aoap) ((aoap)->dev->host) /*===========================================================================*/ /* External declarations. */ diff --git a/os/hal/include/usbh/dev/ftdi.h b/os/hal/include/usbh/dev/ftdi.h index 84ea4bc..fdd767d 100644 --- a/os/hal/include/usbh/dev/ftdi.h +++ b/os/hal/include/usbh/dev/ftdi.h @@ -127,7 +127,7 @@ struct USBHFTDIDriver { /* Driver macros. */ /*===========================================================================*/ #define usbhftdipGetState(ftdipp) ((ftdipp)->state) - +#define usbhftdipGetHost(ftdipp) ((ftdipp)->ftdip->dev->host) /*===========================================================================*/ /* External declarations. */ diff --git a/os/hal/include/usbh/dev/msd.h b/os/hal/include/usbh/dev/msd.h index b245bfc..113f523 100644 --- a/os/hal/include/usbh/dev/msd.h +++ b/os/hal/include/usbh/dev/msd.h @@ -72,7 +72,6 @@ struct USBHMassStorageLUNDriver { /* Driver macros. */ /*===========================================================================*/ - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -95,6 +94,8 @@ extern "C" { bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip); bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp); + + USBHDriver *usbhmsdLUNGetHost(const USBHMassStorageLUNDriver *lunp); #ifdef __cplusplus } #endif -- cgit v1.2.3